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 5cbfc09fe76804461d5bf2221d8a6e5ceff5c385..f056dab7dd084aec5ebcf1a5adce4037b872c297 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 0000000000000000000000000000000000000000..fee00f5b2752038b901bebaa5e0e7d9aa70b9b36 --- /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 0000000000000000000000000000000000000000..5c1eb94be6a1cc3ca1af5de942a83dc0115c0d0a --- /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 0000000000000000000000000000000000000000..c4934c38982b43c209ba83065381684b4f624e36 --- /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 0000000000000000000000000000000000000000..ab30ddf4175e43ed66fb5c2965bebc4af9f7237d --- /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 0000000000000000000000000000000000000000..2032301327f479986cbd14c81ffd40180bce196f --- /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 0000000000000000000000000000000000000000..ddf5fc6833fb003add1e2ab546cd73d133014c96 --- /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 diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md index 23fec84fb65e3b19b6bc650b6e862744c1cd6099..2ec957a52b4e1f37aa5beb3f4f57a14edeac45a5 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 diff --git a/AUTHORS b/AUTHORS index 95d3158d204ff0cc73238867aeba27e0d70b0e34..1a4a57bae7aa3a0f3ce0ed05bf556e0f8512560b 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 @@ -262,6 +263,7 @@ Casey Callendrello Casey Marshall Cezar Sá Espinola ChaiShushan +Chaoqun Han Charles Fenwick Elliott Charles L. Dorian Charles Lee @@ -817,6 +819,7 @@ Lehner Florian Leigh McCulloch Leo Antunes Leon Klingele +Leonard Wang Leonel Quinteros Lev Shamardin Lewin Bormann @@ -1015,6 +1018,7 @@ Nathan Youngman Nathaniel Cook Naveen Kumar Sangi Neelesh Chandola +Neil Alexander Neil Lyons Netflix, Inc. Neuman Vong @@ -1477,8 +1481,10 @@ Zemanta d.o.o. Zev Goldstein Zheng Dayu Zhongtao Chen +Zhou Guangyuan Zhou Peng Ziad Hatahet +Zizhao Zhang Zorion Arrizabalaga Максим Федосеев Роман Хавроненко diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 1984d44c53773624a686c0af48bc1055d4fb0e5a..e2e102f61001f322eb6fc1bb06ee0f9a1bbe6cdf 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 @@ -475,6 +476,7 @@ ChaiShushan Changkun Ou Channing Kimble-Brown Chao Xu +Chaoqun Han Charles Fenwick Elliott Charles Kenney Charles L. Dorian @@ -1109,7 +1111,6 @@ Ian Lance Taylor Ian Leue Ian Mckay Ian Tay -Ian Woolf Ian Zapolsky Ibrahim AshShohail Icarus Sparry @@ -1570,7 +1571,7 @@ Leigh McCulloch Leo Antunes Leo Rudberg Leon Klingele -Leonard Wang +Leonard Wang Leonardo Comelli Leonel Quinteros Lev Shamardin @@ -1902,6 +1903,7 @@ Naveen Kumar Sangi Neeilan Selvalingam Neelesh Chandola Nehal J Wani +Neil Alexander Neil Lyons Neuman Vong Neven Sajko @@ -2746,9 +2748,11 @@ Zhengyu He Zhongpeng Lin Zhongtao Chen Zhongwei Yao +Zhou Guangyuan Zhou Peng Ziad Hatahet Ziheng Liu +Zizhao Zhang Zorion Arrizabalaga Zvonimir Pavlinovic Zyad A. Ali diff --git a/README.md b/README.md index 837734b6e574bfd1f3c99d2a8a4845e58534dbb8..5aca9587fa47e81c13207d036f8b1864f9a65db4 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 diff --git a/VERSION b/VERSION index dd2329269cab0d37fac9f13bc5fd73172f7a9abb..c0e21676a3f5a726ca5fe461e54b58473da7437a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -go1.17 \ No newline at end of file +go1.18beta1 \ No newline at end of file diff --git a/api/except.txt b/api/except.txt index 14fe7785fa54d3bc2a484c992113edf1d13c2d1f..b9972c121cfa4addbfdbfe82644b567745da846e 100644 --- a/api/except.txt +++ b/api/except.txt @@ -492,6 +492,7 @@ pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uin pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr pkg syscall (windows-amd64), type RawSockaddrAny struct, Pad [96]int8 pkg testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M +pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalExample) *M pkg testing, func RegisterCover(Cover) pkg text/scanner, const GoTokens = 1012 pkg text/template/parse, type DotNode bool diff --git a/api/go1.1.txt b/api/go1.1.txt index 81d095704a4c9c58625d72376e4c77724dd8c957..bb00b3b02cc8ad8fffcd32f4df04df67c30cbce8 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 48505381f1e41f961684e0df5f68b74b7766d902..ca2cd162f8bc8e9359bf8e886dfb42c6dc9c052d 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.18.txt b/api/go1.18.txt new file mode 100644 index 0000000000000000000000000000000000000000..afcb31c63806901706cd51cc18c68ef682fee32a --- /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/go1.9.txt b/api/go1.9.txt index c23a17ea1a39491822283aa30de439301b5ffc0f..87fae57920d2f6bcbec78ffe79913639bd7c6252 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/codereview.cfg b/codereview.cfg index 9d5ebe82eb1ff710dd454dc32286d12b61258f7e..77a74f108eae362626abcdbfcf41ddb9a33b02cd 100644 --- a/codereview.cfg +++ b/codereview.cfg @@ -1,2 +1 @@ -branch: release-branch.go1.17 -parent-branch: master +branch: master diff --git a/doc/asm.html b/doc/asm.html index 51f85eb94822a4a900bfbb205f5cbcc709e5a2f8..f7787a4076ce600dbce55eef8b1dbdccdf2898c5 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

diff --git a/doc/go1.17.html b/doc/go1.17.html deleted file mode 100644 index c1b5ab3f6fba73d3eb37b93ebd20420e3de4109b..0000000000000000000000000000000000000000 --- 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.17_spec.html b/doc/go1.17_spec.html new file mode 100644 index 0000000000000000000000000000000000000000..0b374e7bfb2a938ec2cd6749a1aea12d2a8a5583 --- /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. +

diff --git a/doc/go1.18.html b/doc/go1.18.html new file mode 100644 index 0000000000000000000000000000000000000000..5ab40280b571ea6b0a13dbc1bf7367bfd14fd90b --- /dev/null +++ b/doc/go1.18.html @@ -0,0 +1,862 @@ + + + + + + +

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

+ +

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 syntax for + Function and + type declarations + 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 + 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. +
  • +
  • + 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

+ +

+ 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. +

+ +

+ 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. +

+ +

Ports

+ +

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. +

+ +

RISC-V

+ +

+ The 64-bit RISC-V architecture on Linux (the linux/riscv64 port) + 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

+ +

+ 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. +

+ +

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

+ +

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

+ +

+ 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. +

+ +

+ The go command now embeds version control information in + 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. +

+ +

+ 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. +

+ +

+ 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. +

+ +

+ 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.) +

+ +

+ 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

+ +

+ 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. +

+ +

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)
+}
+

+ +

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

+ +

+ 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. +

+ +

+ 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

+ +

+ 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 + typical 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. +

+ +

+ The compiler now can inline functions that contain range loops or + labeled for loops. +

+ +

+ The new compiler -asan option supports the + new go command -asan option. +

+ +

+ 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

+ +

+ The new linker -asan option supports the + new go command -asan option. +

+ +

Core library

+ +

New constraints 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

+ +

+ The new net/netip + 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. +

+

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

+

+ 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. +

+ +

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. +

+ +
bufio
+
+

+ 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. +

+ +

+ The methods Reader.Reset and + Writer.Reset + now use the default buffer size when called on objects with a + nil buffer. +

+
+
+ +
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 + small ASCII cutsets, up to 10 times faster. +

+ +

+ 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. +

+
+
+ +
crypto/tls
+
+

+ The new Conn.NetConn + method allows access to the underlying + net.Conn. +

+
+
+ +
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. +

+
+
+ +
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
+
+

+ The new Kind.String + method returns a human-readable name for the receiver kind. +

+
+
+ +
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 + . +

+
+
+ +
go/types
+
+

+ The new Config.GoVersion + field sets the accepted Go language version. +

+ +

+ 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 are added to represent a type parameter. +
  • +
  • + The new type + TypeParamList holds a list of + type parameters. +
  • +
  • + The new type + TypeList holds 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 simultaneously 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 are 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 are added to represent an error related to a type argument. +
  • +
  • + The new type Context and factory function + NewContext + are added to facilitate sharing of identical type instances across type-checked packages. +
  • +
+
+
+ +
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. +

+
+
+ +
net
+
+

+ net.Error.Temporary has been deprecated. +

+
+
+ +
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. +

+ +

+ The new + Cookie.Valid + method reports whether the cookie is valid. +

+
+
+ +
os/user
+
+

+ User.GroupIds. + now uses a Go native implementation when cgo is not available. +

+
+
+ +
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. +

+ +

+ 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). +

+ +

+ 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. +

+ +

+ A number of methods ( + Value.CanInt, + Value.CanUint, + Value.CanFloat, + Value.CanComplex + ) + have been added to + Value + to test if a conversion is safe. +

+ +

+ Value.FieldByIndexErr + has been added to avoid the panic that occurs in + 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. +

+
+
+ +
regexp
+
+

+ regexp + now treats each invalid byte of a UTF-8 string as U+FFFD. +

+
+
+ +
strconv
+
+

+ strconv.Unquote + now rejects Unicode surrogate halves. +

+
+
+ +
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 + the input string's memory. +

+ +

+ Trim, TrimLeft, + and TrimRight are now allocation free and, especially for + small ASCII cutsets, up to 10 times faster. +

+ +

+ 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. +

+
+
+ +
sync
+
+

+ The new methods + Mutex.TryLock, + RWMutex.TryLock, and + RWMutex.TryRLock, + will acquire the lock if it is not currently held. +

+
+
+ +
syscall
+
+

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

+ +

+ SysProcAttr.Pdeathsig. + is now supported in FreeBSD. +

+
+
+ +
syscall/js
+
+

+ Wrapper interface has been removed. +

+
+
+ +
testing
+
+

+ 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). +

+ +

+ 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. +

+
+
+ +
text/template
+
+

+ 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. +

+
+
+ +
unicode/utf8
+
+

+ The AppendRune function appends the UTF-8 new + encoding of a rune to a []byte. +

+
+
diff --git a/doc/go_spec.html b/doc/go_spec.html index fd5fee46eb220c1111d8aa33853037f751d4bdbb..cb57aa301cbf4430b5414f0b85805f5a0e92a3ae 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,9 +1,16 @@ +

Earlier version

+ +

+For the pre-Go1.18 specification without generics support see +The Go Programming Language Specification. +

+

Introduction

@@ -258,7 +265,7 @@ continue for import return var

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

 +    &     +=    &=     &&    ==    !=    (    )
@@ -266,7 +273,7 @@ The following character sequences represent operators
 *    ^     *=    ^=     <-    >     >=    {    }
 /    <<    /=    <<=    ++    =     :=    ,    ;
 %    >>    %=    >>=    --    !     ...   .    :
-     &^          &^=
+     &^          &^=          ~
 

Integer literals

@@ -635,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 @@ -780,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.

@@ -820,36 +841,52 @@ 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

+

-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 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

@@ -1232,27 +1269,37 @@ 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. +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 | UnderlyingType .
+UnderlyingType = "~" 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 +1344,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 +1385,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 +1416,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 +1428,136 @@ type ReadCloser interface { }
+

+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: +

+ +
    +
  • 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 term 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 elements 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, 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 with more than one term cannot contain interface types +with non-empty method sets. +

+ +

+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. +

+ +
+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. @@ -1470,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. @@ -1538,6 +1722,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

@@ -1547,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: @@ -1572,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. +
  • @@ -1595,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] +)

    @@ -1620,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 @@ -1629,10 +1835,15 @@ 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

    @@ -1646,21 +1857,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 @@ -1669,12 +1881,37 @@ 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

    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:

      @@ -1697,6 +1934,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
     
    @@ -1724,6 +1967,117 @@ x                   T           x is not representable by a value of T because
     1e1000              float64     1e1000 overflows to IEEE +Inf after rounding
     
    +

    Structure of interfaces

    + +

    +An interface specification which contains type elements +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: +

    + +
      +
    • For an interface with no type elements, 𝑆 is the empty set. +
    • + +
    • For an interface with type elements, 𝑆 is the intersection + of the specific types of its type elements. +
    • + +
    • For a non-interface type term T + or ~T, 𝑆 is the set consisting of the type T. +
    • + +
    • For a union of terms + t1|t2|…|tn, + 𝑆 is the union of the specific types of the terms. +
    • +
    + +

    +If 𝑆 is empty, the interface has no specific types. +An interface may have specific types even if its type set +is empty. +

    + +

    +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; 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)
    +
    + +

    +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: +

    + +
    +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

    @@ -1815,6 +2169,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) @@ -1872,7 +2235,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
     
    @@ -1905,7 +2269,6 @@ An identifier is exported if both:
     All other identifiers are not exported.
     

    -

    Uniqueness of identifiers

    @@ -2076,12 +2439,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 .
     

    @@ -2158,6 +2521,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

    @@ -2267,13 +2754,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 .
     
    @@ -2296,18 +2789,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
     
    @@ -2328,9 +2831,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. @@ -2372,18 +2876,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[B, A]  { return Pair[B, A]{p.b, p.a} }
    +func (p Pair[First, _]) First() First  { return p.a }
    +

    Expressions

    @@ -2404,13 +2922,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 .
    @@ -2419,7 +2943,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.

    @@ -2653,6 +3177,7 @@ noteFrequency := map[string]float32{

    A function literal represents an anonymous function. +Function literals cannot declare type parameters.

    @@ -3000,6 +3525,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.

    @@ -3177,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.

    @@ -3347,8 +3904,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

    @@ -3440,6 +3998,12 @@ 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 +or used as a function value. +

    +

    In a function call, the function value and arguments are evaluated in the usual order. @@ -3551,6 +4115,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

    @@ -3602,7 +4241,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 @@ -4111,7 +4750,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.

    @@ -4141,14 +4782,16 @@ in any of these cases:
     	
     	
  • 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 defined types, - and their pointer base types have identical underlying types. + that are not named 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 @@ -4170,6 +4813,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 be converted to each +specific type of T. +
    • +
    +

    Struct tags are ignored when comparing struct types for identity for the purpose of conversion: @@ -4338,7 +5003,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

    @@ -4549,9 +5214,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:

      @@ -4587,7 +5251,8 @@ 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.
      @@ -5036,7 +5701,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. @@ -5047,7 +5713,6 @@ TypeSwitchStmt = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClau TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" . TypeCaseClause = TypeSwitchCase ":" StatementList . TypeSwitchCase = "case" TypeList | "default" . -TypeList = Type { "," Type } .

      @@ -5824,12 +6489,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. @@ -6771,8 +7448,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.

      diff --git a/lib/time/README b/lib/time/README index aab4daa7e2df07e01a7318905eb35917d23d2bf5..0de06df13b9a4575a0f510e854d171878ec7b89d 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 -http://tools.ietf.org/html/rfc6557 +ftp://ftp.iana.org/tz/code/tz-link.html +https://datatracker.ietf.org/doc/html/rfc6557 To rebuild the archive, read and run update.bash. diff --git a/lib/time/update.bash b/lib/time/update.bash index e088ea6b908a5fc281654cb9bebbd87c46173ed5..feb95e2e53d30a1ecbc24662ae834ac17d6914ca 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 Binary files a/lib/time/zoneinfo.zip and b/lib/time/zoneinfo.zip differ diff --git a/misc/android/go_android_exec.go b/misc/android/go_android_exec.go index 3af2bee5839b937aff5d724317e5b68df2259b06..168ebe88a2241340c8ecae41d5c3f85401bb7101 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/errors/errors_test.go b/misc/cgo/errors/errors_test.go index 68a30a44fe427d434df9dc634f702fc38552aa5e..e90ed1e058d83d7318b3ebaadf2c81f5dfaef7ce 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/errors/testdata/err2.go b/misc/cgo/errors/testdata/err2.go index a90598fe35b6304434bba7253c29b1d62173dcc4..aa941584c3c2cfcaa7491f00733c4aa0244d674f 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/misc/cgo/gmp/fib.go b/misc/cgo/gmp/fib.go index f1091b1c54f45e62187aa6a3776507a0af8e851c..f453fcf1843b7c13123398a212c0d8cc64935817 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 d5851e8e6bd389a0049d0369f960f1fc4014e090..5ea034900a9b172a92fc6b716135f6450c4f5767 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_test.go b/misc/cgo/test/cgo_test.go index 143f23f0e0cc36983ad44595469b5b7f55ff0d56..774277e10da6a080cfa9040f11ac5692459d5e9d 100644 --- a/misc/cgo/test/cgo_test.go +++ b/misc/cgo/test/cgo_test.go @@ -59,7 +59,9 @@ 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 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/cgo_thread_lock.go b/misc/cgo/test/cgo_thread_lock.go index b1050685182287dd563a6d302ea819e1e6fbe138..3b9ac845493cd5cfd4d9a665e56e94cab2139956 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 e3d591664983befc0ef8b6bfe3f251f352f491d5..a324503a22faf06ac261c079cdb70e30c851c446 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 92c6b998465caf39aeb7aebe1d39f266542de0f1..91db155c90b9836eb38042725612b9737512c28f 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 f92d6c7f939d22078a428f4ebfc8a80541cd0fdc..e50f9ae53016fce2f88e1b0118145635f41c19d5 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 d13246bd84afdea8995c2e1ab2b5a2c69c2cc4ca..8f39252e688580af7bcd5525426cdd43dc7725a3 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 08b5f4d808e240853d6b666ffd41ba2b5192d75f..50aece3528947ba2f8bd8ba2858628ffda1bf3fa 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 b2d131833a9377ac3643893b5aaa92cff4a179db..90ca08cbfb7da8b17d4b128aaf471a8dd546772f 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 b969bdd0fe8702a74ddfdf8bd72dfde97abe46ca..c2f59485e490d6aec158fddda918bfddf618253e 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/issue42018.go b/misc/cgo/test/issue42018.go new file mode 100644 index 0000000000000000000000000000000000000000..fab686a678320cb82cf6a40b8cde2e1b2eb5866b --- /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 0000000000000000000000000000000000000000..8f4570ab2a5915cb3c4a015e5e8007901da6d14c --- /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/misc/cgo/test/issue6997_linux.go b/misc/cgo/test/issue6997_linux.go index f19afb8b7ad81610520a3f8f5f69a3b5d8d0a746..4acc8c1a07062710cb33075dc5730d5d67e695bf 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 4e431df921d1e33d4ca79faf9ea26e302a4aa6d9..7316ab0335d5cb587a50c90fa83ede25db8d649b 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 89be7ea090763a909e810bbcff1ebf4a67da6986..19071ce1595ec74a4f588ac9e274960dc0693337 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 034cc4b3719150c379d97c0f1efa9bc7ce4747c9..6b371897a73471812c674d44c13d07fcc738c8ed 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 e2b939f05e2b4b61166f180ccd4548549765e67a..983734cc7b620c16e9a55d4449a8b829e5667d27 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.go b/misc/cgo/test/test.go index 3b8f548b13dd206fedd0653d8472c5b8d9958d12..dd81f770a2070c299a8ca4343bcd3dacb0ff0f8c 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/test_unix.go b/misc/cgo/test/test_unix.go index 4a234469dbc6e0d826392b85447893d734fdaa5d..831b9ca625a1fbb354c30fa5da3c7358b7cc45ba 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/test/testdata/issue43639.go b/misc/cgo/test/testdata/issue43639.go new file mode 100644 index 0000000000000000000000000000000000000000..e755fbd4bc005f4f8289bfa726559f2cb4d8c07f --- /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 0000000000000000000000000000000000000000..fe37d5e4b0f00d2feb9b4ddaccea6cbfc91d9876 --- /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/misc/cgo/test/testdata/issue9400_linux.go b/misc/cgo/test/testdata/issue9400_linux.go index e94a9bb45f5def7cf41e7a6f3d0ae05c45037726..051b9ab0bbe526baf56dab936680434d4eb740e0 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,14 @@ 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)) + // 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 issue9400.RewindAndSetgid() diff --git a/misc/cgo/test/testx.go b/misc/cgo/test/testx.go index 823c3e13d2927aac7bfd240ddd46b69882a8aff0..8ec84a8b22e01bcb6b6d78bd16f92d74e6d7cb7d 100644 --- a/misc/cgo/test/testx.go +++ b/misc/cgo/test/testx.go @@ -113,6 +113,7 @@ typedef struct { int i; } Issue38408, *PIssue38408; +extern void cfunc49633(void*); // definition is in test.go */ import "C" @@ -554,3 +555,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/misc/cgo/test/typeparam.go b/misc/cgo/test/typeparam.go new file mode 100644 index 0000000000000000000000000000000000000000..5f766c2bcb93ab35acf093e8070d0193f664683d --- /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/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go index 55be3c5f70710ffe3f1847ac9a545790cdf0d501..a2b43bb72d8d3a351d9c86f715d736d390f42bc5 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 0000000000000000000000000000000000000000..718418ecb8765f297fdb7074ef6624295e2cb070 --- /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 0000000000000000000000000000000000000000..95fb7a349e145086ddd0a411f70a2d858758d63d --- /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/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go index 19ad8c76a838b54bad64c35635216088ff40db80..13ec8761e86d957f91e06dd0417fe7acea34546b 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": @@ -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") } diff --git a/misc/cgo/testcshared/testdata/libgo2/dup2.go b/misc/cgo/testcshared/testdata/libgo2/dup2.go index d18f0b130d3f767671e4030fd34056c85c4bd132..d343aa54d9a8779450092461213c8d748d26fb84 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 c9c65a6e3c1f62be51add7bc6c129cb92dabe2b3..459f0dc196874fbf53db87bf2d976f21d18c4043 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/misc/cgo/testgodefs/testdata/issue48396.go b/misc/cgo/testgodefs/testdata/issue48396.go new file mode 100644 index 0000000000000000000000000000000000000000..d4c192403fde5058e55eec55475896775bc7bdaa --- /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 4a3f6a701cc0e7e1a6a348afdbf72407b64a8ca1..5c670f3d329c1acc2e2788c8024cd2233ec0aa62 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 aae34043605d340a64c6ede42b79ce1ca4575a6e..7628ffc595b7e261ad24e502d8257f1d7494f1f1 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/misc/cgo/testplugin/plugin_test.go b/misc/cgo/testplugin/plugin_test.go index 9697dbf7a78e3c35b2a60ed168f8a254e67e94b0..a6accc1dfbba9e76cd674735618b9a4f8f9793b9 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") diff --git a/misc/cgo/testsanitizers/asan_test.go b/misc/cgo/testsanitizers/asan_test.go new file mode 100644 index 0000000000000000000000000000000000000000..dbcce2fe2881055d7a544fedcc3d69be1c8ecaf0 --- /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 384b6250e1ef168ae130f6d77a5e302341d1cd99..b776afa3e63b319c0452e7ff307960b999690fc3 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)) } @@ -344,7 +347,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) } @@ -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 0000000000000000000000000000000000000000..e60db76981815711d09929df369969130d0b3171 --- /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 0000000000000000000000000000000000000000..e35670c440a14de820f18e85e06b33aa8ad9abe0 --- /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 0000000000000000000000000000000000000000..9f6d26dd89dbce12f1e9759749544520182b9a3a --- /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 0000000000000000000000000000000000000000..12098458ae91d27f6c9d06c316240136dd8c3edf --- /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 0000000000000000000000000000000000000000..3d3d5a6ab1ad473cd4911d1a2f13933b7538d16b --- /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/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go index e77f84891543f584ccb5bd2aa538f0e6237e9d17..d5d018f1516a774ecc4313a7a45c9a55da548077 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))) } @@ -1033,7 +1042,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 +1054,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 @@ -1070,3 +1079,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 0000000000000000000000000000000000000000..68588eda2fa0a90019274e3b448e354c39ceaf6f --- /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 0000000000000000000000000000000000000000..77c6f3437938a48e2b6c22b4c69df99d084e1a61 --- /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/testso/noso_test.go b/misc/cgo/testso/noso_test.go index c88aebfb02a91e13bf366973494413a9bab7d47c..1014534d62cf06962c4f17b96ebc3cfe896ded29 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 2023c51f113785d14482ee7a7b3556825784e7c3..6d14e32dc6caa474d9ca85082407c50db8b5e56c 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 c88aebfb02a91e13bf366973494413a9bab7d47c..1014534d62cf06962c4f17b96ebc3cfe896ded29 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 2023c51f113785d14482ee7a7b3556825784e7c3..6d14e32dc6caa474d9ca85082407c50db8b5e56c 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 3076c2d5943b5cbc1482f504e7bbbe016ac71642..a3b67c004413aafcf305109fb893dd5ed0de09c8 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/go.mod b/misc/go.mod index fc9f1133a4608ae4ca0143f4a8fc4414866d9400..712a051f4573c1fb521d67cb8e96be0008eb7c89 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/misc/ios/clangwrap.sh b/misc/ios/clangwrap.sh index dca3fcc90439d636f9a11756125fc8f28ab8653d..8f7b439315bff743618ad74ad1818ed6da017e2f 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 "$@" diff --git a/misc/ios/detect.go b/misc/ios/detect.go index cde57238923be6b959a3ac6c9341903416cbd17e..1cb8ae5ff711cc1548a825ba0f5706a6fedd26c0 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/ios/go_ios_exec.go b/misc/ios/go_ios_exec.go index 9e63717d9214d6eb98726bb21d9f2c993fded2ac..34a734cda780e3112fd4a15c4befca692a3ec0a2 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 570b430da4f1cbc76f14250822406e5449978757..efe400965b2e06c7bdb9a02b5fd7d38d72cf07e6 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/misc/reboot/experiment_toolid_test.go b/misc/reboot/experiment_toolid_test.go index 4f40284d80f107dd0014d1bfc1171d2a78ac05ef..87a828e32f73a40a1a0a64a31dd35bfc906139fd 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/misc/reboot/reboot_test.go b/misc/reboot/reboot_test.go index 6bafc608b5e234a051c7a19c7e4282cea7297f21..ef164d32327bec41cf719d4b5bc39ed2238fb367 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) diff --git a/misc/wasm/go_js_wasm_exec b/misc/wasm/go_js_wasm_exec index b700722dfe97e57e423e1d51f50c24d778d5fc5f..fcbd0e4fc8ce0e4eb3a753289b0a8283327b3bdd 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 231185a123ed12f8bc6b2ad7a56a00e3615a656a..9ce6a20c3ffa82debd6853a72f02c316ccfb642d 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -2,47 +2,18 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -(() => { - // 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; - } - } +"use strict"; +(() => { 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); @@ -87,8 +58,8 @@ }; } - if (!global.process) { - global.process = { + if (!globalThis.process) { + globalThis.process = { getuid() { return -1; }, getgid() { return -1; }, geteuid() { return -1; }, @@ -102,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 (!global.TextDecoder) { - throw new Error("global.TextDecoder is not available, polyfill required"); + if (!globalThis.TextDecoder) { + throw new Error("globalThis.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 = {}; @@ -517,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 @@ -526,7 +476,7 @@ [null, 2], [true, 3], [false, 4], - [global, 5], + [globalThis, 5], [this, 6], ]); this._idPool = []; // unused ids that have been garbage collected @@ -567,6 +517,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 + 8192; + if (offset >= wasmMinDataAddr) { + throw new Error("total length of command line and environment variables exceeds limit"); + } + this._inst.exports.run(argc, argv); if (this.exited) { this._resolveExitPromise(); @@ -594,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 0000000000000000000000000000000000000000..f9200ca95021e93e1305eb9b9521faa3e8acc06b --- /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); +}); diff --git a/src/archive/tar/common.go b/src/archive/tar/common.go index c667cfc8720b5b9db1a72184bd9fb42461916ec0..c99b5c19207f71f4c93455df42adb44cf6c63c69 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 @@ -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/format.go b/src/archive/tar/format.go index cfe24a5e1d339540c26feb898bfa6ce09d1813d8..21b9d9d4dbc628f7f18a370d7bb10f597b0efc70 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 1b1d5b46891b6bc972ed6bd9bfb1efc63eef1433..4b11909bc9527d37af905cba8c33f495b83893ca 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 789ddc1bc0345ae95058f6fafa7311b54c5f6c25..f21a6065b485706f3e2c2825f1fd8c04472fa275 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,11 +1359,11 @@ 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 } - 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 { @@ -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/stat_actime1.go b/src/archive/tar/stat_actime1.go index 4fdf2a04b3df40d6f1d59c119faa9acb5029f317..c4c2480feeb0c4db635a9b48d56bf2ef9cb910b7 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 5a9a35cbb4e22d9df42f307843730032d7e0b392..f76d6be220f87f89c55e553e88b5e4737484001f 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 3957349d6ef0aa4461062c3203c7bd852d6328ed..717a0b3abc7246a50207378bbba81424ce155dcc 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/archive/tar/strconv.go b/src/archive/tar/strconv.go index f0b61e6dba69a4fb393c8c92c694713c9defd4d6..275db6f0263f2ce8f165c265bba65a272f951bad 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/tar_test.go b/src/archive/tar/tar_test.go index e9fafc7cc70df5cd5f6308f42c87c6d577f6dabf..a476f5eb010f21d7cc4559bf860a83aa516a0553 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.go b/src/archive/tar/writer.go index e80498d03e39c0699a4f6d51c91fd4dda471ffa4..3729f7e82c192f685e43398a88d2777bde5c17e0 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 a00f02d8fab698a588872ade0e5693b0d0dc0660..da3fb89e65e51ecd17627d444af95b68e54f4596 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 { @@ -987,11 +987,9 @@ 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()) - 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) { + prefix := string(blk.toUSTAR().prefix()) + 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) } @@ -1029,11 +1027,11 @@ 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 } - testFnc interface{} // testWrite | testReadFrom | testRemaining + testFnc any // testWrite | testReadFrom | testRemaining ) type ( @@ -1046,7 +1044,7 @@ func TestFileWriter(t *testing.T) { sph sparseHoles size int64 } - fileMaker interface{} // makeReg | makeSparse + fileMaker any // makeReg | makeSparse ) vectors := []struct { @@ -1292,11 +1290,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) diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index 2d53f4c7231653d651b4f3b5bb1a15325b4a33ac..92fd6f6a9252525fb392e982952cfed66ce33e13 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 @@ -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) { @@ -710,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 { @@ -741,6 +701,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 +745,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 +763,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 37dafe6c8e7c448c8fa28359e07fc2cdbb73560f..d1a9bdd3346e519cb8afc75fc13475094e7249ad 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,127 +1203,14 @@ func TestCVE202127919(t *testing.T) { if err != nil { t.Errorf("Error reading file: %v", err) } -} - -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) - } - }) + 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) } } @@ -1384,3 +1272,139 @@ 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) + } +} + +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) + } +} diff --git a/src/archive/zip/struct.go b/src/archive/zip/struct.go index ff9f605eb697eec319602d455917953b70b906e6..6f73fb8376a859235ff3d589a3a0314bc9311721 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 } @@ -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 -} diff --git a/src/archive/zip/writer_test.go b/src/archive/zip/writer_test.go index 97c6c5297994684ca7fcfc5ccc492025709d795c..2b73eca814f621a9a0289f24cf0b6bbe8df35c6c 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/bufio/bufio.go b/src/bufio/bufio.go index ec928e7ad69ed54d213d3a38d9efb011ff32eb82..7483946fc0aabf3e0dffaa07608369c1f473a0f3 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) } @@ -168,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() @@ -235,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]) @@ -261,8 +272,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 @@ -497,6 +508,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 @@ -581,6 +595,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) } @@ -590,7 +606,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 @@ -623,6 +644,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 } @@ -720,19 +749,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 { @@ -740,6 +764,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 ebcc711db9d48cdefa44d6ec9bddd2406c13b59d..4dddfa9085cc4a99aacb5702dfa7f497c82cb48c 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" @@ -302,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}) @@ -608,6 +644,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 { @@ -1284,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) { @@ -1312,6 +1427,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 +1436,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 +1462,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) { @@ -1382,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", diff --git a/src/bufio/example_test.go b/src/bufio/example_test.go index 8885d40549f1532010a320d00964f19bffbb5846..a864d11012e77f96bc2a24dc692ce967c73270e3 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) diff --git a/src/builtin/builtin.go b/src/builtin/builtin.go index 01190e99002d441da5a477fa9ec7c8f36a0df44b..08ae7ed313add4fb435b154605d143188747f302 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. @@ -229,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 @@ -240,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/boundary_test.go b/src/bytes/boundary_test.go index 5a47526593b093678b85e0c45c2dfbd5a42d16ed..f9855fcb0520f3bdf9082f71ddf794c923c3d0b5 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 @@ -66,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. @@ -82,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 } diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index ce52649f132bb9575beacdca5af912f97478bb32..6fdaa49c7344921da2d1c987d714a61884935157 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) @@ -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:]) @@ -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 @@ -867,6 +868,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,53 +880,133 @@ 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 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)) - } - } - return func(r rune) bool { - for _, c := range cutset { - if c == r { - return true - } +// 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 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 { - return TrimFunc(s, makeCutsetFunc(cutset)) + if len(s) == 0 || cutset == "" { + return s + } + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0]) + } + 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 { - return TrimLeftFunc(s, makeCutsetFunc(cutset)) + if len(s) == 0 || cutset == "" { + return s + } + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimLeftByte(s, cutset[0]) + } + if as, ok := makeASCIISet(cutset); ok { + return trimLeftASCII(s, &as) + } + return trimLeftUnicode(s, cutset) +} + +func trimLeftByte(s []byte, c byte) []byte { + for len(s) > 0 && s[0] == c { + s = s[1:] + } + 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 { - return TrimRightFunc(s, makeCutsetFunc(cutset)) + if len(s) == 0 || cutset == "" { + return s + } + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimRightByte(s, cutset[0]) + } + if as, ok := makeASCIISet(cutset); ok { + return trimRightASCII(s, &as) + } + return trimRightUnicode(s, cutset) +} + +func trimRightByte(s []byte, c byte) []byte { + for len(s) > 0 && s[len(s)-1] == c { + s = s[:len(s)-1] + } + 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 @@ -1174,3 +1257,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, nil, 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 544ee46f908860dc969170c26d8f3ad472394eee..3bece6adf0b905b63f580db349c5ee0cf007b89b 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"}, @@ -1565,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 { @@ -1963,6 +1988,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/bytes/example_test.go b/src/bytes/example_test.go index ae93202b5706e12da11cb8866af8f6a9d75b5745..54a7aa6ae6c04960ce88f6b0d9cabbc01b46acbe 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) @@ -54,6 +64,52 @@ 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 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 @@ -92,36 +148,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"))) @@ -168,6 +194,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++"))) @@ -181,6 +223,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"))) @@ -246,6 +301,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"))) @@ -286,10 +347,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() { @@ -399,20 +462,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: @@ -429,11 +478,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: @@ -450,21 +516,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 @@ -480,10 +531,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/bytes/reader_test.go b/src/bytes/reader_test.go index 8baac5046cbeecf30b6dce346908943de524d1e8..9119c944ace4783ebb9fb3295beb7be23336e009 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 b07a238d679a1636657fb7618b8c0d7e7ea34a72..036aefe4d8b3e280f07cdbcb399243147d8993cc 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{} @@ -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 { @@ -701,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: @@ -758,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("}") @@ -795,12 +837,19 @@ func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) { } buf.WriteString(typ.Obj().Name()) + case *types.TypeParam: + // Type parameter names may change, so use a placeholder instead. + fmt.Fprintf(buf, "$%d", typ.Index()) + 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: @@ -814,6 +863,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) + w.writeType(buf, tp) + 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++ { @@ -867,6 +933,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)) @@ -990,10 +1062,16 @@ 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{}) { +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/run.go b/src/cmd/api/run.go index 81979de191abc2f13263a467fc7e34aab31b8026..1b94a1b883f4747e6d37e17e99de6fdb5e0f7b39 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/api/testdata/src/issue21181/p/p_generic.go b/src/cmd/api/testdata/src/issue21181/p/p_generic.go index 4d75809676200c5b6e642cb80d2abeeff781cc5e..ad6df20187e9c0bfbbf3104f4c81067259e8a4ff 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 65181b248a30388d9901e00eeca9ae1ea71ed769..81826d768b4f8c06111b66f1db7cc3e75ed56002 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/golden.txt b/src/cmd/api/testdata/src/pkg/p4/golden.txt new file mode 100644 index 0000000000000000000000000000000000000000..7997ab447123e83a5de90a695a7fa271bcb3d0a0 --- /dev/null +++ b/src/cmd/api/testdata/src/pkg/p4/golden.txt @@ -0,0 +1,5 @@ +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 new file mode 100644 index 0000000000000000000000000000000000000000..1f90e779dd4b52b540b1d9c6a74d48601be61945 --- /dev/null +++ b/src/cmd/api/testdata/src/pkg/p4/p4.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 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 +} + +func Clone[S ~[]T, T any](s S) S { + return append(S(nil), s...) +} diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go index 026d8abf81305f51d953b500c35d3bd2d7c7a087..4d374cb828eadb595727a5f4e2552570a7f39d70 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": @@ -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, @@ -374,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 @@ -534,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/arch/arm64.go b/src/cmd/asm/internal/arch/arm64.go index 40d828a1fea7485d3389c529f16180ecdd140bc7..24689c5ab17657816a67e7fe0b69a498e40d4c99 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) diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index cf0d1550f99f0e3d6f014b1b4782553692348bb2..d0cb6328f16b6e6936b826a7e11e09b914549b76 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/operand_test.go b/src/cmd/asm/internal/asm/operand_test.go index 8ef02b1a0e8acacafb379d12030e1c522de984f0..c1295a0c4267d577e5302c493518aed7c69f47fb 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/internal/asm/testdata/amd64enc.s b/src/cmd/asm/internal/asm/testdata/amd64enc.s index c02f51d125916b84687fc8aba07428a37950ccd8..5bba292dee43f6659b457c8de9177682b0fa5d82 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/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index d8a20edfc13039d205c10a0579ab9414a54daa54..a4b56b0696b33a8524243df796ac9c7fee0ea4be 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 @@ -386,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/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index cf57179e43016156cf148dcbd001c54d5620b00e..3d3de1d9b13770ba9efbd403359a7b0a1abac0d6 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" @@ -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,4 +419,17 @@ 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" + 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" + 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/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index b6c0aa5035c013652dcd7df91505d78cfd9ac6a7..c140fd025a64e8117754db20842bffe3e714b3ff 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 @@ -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 @@ -736,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/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 77c0764c48117a78132e0407837c45dc7194b208..fe911a74f5da6d85c1bf95a7c50678c3ca9cdf37 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 @@ -86,20 +101,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 @@ -219,6 +229,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 @@ -259,6 +273,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 @@ -277,11 +295,17 @@ start: // MOV pseudo-instructions MOV X5, X6 // 13830200 - MOV $2047, X5 // 9b02f07f - MOV $-2048, X5 // 9b020080 - - // Converted to load of symbol. - MOV $4294967296, X5 // 97020000 + 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 MOV (X5), X6 // 03b30200 MOV 4(X5), X6 // 03b34200 @@ -325,42 +349,44 @@ 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 - // 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, 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 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/asm/internal/asm/testdata/riscv64error.s b/src/cmd/asm/internal/asm/testdata/riscv64error.s index fb43e68fc1740b131328778f0612ccf99455674f..238552565bdd2f6fe1fe1f9769f7020403a6a5a7 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 "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" 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/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go index dd947c7b5ba5b805d4319d78fe432cafdbf1faad..607166e664d90fef67494671f45038e80e9fb6ed 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 043bc696e58ae2fb0fdd74bcc0e5cdcfe9bb7a39..3683527f5b8e582fdecac1fb1dbfa315de5956e9 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -29,19 +29,20 @@ 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 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/cgo/ast.go b/src/cmd/cgo/ast.go index a073407a961e15af2a7b4cbe92afd925712e82b3..28879e349c49cf371b40a7fb0d09f2e4b285f549 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 0000000000000000000000000000000000000000..f52bf00d7cb946e9844f485352daec989435a2db --- /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 compiler_bootstrap +// +build compiler_bootstrap + +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 0000000000000000000000000000000000000000..db0108ed7268366a5dc0543645645bed443a3ecb --- /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 !compiler_bootstrap +// +build !compiler_bootstrap + +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 a73e998877af812762afcc4716c17b78adf7f065..997a830994f09bdd6118299e31e20125cadff3ff 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/quoted" ) 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") @@ -1503,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) } @@ -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) } - // Try $GCC if set, since that's what we used to use. - if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 { - return ret + args, err := quoted.Split(value) + if err != nil { + return nil, err } - return strings.Fields(defaultCC(goos, goarch)) + if len(args) == 0 { + return nil, errors.New("CC not set and no default found") + } + if _, err := exec.LookPath(args[0]); err != nil { + return nil, fmt.Errorf("C compiler %q not found: %v", args[0], err) + } + 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 @@ -2086,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 @@ -2097,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 @@ -2120,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") @@ -2138,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. @@ -2518,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 } @@ -2561,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 @@ -3010,6 +3061,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 { @@ -3087,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/main.go b/src/cmd/cgo/main.go index c6a0c525e64f212bd51bb7a5eb317e46a085ffbc..14642b7576b0122e0252960c498fe9ed11a21826 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/cgo/out.go b/src/cmd/cgo/out.go index 94152f4278cb04b44325a936c50d8d11887f4b3d..4968f7059d9bd6e13789d84798f7b38d7deb4d71 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. @@ -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 { @@ -1054,9 +1055,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 { @@ -1458,10 +1460,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/cmd/compile/abi-internal.md b/src/cmd/compile/abi-internal.md index 2bb4055083263044df3c400a52a3cf6dd27dde40..7fe446366568124dc9d9c4559d28b6198cdb4d1e 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 @@ -505,6 +509,227 @@ 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. + +### 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 diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go index b68ef274f379e0fa932b54307afafb0b8db1cfdf..ef7fa86749f0137d03c949a08dcf504cb58bb56f 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/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index d657ddc867bad00f44a00a3e9af54b7507b99683..529150a390b1d577e93bfa554bb2a42553c77549 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 } @@ -715,21 +715,25 @@ 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), }) + types.CalcStructSize(synthIface) }) } @@ -764,10 +768,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) @@ -777,11 +781,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 { @@ -793,8 +797,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) diff --git a/src/cmd/compile/internal/amd64/galign.go b/src/cmd/compile/internal/amd64/galign.go index 2785aa03368b782c3d5d9b5c8f983d0dac19b1d6..ca44263afc476c4eef177df64562920b13e7afdc 100644 --- a/src/cmd/compile/internal/amd64/galign.go +++ b/src/cmd/compile/internal/amd64/galign.go @@ -18,11 +18,10 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop 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/ggen.go b/src/cmd/compile/internal/amd64/ggen.go index 1484ad5404b4797552195b597fd0e22cab00e85b..b8dce81a92d2cc9013e075b6698e8acc2b8b2fbf 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 ca5f36e77598c6ff54b6c3288b086f40a9f999d4..b0e5c34030f32b9d6b62159a7fef03e4dc3a5e80 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -263,6 +263,24 @@ 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, + ssa.OpAMD64TZCNTQ, ssa.OpAMD64TZCNTL: + 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. @@ -600,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, @@ -741,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() @@ -757,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() @@ -822,8 +856,13 @@ 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: - if !buildcfg.Experiment.RegabiG || s.ABI != obj.ABIInternal { + 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 +871,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, @@ -914,7 +954,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,22 +1037,30 @@ 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 { + 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 - 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) } + if v.Op == ssa.OpAMD64CALLtail { + s.TailCall(v) + break + } 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 - 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) } @@ -1093,7 +1141,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 @@ -1221,6 +1269,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 @@ -1300,20 +1352,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 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) - // 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) @@ -1348,20 +1389,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/amd64/versions_test.go b/src/cmd/compile/internal/amd64/versions_test.go new file mode 100644 index 0000000000000000000000000000000000000000..7aa697b811442b3367f83998f1bdfb7b056701b8 --- /dev/null +++ b/src/cmd/compile/internal/amd64/versions_test.go @@ -0,0 +1,393 @@ +// Copyright 2021 The Go Authors. 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" + "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 { + if runtimeFeatures[feature] { + 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) + } + // 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) + } +} + +// 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-z0-9]+)`) + } + + // 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() +} + +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"}, +} + +// 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) + } + } +} + +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) + } + } +} diff --git a/src/cmd/compile/internal/arm/galign.go b/src/cmd/compile/internal/arm/galign.go index d68500280d00b79376d976a39fab34286faa65a8..23e52bacbf2a3d077d7fc267859c0167283707a2 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/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go index 4b083cec46b4a5cff59981de626a75f62fc0e1b7..063fb65b33ab90bf7e56f5f681a1a32ec959487e 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 @@ -696,6 +699,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 +941,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/galign.go b/src/cmd/compile/internal/arm64/galign.go index d3db37e16f43bcbbb261d75078df6c8d126b4a72..3ebd860de8f887c4c0b4dbc3934b7ed297995398 100644 --- a/src/cmd/compile/internal/arm64/galign.go +++ b/src/cmd/compile/internal/arm64/galign.go @@ -18,9 +18,10 @@ 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 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 0c997bc4b3e82adaee8e20ea5bafaf29f6a01c7b..96a29224bf71d50b0201457ae965f54a55381eb6 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" @@ -78,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 @@ -161,6 +165,18 @@ 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: + // 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, ssa.OpARM64AND, @@ -297,11 +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, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_ROR, v.AuxInt) case ssa.OpARM64ADDshiftLL, ssa.OpARM64SUBshiftLL, ssa.OpARM64ANDshiftLL, @@ -310,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, @@ -319,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, @@ -328,7 +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, 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 @@ -371,11 +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, 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 @@ -1033,6 +1060,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 @@ -1082,6 +1111,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) @@ -1097,12 +1132,42 @@ 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: 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()) } @@ -1196,17 +1261,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, @@ -1266,3 +1325,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/base/base.go b/src/cmd/compile/internal/base/base.go index 4c2516f60e364b5d177707daaa8584c0e1920777..be6d49fac766db1d846ad5a376e4e0d8297ece0e 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/bootstrap_false.go b/src/cmd/compile/internal/base/bootstrap_false.go new file mode 100644 index 0000000000000000000000000000000000000000..c77fcd730812d824c061d329ca0ed353d82a8b16 --- /dev/null +++ b/src/cmd/compile/internal/base/bootstrap_false.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 !compiler_bootstrap +// +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 0000000000000000000000000000000000000000..1eb58b2f9dc1ce86ca9fb095715e685e667cbb3e --- /dev/null +++ b/src/cmd/compile/internal/base/bootstrap_true.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 compiler_bootstrap +// +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/base/debug.go b/src/cmd/compile/internal/base/debug.go index 71712ab1a56fd281f52d3befede9b833caa70fbd..b105e46e353cb4767b610e6dfe6f1293f2c2a526 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,150 +31,23 @@ 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"` + 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"` + 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 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 42c0c1b94b559c17ae593b9592b7ec5152e3a5f8..d78f93b343fa118670f5703cefddd2f700f1d94e 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\"" @@ -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\"" @@ -108,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\"" @@ -140,10 +141,11 @@ type CmdFlags struct { // ParseFlags parses the command-line flags into Flag. func ParseFlags() { + Flag.G = 3 Flag.I = addImportDir Flag.LowerC = 1 - Flag.LowerD = parseDebug + Flag.LowerD = objabi.NewDebugFlag(&Debug, DebugSSA) Flag.LowerP = &Ctxt.Pkgpath Flag.LowerV = &Ctxt.Debugvlog @@ -159,7 +161,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 @@ -172,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) } @@ -183,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() @@ -212,12 +222,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 } @@ -317,6 +331,12 @@ func registerFlags() { case funcType: f := v.Field(i).Interface().(func(string)) objabi.Flagfn1(name, help, f) + default: + 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)) + } } } } @@ -344,7 +364,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. @@ -352,7 +372,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/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 298b385bcb0f762413c6cf6f7402f0817240d005..c1616db8e9dd684027400eea36481f209d98d2b6 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 9637ab97abe458dc19e0ead21ed0759532fc7d47..01796a9bab7c9978f0b22211d714efff01782c58 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/base/print.go b/src/cmd/compile/internal/base/print.go index b095fd704daad807b3847bbd2916024356161af2..4afe2eb9eea3154f83456ed4ed282f04d7d1ab4a 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/bitvec/bv.go b/src/cmd/compile/internal/bitvec/bv.go index bcac1fe351fac13c7d06850495cc13364f3d0ddd..ad7ed0a1965e9c064e2dddf0f19125dfd4fe7ed4 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<= 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/desugar.go b/src/cmd/compile/internal/escape/desugar.go new file mode 100644 index 0000000000000000000000000000000000000000..8b3cc25cf9a4a684810107e1124546d6e9b3b187 --- /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/escape.go b/src/cmd/compile/internal/escape/escape.go index cd56f07b6147a431cf0347e65c5c91df2d98d29d..61e0121a40aec2ea54b6829932eecd3641e00ba6 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 @@ -269,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) } } @@ -342,1771 +262,173 @@ 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) +func (b *batch) finish(fns []*ir.Func) { + // Record parameter tags for package export data. + for _, fn := range fns { + fn.SetEsc(escFuncTagged) - 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")) - } - } + narg := 0 + for _, fs := range &types.RecvsParams { + for _, f := range fs(fn.Type()).Fields().Slice() { + narg++ + f.Note = b.paramTag(fn, narg, f) } - 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.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) + for _, loc := range b.allLocs { + n := loc.n + if n == nil { + continue } - - 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) + if n.Op() == ir.ONAME { + n := n.(*ir.Name) + n.Opt = nil } - case ir.OCLOSURE: - n := n.(*ir.ClosureExpr) - k = e.spill(k, n) - e.closures = append(e.closures, closure{k, n}) + // Update n.Esc based on escape analysis results. - if fn := n.Func; fn.IsHiddenClosure() { - for _, cv := range fn.ClosureVars { - if loc := e.oldLoc(cv); !loc.captured { - loc.captured = true + // 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() - // Ignore reassignments to the variable in straightline code - // preceding the first capture by a closure. - if loc.loopDepth == e.loopDepth { - loc.reassigned = false - } + if loc.escapes { + if n.Op() == ir.ONAME { + if base.Flag.CompilingRuntime { + base.ErrorfAt(n.Pos(), "%v escapes to heap, not allowed in runtime", n) + } + if base.Flag.LowerM != 0 { + base.WarnfAt(n.Pos(), "moved to heap: %v", n) + } + } else { + if base.Flag.LowerM != 0 && !goDeferWrapper { + base.WarnfAt(n.Pos(), "%v escapes to heap", n) + } + if logopt.Enabled() { + var e_curfn *ir.Func // TODO(mdempsky): Fix. + logopt.LogOpt(n.Pos(), "escape", "escape", ir.FuncName(e_curfn)) } } - - 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) + n.SetEsc(ir.EscHeap) + } else { + if base.Flag.LowerM != 0 && n.Op() != ir.ONAME && !goDeferWrapper { + base.WarnfAt(n.Pos(), "%v does not escape", n) + } + n.SetEsc(ir.EscNone) + if loc.transient { + switch n.Op() { + case ir.OCLOSURE: + n := n.(*ir.ClosureExpr) + n.SetTransient(true) + case ir.OMETHVALUE: + n := n.(*ir.SelectorExpr) + n.SetTransient(true) + case ir.OSLICELIT: + n := n.(*ir.CompLitExpr) + n.SetTransient(true) } } - 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) +// 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) } - 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) + return true } + return false } -// 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) - } -} +const ( + escFuncUnknown = 0 + iota + escFuncPlanned + escFuncStarted + escFuncTagged +) -// 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() - } +// Mark labels that have no backjumps to them as not increasing e.loopdepth. +type labelState int - k := e.heapHole() +const ( + looping labelState = 1 + iota + nonlooping +) - 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) +func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { + name := func() string { + if f.Sym != nil { + return f.Sym.Name } - 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 fmt.Sprintf("arg#%d", narg) } - return k -} + // 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()) -func (e *escape) addrs(l ir.Nodes) []hole { - var ks []hole - for _, n := range l { - ks = append(ks, e.addr(n)) - } - return ks -} + if len(fn.Body) == 0 { + // Assume that uintptr arguments must be held live across the call. + // This is most important for syscall.Syscall. + // See golang.org/issue/13372. + // 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 -// 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 + if f.Type.IsUintptr() { + if diagnose { + base.WarnfAt(f.Pos, "assuming %v is unsafe uintptr", name()) + } + 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 + if !f.Type.HasPointers() { // don't bother tagging for scalars + return "" } - 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] - } + var esc leaks - 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 + // External functions are assumed unsafe, unless + // //go:noescape is given before the declaration. + if fn.Pragma&ir.Noescape != 0 { + if diagnose && f.Sym != nil { + base.WarnfAt(f.Pos, "%v does not escape", name()) } - - // 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() + } else { + if diagnose && f.Sym != nil { + base.WarnfAt(f.Pos, "leaking param: %v", name()) } + esc.AddHeap(0) } - 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) + return esc.Encode() } - 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) + if fn.Pragma&ir.UintptrEscapes != 0 { + fn.Pragma |= ir.UintptrKeepAlive - // 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 + if f.Type.IsUintptr() { + if diagnose { + base.WarnfAt(f.Pos, "marking %v as escaping uintptr", name()) } - 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 param.Note == UintptrEscapesNote { - 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 { - fn.SetEsc(escFuncTagged) - - narg := 0 - for _, fs := range &types.RecvsParams { - for _, f := range fs(fn.Type()).Fields().Slice() { - narg++ - f.Note = b.paramTag(fn, narg, f) - } - } - } - - for _, loc := range b.allLocs { - n := loc.n - if n == nil { - continue - } - if n.Op() == ir.ONAME { - n := n.(*ir.Name) - n.Opt = nil - } - - // Update n.Esc based on escape analysis results. - - if loc.escapes { - if n.Op() == ir.ONAME { - if base.Flag.CompilingRuntime { - base.ErrorfAt(n.Pos(), "%v escapes to heap, not allowed in runtime", n) - } - if base.Flag.LowerM != 0 { - base.WarnfAt(n.Pos(), "moved to heap: %v", n) - } - } else { - if base.Flag.LowerM != 0 { - base.WarnfAt(n.Pos(), "%v escapes to heap", n) - } - if logopt.Enabled() { - var e_curfn *ir.Func // TODO(mdempsky): Fix. - logopt.LogOpt(n.Pos(), "escape", "escape", ir.FuncName(e_curfn)) - } - } - n.SetEsc(ir.EscHeap) - } else { - if base.Flag.LowerM != 0 && n.Op() != ir.ONAME { - base.WarnfAt(n.Pos(), "%v does not escape", n) - } - n.SetEsc(ir.EscNone) - if loc.transient { - switch n.Op() { - case ir.OCLOSURE: - n := n.(*ir.ClosureExpr) - n.SetTransient(true) - case ir.OCALLPART: - n := n.(*ir.SelectorExpr) - n.SetTransient(true) - case ir.OSLICELIT: - n := n.(*ir.CompLitExpr) - n.SetTransient(true) - } - } - } - } -} - -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) - } - } - } -} - -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) -} - -const ( - escFuncUnknown = 0 + iota - escFuncPlanned - escFuncStarted - escFuncTagged -) - -// Mark labels that have no backjumps to them as not increasing e.loopdepth. -type labelState int - -const ( - looping labelState = 1 + iota - 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 "" -} - -// 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 { - return f.Sym.Name - } - return fmt.Sprintf("arg#%d", narg) - } - - if len(fn.Body) == 0 { - // Assume that uintptr arguments must be held live across the call. - // This is most important for syscall.Syscall. - // See golang.org/issue/13372. - // 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. - if f.Type.IsUintptr() { - if base.Flag.LowerM != 0 { - base.WarnfAt(f.Pos, "assuming %v is unsafe uintptr", name()) - } - return UnsafeUintptrNote - } - - if !f.Type.HasPointers() { // don't bother tagging for scalars - return "" - } - - var esc leaks - - // 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 { - base.WarnfAt(f.Pos, "%v does not escape", name()) - } - } else { - if base.Flag.LowerM != 0 && f.Sym != nil { - base.WarnfAt(f.Pos, "leaking param: %v", name()) - } - esc.AddHeap(0) - } - - return esc.Encode() - } - - if fn.Pragma&ir.UintptrEscapes != 0 { - 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 { + if diagnose { base.WarnfAt(f.Pos, "marking %v as escaping ...uintptr", name()) } - return UintptrEscapesNote + return "" } } @@ -2125,7 +447,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/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go new file mode 100644 index 0000000000000000000000000000000000000000..ced90a47bcb6632a4c8df5a0a1664ab5de409429 --- /dev/null +++ b/src/cmd/compile/internal/escape/expr.go @@ -0,0 +1,335 @@ +// 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 + }() + + if k.derefs >= 0 && !n.Type().IsUntyped() && !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.OGETCALLERPC, ir.OGETCALLERSP, ir.OTYPE, ir.OMETHEXPR, ir.OLINKSYMOFFSET: + // nop + + case ir.ONAME: + n := n.(*ir.Name) + if n.Class == ir.PFUNC || n.Class == ir.PEXTERN { + return + } + 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.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() { + 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, ir.OCONVIDATA: + 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.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: + 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.OMETHVALUE: + // 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) + + 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) + + case ir.ODYNAMICTYPE: + // Nothing to do - argument is a *runtime._type (+ maybe a *runtime.itab) pointing to static data section + } +} + +// 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 0000000000000000000000000000000000000000..cc3d078adddf8796349ab5aa813c81615450806b --- /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 +} + +// 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 { + 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 +} + +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 { + if canon := n.(*ir.Name).Canonical(); n != canon { + base.Fatalf("newLoc on non-canonical %v (canonical is %v)", n, canon) + } + } + 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.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) + } + + 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 0000000000000000000000000000000000000000..4c848a5ee7859d0f2bfe3adf4118df263c0bd1f9 --- /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 0000000000000000000000000000000000000000..77d6b27dd75b01178d546b18da323f1263558566 --- /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 0000000000000000000000000000000000000000..0afb5d64ef681433aa031e2334da33c71d3e3991 --- /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]) + 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.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) + e.goDeferStmt(n) + + case ir.OTAILCALL: + n := n.(*ir.TailCallStmt) + e.call(nil, n.Call) + } +} + +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 0000000000000000000000000000000000000000..2c6e9bcbebda07143061a9ddb631e837685db432 --- /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().Size() > ir.MaxStackVarSize { + return "too large for stack" + } + + if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Size() > 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.OMETHVALUE && typecheck.MethodValueType(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().Size() != 0 && ir.Int64Val(r) > ir.MaxImplicitStackVarSize/t.Elem().Size() { + return "too large for stack" + } + } + + return "" +} diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 2137f1d1961abf8987383d0cd835459fb37fc2c5..eed438705ade0f20a18451eb8a0a0f5cfc8e24c2 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -5,46 +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 { - // 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) - } - - // 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 { @@ -61,14 +31,14 @@ 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() 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)) @@ -79,83 +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 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: - for _, f := range t.AllMethods().Slice() { - if types.IsExported(f.Sym.Name) { - p.markType(f.Type) - } - } - } -} diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index ce50cbb4c2e691ed3054d20894fc1bc722623eda..ed81ef7bc0471458df4387387a3466c1979badf6 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() { @@ -83,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 @@ -106,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") @@ -148,20 +149,18 @@ 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 { 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 } @@ -181,21 +180,40 @@ 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) typecheck.InitUniverse() + typecheck.InitRuntime() // Parse and typecheck input. noder.LoadPackage(flag.Args()) dwarfgen.RecordPackageName() - // Build init task. - if initTask := pkginit.Task(); initTask != nil { - typecheck.Export(initTask) + // Prepare for backend processing. This must happen before pkginit, + // because it generates itabs for initializing global variables. + ssagen.InitConfig() + + // 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. + 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. @@ -227,7 +245,13 @@ 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 // Devirtualize. for _, n := range typecheck.Target.Decls { @@ -237,6 +261,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() @@ -252,6 +281,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 +294,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. @@ -278,6 +302,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/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 474d718525f5b80a3adc9c47c3aad8e879830e48..dcb54047f1fce75b577f8c32c40f0e19f88464e4 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() { @@ -116,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() @@ -157,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) { @@ -251,8 +249,7 @@ func addGCLocals() { } } if x := fn.StackObjects; x != nil { - attr := int16(obj.RODATA) - objw.Global(x, int32(len(x.P)), attr) + objw.Global(x, int32(len(x.P)), obj.RODATA) x.Set(obj.AttrStatic, true) } if x := fn.OpenCodedDeferInfo; x != nil { @@ -261,7 +258,10 @@ 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) + } + if x := fn.ArgLiveInfo; x != nil { + objw.Global(x, int32(len(x.P)), obj.RODATA|obj.DUPOK) + x.Set(obj.AttrStatic, true) } } } @@ -276,7 +276,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/gc/util.go b/src/cmd/compile/internal/gc/util.go index 4baddbc029a8d2dc587650a1b99243bc20b9b619..56fd137de2374b96b9788417b809fec1e0a91388 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 { diff --git a/src/cmd/compile/internal/importer/exportdata.go b/src/cmd/compile/internal/importer/exportdata.go index 3925a64314ea0d8d160afcc5fbc3719dbae58338..6a672be9c1bac15a5fa4cc89e69b67c21e95f4f1 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. diff --git a/src/cmd/compile/internal/importer/gcimporter.go b/src/cmd/compile/internal/importer/gcimporter.go index feb18cf2c9ad78c50f2287d723246991e678e8bd..ff40be65bbeceebcbb67d3d07c4b87631ea2c904 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. @@ -156,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/gcimporter_test.go b/src/cmd/compile/internal/importer/gcimporter_test.go index 7fb8fed59cf9be1cd00471a1d0854e89d4ed1148..5d80db244b9bf3c31ae93ddac34b24f37f3ac901 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. @@ -9,8 +8,8 @@ import ( "bytes" "cmd/compile/internal/types2" "fmt" + "internal/goexperiment" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -64,7 +63,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 +91,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) } @@ -109,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) + } } } } @@ -142,7 +145,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 +198,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 +215,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) @@ -255,14 +258,13 @@ 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)}"}, {"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 +459,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 diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 8ab0b7b98961fdefe1e4dc605a65a029979c79b1..7c51d3b16fc4b669bd4757e1257d3fef713716bb 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. @@ -9,7 +8,6 @@ package importer import ( - "bytes" "cmd/compile/internal/syntax" "cmd/compile/internal/types2" "encoding/binary" @@ -19,10 +17,11 @@ import ( "io" "math/big" "sort" + "strings" ) type intReader struct { - *bytes.Reader + *strings.Reader path string } @@ -42,6 +41,21 @@ func (r *intReader) uint64() uint64 { return i } +// Keep this in sync with constants in iexport.go. +const ( + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + iexportVersionGenerics = 2 + iexportVersionGo1_18 = 2 + + iexportVersionCurrent = 2 +) + +type ident struct { + pkg string + name string +} + const predeclReserved = 32 type itag uint64 @@ -57,6 +71,9 @@ const ( signatureType structType interfaceType + typeParamType + instanceType + unionType ) const io_SeekCurrent = 1 // io.SeekCurrent (not defined in Go 1.4) @@ -65,8 +82,8 @@ 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) { - const currentVersion = 1 +func ImportData(imports map[string]*types2.Package, data, path string) (pkg *types2.Package, err error) { + const currentVersion = iexportVersionCurrent version := int64(-1) defer func() { if e := recover(); e != nil { @@ -78,11 +95,11 @@ 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 { - case currentVersion, 0: + case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: default: errorf("unknown iexport format version %d", version) } @@ -96,16 +113,20 @@ 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), - pkgCache: make(map[uint64]*types2.Package), + stringData: stringData, + pkgCache: make(map[uint64]*types2.Package), + posBaseCache: make(map[uint64]*syntax.PosBase), 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 { @@ -117,17 +138,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 @@ -153,10 +179,6 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( 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)) @@ -165,21 +187,22 @@ 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 { - ipath string - version int + exportVersion int64 + ipath string + version int - stringData []byte - stringCache map[uint64]string - pkgCache map[uint64]*types2.Package + stringData string + 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 string + pkgIndex map[*types2.Package]map[string]uint64 + typCache map[uint64]types2.Type + tparamIndex map[ident]types2.Type interfaceList []*types2.Interface } @@ -199,24 +222,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 { @@ -228,8 +248,18 @@ 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.NewTrimmedFileBase(filename, true) + 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)) { + if t, ok := p.typCache[off]; ok && canReuse(base, t) { return t } @@ -241,22 +271,40 @@ 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) { + 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 bytes.Reader - currPkg *types2.Package - prevFile string - prevLine int64 - prevColumn int64 + p *iimporter + declReader strings.Reader + currPkg *types2.Package + prevPosBase *syntax.PosBase + prevLine int64 + prevColumn int64 } func (r *importReader) obj(name string) { @@ -274,17 +322,26 @@ func (r *importReader) obj(name string) { r.declare(types2.NewConst(pos, r.currPkg, name, typ, val)) - case 'F': - sig := r.signature(nil) - + case 'F', 'G': + var tparams []*types2.TypeParam + if tag == 'G' { + tparams = r.tparamList() + } + sig := r.signature(nil, nil, tparams) r.declare(types2.NewFunc(pos, r.currPkg, name, sig)) - case 'T': + case 'T', 'U': // 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) + // 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) @@ -294,12 +351,57 @@ 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(recv.Type()).TypeArgs() + var rparams []*types2.TypeParam + if targs.Len() > 0 { + rparams = make([]*types2.TypeParam, targs.Len()) + for i := range rparams { + rparams[i], _ = targs.At(i).(*types2.TypeParam) + } + } + msig := r.signature(recv, rparams, nil) named.AddMethod(types2.NewFunc(mpos, r.currPkg, mname, msig)) } } + 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") + } + // 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") + } + 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} + r.p.tparamIndex[id] = t + + 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() @@ -316,6 +418,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: @@ -439,12 +545,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 +559,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 +571,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 +585,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 { @@ -507,7 +613,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() @@ -547,13 +653,56 @@ 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) } typ := types2.NewInterfaceType(methods, embeddeds) r.p.interfaceList = append(r.p.interfaceList, typ) return typ + + case typeParamType: + 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 instanceType: + 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([]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. + // TODO provide a non-nil *Context + t, _ := types2.Instantiate(nil, baseType, targs, false) + return t + + case unionType: + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected instantiation type") + } + terms := make([]*types2.Term, r.uint64()) + for i := range terms { + terms[i] = types2.NewTerm(r.bool(), r.typ()) + } + return types2.NewUnion(terms) } } @@ -561,11 +710,23 @@ 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 { + n := r.uint64() + if n == 0 { + return nil + } + xs := make([]*types2.TypeParam, n) + for i := range xs { + xs[i] = r.typ().(*types2.TypeParam) + } + return xs } func (r *importReader) paramList() *types2.Tuple { @@ -610,3 +771,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/importer/support.go b/src/cmd/compile/internal/importer/support.go index 40b9c7c9583fbff277c7d5a2237bdc82596384de..9377d997796190b402536a25f849c75717516fe5 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. @@ -119,7 +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/importer/testdata/a.go b/src/cmd/compile/internal/importer/testdata/a.go index 06dafee98c30f82e459be13f0c0ced7e535d57af..56e4292cda9f3a0892677a20722c833165171290 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 a601dbccc5a0e9b76ac8bfd752e2fb7e5b6397cd..419667820078e47d4744ee7c809a8f63516c8a42 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 2a720fd2c172541bbbe32976791534c06a2ecbdb..91598c03e35c0337edd1f51b4b399135b32be8dd 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. @@ -16,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 0000000000000000000000000000000000000000..00bf04000fa06c717f8bad1ab238dd83a8047ebe --- /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/cmd/compile/internal/importer/testdata/issue15920.go b/src/cmd/compile/internal/importer/testdata/issue15920.go index b40202616275836a6d5e43eec0f8d5cca29d1f74..c70f7d8267b2f9209cf5f52a0ca7fe1bcc303649 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 e412f353ad2e6d7cbca580ba24adb67acfe4c51e..c63ee821c959dafda6799ccc8df77347221ad46a 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 a9dc1d7f083b2eae0353e51fff547b2776fc4476..e3dc98b4e1f9acdc9801c6a66e9305206f943cb5 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 95bef42280e9b4283bcec8bb32993ffc4999da87..8923373e5fa44d57d25ce1b4ccdc3a480360c74f 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 34a20eaa1451eca59573898adcad40c3a6a58e26..9e2e7057653725fc8ce963b5768828b3d9a88b42 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 2f8eb5ced047c4ae88aadad7a34b688a2ad838a8..227fc092519212f30793e1266fe619858ac28bef 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. diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index d6b4ced4e157cd46a2dbbcc814635453f32e198e..716a7fbcd93a25900e204efa575a3a532aabd6fd 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,60 +193,36 @@ func CanInline(fn *ir.Func) { } } -// 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) +// 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. - case ir.ONAME: - n := n.(*ir.Name) - switch n.Class { - case ir.PFUNC: - Inline_Flood(n, exportsym) - exportsym(n) - case ir.PEXTERN: - exportsym(n) + 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) } + } + }) - 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) + 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) } } - // 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) + return true } // hairyVisitor visits a function body to determine its inlining @@ -295,13 +273,43 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { } } } + if n.X.Op() == ir.OMETHEXPR { + if meth := ir.MethodExprName(n.X); meth != nil { + 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 + } + } + } + } if ir.IsIntrinsicCall(n) { // Treat like any other node. 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 } @@ -309,28 +317,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: @@ -370,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 @@ -402,35 +389,18 @@ 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) { // 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: @@ -445,7 +415,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: @@ -499,9 +469,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() ?? @@ -544,37 +511,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, @@ -597,21 +533,33 @@ 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 } + 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. 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 + } + } } } @@ -619,72 +567,31 @@ 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.OCALLFUNC, ir.OCALLMETH: - n := n.(*ir.CallExpr) - if n.NoInline { - return n - } - } + case ir.OCALLMETH: + base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") - 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) } 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) } - - 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.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 } @@ -740,7 +647,12 @@ var inlgen int // when producing output for debugging the compiler itself. var SSADumpInline = func(*ir.Func) {} -// If n is a call node (OCALLFUNC or OCALLMETH), and fn is an ONAME node for a +// 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 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) @@ -773,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 @@ -793,38 +726,90 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b defer func() { inlMap[fn] = false }() - if base.Debug.TypecheckInl == 0 { - typecheck.ImportedBody(fn) + + typecheck.FixVariadicCall(n) + + 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) } - SSADumpInline(fn) + 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) - ninit := n.Init() + if base.Flag.LowerM > 2 { + fmt.Printf("%v: After inlining %+v\n\n", ir.Line(res), res) + } - // 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 - for callee.Op() == ir.OCONVNOP { + 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) - ninit.Append(ir.TakeInit(conv)...) + 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) } - if callee.Op() != ir.ONAME && callee.Op() != ir.OCLOSURE && callee.Op() != ir.OMETHEXPR { - base.Fatalf("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 +// 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 := call.Init() + + // For normal function calls, the function callee expression + // may contain side effects. Make sure to preserve these, + // if necessary (#42703). + if call.Op() == ir.OCALLFUNC { + CalleeEffects(&ninit, call.X) } // Make temp names to use instead of the originals. @@ -854,25 +839,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() { @@ -882,7 +848,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) @@ -905,61 +870,23 @@ 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 sel.X == nil { - base.Fatalf("method call without receiver: %+v", n) - } - as.Rhs.Append(sel.X) + if call.Op() == ir.OCALLMETH { + base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck") } - 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 + as.Rhs.Append(call.Args...) 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 { + if !fn.Inl.CanDelayResults { // Zero the return parameters. for _, n := range retvars { ninit.Append(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name))) @@ -972,40 +899,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 @@ -1026,26 +934,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, @@ -1058,8 +951,10 @@ 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()) n.Curfn = ir.CurFunc // the calling function, not the called one n.SetAddrtaken(var_.Addrtaken()) @@ -1071,18 +966,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.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 -} - -// 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.SetTypecheck(1) n.Class = ir.PAUTO n.SetUsed(true) n.Curfn = ir.CurFunc // the calling function, not the called one @@ -1099,10 +983,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. @@ -1157,17 +1037,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) { @@ -1200,6 +1084,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) } @@ -1222,38 +1108,27 @@ 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 - // 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 - 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 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(), true) + // 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") @@ -1303,13 +1178,10 @@ 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) - if oldfn.ClosureCalled() { - typecheck.Callee(m) - } else { - typecheck.Expr(m) - } - return m + newclo := newfn.OClosure + newclo.SetPos(newClosurePos) + newclo.SetInit(subst.list(n.Init())) + return typecheck.Expr(newclo) } // node recursively copies a node from the saved pristine body of the @@ -1376,7 +1248,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()) @@ -1391,7 +1263,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 @@ -1404,7 +1276,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 @@ -1412,9 +1284,8 @@ 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 - p := fmt.Sprintf("%s·%d", n.Label.Name, inlgen) - m.Label = typecheck.Lookup(p) + m.SetInit(nil) + m.Label = translateLabel(n.Label) return m case ir.OLABEL: @@ -1425,9 +1296,8 @@ 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 - p := fmt.Sprintf("%s·%d", n.Label.Name, inlgen) - m.Label = typecheck.Lookup(p) + m.SetInit(nil) + m.Label = translateLabel(n.Label) return m case ir.OCLOSURE: @@ -1439,6 +1309,27 @@ 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, RANGE loops or SWITCH + switch m.Op() { + case ir.OFOR: + m := m.(*ir.ForStmt) + m.Label = translateLabel(m.Label) + return m + + 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) { case *ir.AssignStmt: if lhs, ok := m.X.(*ir.Name); ok && lhs.Defn == &subst.defnMarker { @@ -1455,6 +1346,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/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index f70645f07913f8c309023d0fc84208d8e09b85b3..f526d987a7b20e6318655445319c30a7a1cda058 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -142,28 +142,15 @@ 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 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 + NoInline bool } func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr { @@ -181,8 +168,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 } } @@ -192,8 +183,10 @@ type ClosureExpr struct { miniExpr Func *Func `mknode:"-"` Prealloc *Name + 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 @@ -277,12 +270,12 @@ 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 } } -// An IndexExpr is an index expression X[Y]. +// An IndexExpr is an index expression X[Index]. type IndexExpr struct { miniExpr X Node @@ -323,26 +316,24 @@ 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 { miniExpr Body Nodes - ReturnVars Nodes + ReturnVars Nodes // must be side-effect free } func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { @@ -354,6 +345,21 @@ 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) + } + 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] +} + // 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. @@ -448,6 +454,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 @@ -494,10 +514,15 @@ 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 + Prealloc *Name // preallocated storage for OMETHVALUE, if any } func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr { @@ -511,7 +536,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 } } @@ -652,6 +677,38 @@ 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 +} + +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 { @@ -678,6 +735,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 @@ -773,6 +835,11 @@ func StaticValue(n Node) Node { continue } + if n.Op() == OINLCALL { + n = n.(*InlinedCallExpr).SingleResult() + continue + } + n1 := staticValue1(n) if n1 == nil { return n @@ -1071,7 +1138,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 f2ae0f7606ee7ba04d8b219f1330de8ecf18a121..033188547b61ca65c35e4d4e671db419e30e7bdb 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, @@ -237,7 +238,7 @@ var OpPrec = []int{ ODOTTYPE: 8, ODOT: 8, OXDOT: 8, - OCALLPART: 8, + OMETHVALUE: 8, OMETHEXPR: 8, OPLUS: 7, ONOT: 7, @@ -385,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) @@ -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 @@ -558,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] } @@ -567,6 +568,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) @@ -709,6 +715,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 @@ -752,7 +762,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 { @@ -804,6 +814,7 @@ func exprFmt(n Node, s fmt.State, prec int) { case OCONV, OCONVIFACE, + OCONVIDATA, OCONVNOP, OBYTES2STR, ORUNES2STR, @@ -854,6 +865,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 { @@ -986,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. @@ -1041,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. @@ -1112,18 +1132,27 @@ 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() { - 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()) + // 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()) } - pos := base.Ctxt.PosTable.Pos(n.Pos()) - file := filepath.Base(pos.Filename()) - fmt.Fprintf(w, " # %s%s:%d", pfx, file, pos.Line()) } } @@ -1222,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() diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 20fe965711df33896e2f8025ea91b450a863dc4d..41c96079f75df3ceed4c695ed686f89f939a5415 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 @@ -39,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 @@ -166,6 +167,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. @@ -190,13 +196,14 @@ 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 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 + funcClosureCalled // closure is only immediately called; used by escape analysis ) type SymAndPos struct { @@ -210,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 } @@ -224,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) } @@ -272,6 +281,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" } @@ -279,7 +299,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 @@ -296,8 +316,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)) } } @@ -306,3 +326,109 @@ 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. +// 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(hidden) + + 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) { + 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) + } + + 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/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index a7ff4ac9c77a1a122b8fd558dd69f6b83e4879cb..eeb74081fb8bc51724e761f3579dc660416490bb 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/ir/name.go b/src/cmd/compile/internal/ir/name.go index b6c68bc5e01a4b33d8b590f29658886446584fbf..1d4110c73cf731ac343a5b8395a917663b902e8f 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 @@ -51,6 +52,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 @@ -143,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. @@ -358,39 +364,74 @@ func (n *Name) Byval() bool { return n.Canonical().flags&nameByval != 0 } +// 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()) + c.Curfn = fn + c.Class = PAUTOHEAP + c.SetIsClosureVar(true) + 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 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/ir/node.go b/src/cmd/compile/internal/ir/node.go index af559cc0820cc3e74ebd3065630e558c008e3e53..4fdee5010b660c1b8cbab3e02b1c6db068ffdd79 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) @@ -171,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) @@ -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) @@ -249,14 +250,16 @@ 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) 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 @@ -317,13 +320,30 @@ 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 // 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 - 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 ) +// 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. @@ -436,18 +456,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. @@ -563,7 +584,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 OuterValue: %v", n) case ODOT: nn := nn.(*SelectorExpr) n = nn.X diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index 22855d7163f44a6e9d51586c60cabc3c397dccff..44988880c8c2a7a52a37517cc57d361e3b3ab144 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -463,6 +463,62 @@ 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 + 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 @@ -947,6 +1003,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 @@ -1259,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/op_string.go b/src/cmd/compile/internal/ir/op_string.go index 405a0c6b3c985851c4dbbf68c5fd8990a61e06cf..b8cee718182c08889eb73e6493d0c67ddb0e7b59 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -41,18 +41,18 @@ 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[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[OCONVIDATA-44] _ = x[OCONVNOP-45] _ = x[OCOPY-46] _ = x[ODCL-47] @@ -109,65 +109,72 @@ 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[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[ODYNAMICDOTTYPE-154] + _ = x[ODYNAMICDOTTYPE2-155] + _ = x[ODYNAMICTYPE-156] + _ = x[OTAILCALL-157] + _ = x[OGETG-158] + _ = x[OGETCALLERPC-159] + _ = x[OGETCALLERSP-160] + _ = x[OEND-161] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGEND" +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, 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, 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/package.go b/src/cmd/compile/internal/ir/package.go index e4b93d113eda9c89b44512e2e5957c977df15a03..3896e2b91b1177dbc41977960d7fe26648e88d6e 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/ir/scc.go b/src/cmd/compile/internal/ir/scc.go index 83c6074170b31370e0e6c6e71f35e56533204d2b..a42951c1dda2de5676c496e1b9cfe45971e54ed5 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) } @@ -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] diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 8115012f97852c030d59b0e74bdd0cad17825916..e7d0d873b781ef79e43fa81d2447a139a54cdea5 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 @@ -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 { @@ -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/ir/symtab.go b/src/cmd/compile/internal/ir/symtab.go index 61727fb1c4b004d52e4942631e200ce837f791f4..b204a1d544e7b4e2ba9835d1b7c27f529082adf6 100644 --- a/src/cmd/compile/internal/ir/symtab.go +++ b/src/cmd/compile/internal/ir/symtab.go @@ -11,33 +11,36 @@ 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 + Asanread *obj.LSym + Asanwrite *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 @@ -68,5 +71,4 @@ var Pkgs struct { Go *types.Pkg Itab *types.Pkg Runtime *types.Pkg - Unsafe *types.Pkg } diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index a903ea8cd45543faebe7c9bce30c428f318b6a1b..63dd673dcdf11c9440139583a0252b22c384cdd6 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -300,11 +300,36 @@ 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) +} + +// 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/ir/val.go b/src/cmd/compile/internal/ir/val.go index 03c320e205dbfdf8b6b46eb7d3d9adcc8295c46d..bfe7d2bb436c8999631fdbf364c7c766006118a5 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 (%v) does not represent %v (%v)", t, t.Kind(), v, v.Kind()) } } diff --git a/src/cmd/compile/internal/liveness/arg.go b/src/cmd/compile/internal/liveness/arg.go new file mode 100644 index 0000000000000000000000000000000000000000..2ca5d095aa91095591eff61171f5922046caf48f --- /dev/null +++ b/src/cmd/compile/internal/liveness/arg.go @@ -0,0 +1,339 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package liveness + +import ( + "fmt" + + "cmd/compile/internal/base" + "cmd/compile/internal/bitvec" + "cmd/compile/internal/ir" + "cmd/compile/internal/objw" + "cmd/compile/internal/ssa" + "cmd/internal/obj" + "cmd/internal/objabi" +) + +// Argument liveness tracking. +// +// For arguments passed in registers, this file tracks if their spill slots +// are live for runtime traceback. An argument spill slot is live at a PC +// if we know that an actual value has stored into it at or before this point. +// +// Stack args are always live and not tracked in this code. Stack args are +// laid out before register spill slots, so we emit the smallest offset that +// needs tracking. Slots before that offset are always live. That offset is +// usually the offset of the first spill slot. But if the first spill slot is +// always live (e.g. if it is address-taken), it will be the offset of a later +// one. +// +// The liveness information is emitted as a FUNCDATA and a PCDATA. +// +// FUNCDATA format: +// - start (smallest) offset that needs tracking (1 byte) +// - a list of bitmaps. +// In a bitmap bit i is set if the i-th spill slot is live. +// +// At a PC where the liveness info changes, a PCDATA indicates the +// byte offset of the liveness map in the FUNCDATA. PCDATA -1 is a +// special case indicating all slots are live (for binary size +// saving). + +const allLiveIdx = -1 + +// name and offset +type nameOff struct { + n *ir.Name + off int64 +} + +func (a nameOff) FrameOffset() int64 { return a.n.FrameOffset() + a.off } +func (a nameOff) String() string { return fmt.Sprintf("%v+%d", a.n, a.off) } + +type blockArgEffects struct { + livein bitvec.BitVec // variables live at block entry + liveout bitvec.BitVec // variables live at block exit +} + +type argLiveness struct { + fn *ir.Func + f *ssa.Func + args []nameOff // name and offset of spill slots + idx map[nameOff]int32 // index in args + + be []blockArgEffects // indexed by block ID + + bvset bvecSet // Set of liveness bitmaps, used for uniquifying. + + // Liveness map indices at each Value (where it changes) and Block entry. + // During the computation the indices are temporarily index to bvset. + // At the end they will be index (offset) to the output funcdata (changed + // in (*argLiveness).emit). + blockIdx map[ssa.ID]int + valueIdx map[ssa.ID]int +} + +// ArgLiveness computes the liveness information of register argument spill slots. +// An argument's spill slot is "live" if we know it contains a meaningful value, +// that is, we have stored the register value to it. +// Returns the liveness map indices at each Block entry and at each Value (where +// it changes). +func ArgLiveness(fn *ir.Func, f *ssa.Func, pp *objw.Progs) (blockIdx, valueIdx map[ssa.ID]int) { + if f.OwnAux.ABIInfo().InRegistersUsed() == 0 || base.Flag.N != 0 { + // No register args. Nothing to emit. + // Or if -N is used we spill everything upfront so it is always live. + return nil, nil + } + + lv := &argLiveness{ + fn: fn, + f: f, + idx: make(map[nameOff]int32), + be: make([]blockArgEffects, f.NumBlocks()), + blockIdx: make(map[ssa.ID]int), + valueIdx: make(map[ssa.ID]int), + } + // Gather all register arg spill slots. + for _, a := range f.OwnAux.ABIInfo().InParams() { + n, ok := a.Name.(*ir.Name) + if !ok || len(a.Registers) == 0 { + continue + } + _, offs := a.RegisterTypesAndOffsets() + for _, off := range offs { + if n.FrameOffset()+off > 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 3431f54ede84e09bec45272d044247e115eb59d2..60b25938677c85c1ce7c07be102159230f506637 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 f5c2ef7709e515c376cc181c8e338bd51a1b33d8..3202e506c8f913aef4c14aad66a388b6b8971cc2 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" @@ -274,7 +273,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 @@ -855,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, } } @@ -903,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 { @@ -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. @@ -1322,19 +1326,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 @@ -1424,6 +1418,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))) @@ -1440,7 +1435,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) } @@ -1450,7 +1445,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/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go index 71976174b03517def512290e47d86a4980a02963..902cbc8091f1eb1e56b1c0507cd25b19b52c78c1 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,8 +220,8 @@ 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: from return (*int)(~R0) (return)"}]}`) + `{"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 ~R0 (return)"}]}`) }) } diff --git a/src/cmd/compile/internal/mips/galign.go b/src/cmd/compile/internal/mips/galign.go index f892923ba038f32a370873af79a9671e55e65a1b..4e6897042ec04ce2e81fa58960a26541fa5aaeb0 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/mips/ssa.go b/src/cmd/compile/internal/mips/ssa.go index e0447f38cbf23347c05a831d304581259eb9b092..6326f966bf2158807d6bdab361a19393c884f831 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/galign.go b/src/cmd/compile/internal/mips64/galign.go index af81366e51bdf51c4cd88b55da03440da29773c6..412bc71aab270d97befa5dd3296ad381db180dcc 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/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go index e821a00876fa799bc6b0a4413ed48acb445e336e..990b9788f765e39974873f07f544b218b171df6f 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/noder/codes.go b/src/cmd/compile/internal/noder/codes.go new file mode 100644 index 0000000000000000000000000000000000000000..f8cb7729acc2287a13f626d9ab8ce495701b6711 --- /dev/null +++ b/src/cmd/compile/internal/noder/codes.go @@ -0,0 +1,124 @@ +// 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 + exprConvert +) + +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/decl.go b/src/cmd/compile/internal/noder/decl.go index 4ca2eb4740a4916e171d2cfe278a38c9b472e9f1..df1ca1c5055e0e2b497178fc063599b0375fb147 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -18,43 +18,48 @@ 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) { - // TODO(mdempsky): Merge with gcimports so we don't have to import - // packages twice. - g.pragmaFlags(decl.Pragma, 0) - ipkg := importfile(decl) - if ipkg == ir.Pkgs.Unsafe { + // Get the imported package's path, as resolved already by types2 + // and gcimporter. This is the same path as would be computed by + // parseImportPath. + switch pkgNameOf(g.info, decl).Imported().Path() { + case "unsafe": p.importedUnsafe = true - } - if ipkg.Path == "embed" { + case "embed": p.importedEmbed = true } } +// 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) @@ -81,6 +86,18 @@ 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 + 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 = t2.(*types2.Named).Obj().Name() + "." + g.curDecl + } + fn := ir.NewFunc(g.pos(decl)) fn.Nname, _ = g.def(decl.Name) fn.Nname.Func = fn @@ -90,29 +107,72 @@ 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) + 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) + } + } + + 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) } - g.funcBody(fn, decl.Recv, decl.Type, decl.Body) + haveEmbed := g.haveEmbed + g.curDecl = "" + g.later(func() { + defer func(b bool) { g.haveEmbed = b }(g.haveEmbed) + + g.haveEmbed = haveEmbed + 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) { + // 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. + g.curDecl = decl.Name.Value 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)) + g.curDecl = "" return } @@ -122,8 +182,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) @@ -154,21 +213,30 @@ 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).TypeParams() + if n := tparams.Len(); n > 0 { + rparams := make([]*types.Type, n) + for i := range rparams { + rparams[i] = g.typ(tparams.At(i)) + } + // This will set hasTParam flag if any rparams are not concrete types. + ntyp.SetRParams(rparams) } types.ResumeCheckSize() + g.curDecl = "" if otyp, ok := otyp.(*types2.Named); ok && otyp.NumMethods() != 0 { 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 + g.curDecl = "" } ntyp.Methods().Set(methods) } @@ -178,57 +246,78 @@ 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) } - values := g.exprList(decl.Values) 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) } - var as2 *ir.AssignListStmt - if len(values) != 0 && len(names) != len(values) { - as2 = ir.NewAssignListStmt(pos, ir.OAS2, make([]ir.Node, len(names)), values) - } + haveEmbed := g.haveEmbed + do := func() { + defer func(b bool) { g.haveEmbed = b }(g.haveEmbed) - for i, name := range names { - if ir.CurFunc != nil { - out.Append(ir.NewDecl(pos, ir.ODCL, name)) + g.haveEmbed = haveEmbed + values := g.exprList(decl.Values) + + 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 + + for i, name := range names { + if ir.CurFunc != nil { + out.Append(ir.NewDecl(pos, ir.ODCL, name)) } - lhs := []ir.Node{as.X} - rhs := []ir.Node{} - if as.Y != nil { - rhs = []ir.Node{as.Y} + 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 + } + 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) } - transformAssign(as, lhs, rhs) - as.X = lhs[0] - if as.Y != nil { - as.Y = rhs[0] + } + if as2 != nil { + if !g.delayTransform() { + transformAssign(as2, as2.Lhs, as2.Rhs) } - as.SetTypecheck(1) - out.Append(as) + 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/decoder.go b/src/cmd/compile/internal/noder/decoder.go new file mode 100644 index 0000000000000000000000000000000000000000..2c18727420aec23281eac633cb89f31e1b30efce --- /dev/null +++ b/src/cmd/compile/internal/noder/decoder.go @@ -0,0 +1,302 @@ +// 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" + "runtime" + "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) 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 { + 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) + return r.rawVarint() +} + +func (r *decoder) uint64() uint64 { + r.sync(syncUint64) + return r.rawUvarint() +} + +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) + return r.rawReloc(k, r.len()) +} + +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) value() constant.Value { + r.sync(syncValue) + 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 0000000000000000000000000000000000000000..b07b3a4a480573b8a2279bf9dce2df1445608e22 --- /dev/null +++ b/src/cmd/compile/internal/noder/encoder.go @@ -0,0 +1,285 @@ +// 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" + "runtime" + + "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 + + encodingRelocHeader bool + + 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. + 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 { + 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) 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 !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)))) + } +} + +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) + w.rawVarint(x) +} + +func (w *encoder) uint64(x uint64) { + w.sync(syncUint64) + w.rawUvarint(x) +} + +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) + w.len(w.rawReloc(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) value(val constant.Value) { + w.sync(syncValue) + 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/export.go b/src/cmd/compile/internal/noder/export.go new file mode 100644 index 0000000000000000000000000000000000000000..1a296e22c8489b803fedf0ed2965daa1fe8be5c1 --- /dev/null +++ b/src/cmd/compile/internal/noder/export.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 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 + 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, oldLen) + if useNewExport { + fmt.Printf("BenchmarkNewExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, newLen) + } + } +} diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index c7695ed920435291bab7c64a0cbfdfb08b8b8a7e..6891d1ec30dac2244a87ebe494ace67058b2f611 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 } @@ -46,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, @@ -67,14 +73,16 @@ 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) 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 @@ -82,6 +90,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: @@ -101,68 +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 && 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[i] = ir.TypeNode(g.typ(targ)) - } - if fun.Op() == ir.OFUNCINST { - // Replace explicit type args with the full list that - // 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) - inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs) - typed(fun.Type(), 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 && 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[i] = ir.TypeNode(g.typ(targ)) - } - } 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 - return 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) - typed(g.typ(typ), n) - return n - case *syntax.ParenExpr: - return g.expr(expr.X) // skip parens; unneeded after parse+typecheck + // 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. @@ -174,17 +146,37 @@ 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 !g.delayTransform() { + transformSlice(n) + } + return n 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: - 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 !g.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 && !g.delayTransform() { + return transformAdd(n) + } + return n } default: @@ -193,7 +185,28 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { } } -// selectorExpr resolves the choice of ODOT, ODOTPTR, OCALLPART (eventually +// 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) + 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. func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.SelectorExpr) ir.Node { @@ -222,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) @@ -259,24 +266,26 @@ 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 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 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()) + 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.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) - // 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)) + xt := deref(x.Type()) + targs := make([]ir.Node, len(xt.RParams())) + for i := range targs { + targs[i] = ir.TypeNode(xt.RParams()[i]) } // Create function instantiation with the type @@ -299,27 +308,18 @@ 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.Type { - r := selinfo.Recv() - if p := types2.AsPointer(r); p != nil { - r = p.Elem() - } - n := types2.AsNamed(r) - if n == nil { - base.Fatalf("Incorrect type for selinfo %v", selinfo) - } - return n.TArgs() +func (g *irgen) exprList(expr syntax.Expr) []ir.Node { + return g.exprs(unpackListExpr(expr)) } -func (g *irgen) exprList(expr syntax.Expr) []ir.Node { +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} } } @@ -338,41 +338,50 @@ 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.StructuralType(typ).(*types2.Struct) exprs := make([]ir.Node, len(lit.ElemList)) 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) } + 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] = g.expr(elem) + 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 { - fn := ir.NewFunc(g.pos(expr)) - fn.SetIsHiddenClosure(ir.CurFunc != nil) + fn := ir.NewClosureFunc(g.pos(expr), ir.CurFunc != nil) + 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) @@ -386,9 +395,14 @@ 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 + 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 { @@ -398,3 +412,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/frames_go1.go b/src/cmd/compile/internal/noder/frames_go1.go new file mode 100644 index 0000000000000000000000000000000000000000..d00e0f51f9f8f8d4fda8dc9fe3a26d6b8fb13332 --- /dev/null +++ b/src/cmd/compile/internal/noder/frames_go1.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 !go1.7 +// +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 0000000000000000000000000000000000000000..48d77625b41d11105e73f218164c3c3395832574 --- /dev/null +++ b/src/cmd/compile/internal/noder/frames_go17.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.7 +// +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/func.go b/src/cmd/compile/internal/noder/func.go index 702138157c53b8186760e616c9541aa0e90670d6..6077b348a5c73e6bc123ebb2091d20212ada72df 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/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 9da0e493007a0687899eb59fe64f2eaa03d95e0c..5524673e6679666f2befb111f8a10ec3af680c85 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.IsTypeParam() { + ir.AssertValidTypeForConst(typ, val) + } + return val +} + func Nil(pos src.XPos, typ *types.Type) ir.Node { return typed(typ, ir.NewNilExpr(pos)) } @@ -51,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 } @@ -63,39 +85,31 @@ 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) - 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) + 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 } } 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. - 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) @@ -103,24 +117,27 @@ 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: - // - // 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. + // For most Builtin ops, we delay doing transformBuiltin if any of the + // args have type params, for a variety of reasons: // - // 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 + // OALIGNOF, OSIZEOF: can be eval'ed to a constant until types known. 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, 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 @@ -137,10 +154,8 @@ 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.OCALLPART { + if fun.Op() == ir.OMETHVALUE { op := ir.ODOTMETH if fun.X.Type().IsInterface() { op = ir.ODOTINTER @@ -152,49 +167,29 @@ 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 + 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). 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. + // (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. 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 } -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) - 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 - } typed(typ, n) - transformCompare(n) return n } @@ -225,7 +220,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 @@ -264,34 +259,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) - 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) 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) - 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) return n } @@ -321,5 +301,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/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index 701e9001c859ea8d2819b0e2850a1604e8e0c978..58dffbad1e4d5c0c11850383ea5e391d9d6ea59d 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" @@ -32,8 +31,24 @@ import ( "cmd/internal/src" ) -// Temporary import helper to get type2-based type-checking going. +// 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, env *types2.Context, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { + panic("unexpected new export data payload") +} + type gcimports struct { + ctxt *types2.Context packages map[string]*types2.Package } @@ -46,13 +61,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.ctxt, m.packages) + return pkg, err } func isDriveLetter(b byte) bool { @@ -117,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 { @@ -175,160 +187,242 @@ 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) + pkg, _, err := readImportFile(path, typecheck.Target, nil, nil) if err != nil { - base.Errorf("import path must be a string") + base.Errorf("%s", err) return nil } + if pkg != types.UnsafePkg && pkg.Height >= myheight { + myheight = pkg.Height + 1 + } + return pkg +} + +func parseImportPath(pathLit *syntax.BasicLit) (string, error) { + if pathLit.Kind != syntax.StringLit { + return "", errors.New("import path must be a string") + } + + path, err := strconv.Unquote(pathLit.Value) + if err != nil { + return "", errors.New("import path must be a string") + } + if err := checkImportPath(path, false); err != nil { - base.Errorf("%s", err.Error()) - return nil + return "", err } + return path, err +} + +// 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.Context, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) { path, err = resolveImportPath(path) if err != nil { - base.Errorf("%s", err) - return nil + return + } + + if path == "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? + if !pkg1.Direct { + pkg1.Direct = true + target.Imports = append(target.Imports, pkg1) + } + + return } - importpkg := types.NewPkg(path, "") - if importpkg.Direct { - return importpkg // already fully loaded + pkg1 = types.NewPkg(path, "") + if packages != nil { + pkg2 = packages[path] + assert(pkg1.Direct == (pkg2 != nil && pkg2.Complete())) } - importpkg.Direct = true - typecheck.Target.Imports = append(typecheck.Target.Imports, importpkg) - if path == "unsafe" { - return importpkg // initialized with universe + 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() - // check object header - p, err := imp.ReadString('\n') + r, end, newsize, err := findExportData(f) if err != nil { - base.Errorf("import %s: reading input: %v", file, err) - base.ErrorExit() + return } - if p == "!\n" { // package archive - // package export block should be first - sz := archive.ReadHeader(imp.Reader, "__.PKGDEF") - if sz <= 0 { - base.Errorf("import %s: not a package file", file) - base.ErrorExit() - } - p, err = imp.ReadString('\n') + if base.Debug.Export != 0 { + fmt.Printf("importing %s (%s)\n", path, f.Name()) + } + + 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 { - base.Errorf("import %s: reading input: %v", file, err) - base.ErrorExit() + return } - } - if !strings.HasPrefix(p, "go object ") { - base.Errorf("import %s: not a go object file: %s", file, p) - base.ErrorExit() - } - q := objabi.HeaderString() - if p != q { - base.Errorf("import %s: object is [%s] expected [%s]", file, p, q) - base.ErrorExit() - } + pkg2, err = newReadImportFunc(data, pkg1, env, packages) + } else { + // We only have old data. Oh well, fall back to the legacy importers. + haveLegacyImports = true - // process header lines - for { - p, err = imp.ReadString('\n') + 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 + } + + pos := r.Offset() + + // 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 { - base.Errorf("import %s: reading input: %v", file, err) - base.ErrorExit() + return } - if p == "\n" { - break // header ends with blank line + + typecheck.ReadImports(pkg1, data) + + if packages != nil { + pkg2, err = importer.ImportData(packages, data, path) + if err != nil { + return + } } } - // Expect $$B\n to signal binary import format. + 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, newsize int64, err error) { + r = bio.NewReader(f) + + // check object header + line, err := r.ReadString('\n') + if err != nil { + return + } - // look for $$ - var c byte - for { - c, err = imp.ReadByte() + if line == "!\n" { // package archive + // package export block should be first + sz := int64(archive.ReadHeader(r.Reader, "__.PKGDEF")) + if sz <= 0 { + err = errors.New("not a package file") + return + } + end = r.Offset() + sz + line, err = r.ReadString('\n') if err != nil { - break + return } - if c == '$' { - c, err = imp.ReadByte() - if c == '$' || err != nil { - break - } + } 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 { + return } + end = fi.Size() } - // get character after $$ - if err == nil { - c, _ = imp.ReadByte() + if !strings.HasPrefix(line, "go object ") { + err = fmt.Errorf("not a go object file: %s", line) + return + } + if expect := objabi.HeaderString(); line != expect { + err = fmt.Errorf("object is [%s] expected [%s]", line, expect) + return } - 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) + // 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 + } } - imp.ReadByte() // skip \n after $$B - c, err = imp.ReadByte() + line, err = r.ReadString('\n') if err != nil { - base.Errorf("import %s: reading input: %v", file, err) - base.ErrorExit() + return } + } - // 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) + // Expect $$B\n to signal binary import format. + if line != "$$B\n" { + err = errors.New("old export format no longer supported (recompile library)") + return + } + + 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 + + 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) } - - if importpkg.Height >= myheight { - myheight = importpkg.Height + 1 - } - - return importpkg + return nil } // The linker uses the magic symbol prefixes "go." and "type." @@ -431,7 +525,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/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 3e0d3285ab916ec0661ba9601149a3209138f02c..e20939de6639026536b5d5a4fdb85938d689a6c9 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) (posMap, *types2.Package, *types2.Info) { if base.SyntaxErrors() != 0 { base.ErrorExit() } @@ -34,7 +34,13 @@ func check2(noders []*noder) { } // typechecking + ctxt := types2.NewContext() + importer := gcimports{ + ctxt: ctxt, + packages: map[string]*types2.Package{"unsafe": types2.Unsafe}, + } conf := types2.Config{ + Context: ctxt, GoVersion: base.Flag.Lang, IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode CompilerErrorMessages: true, // use error strings matching existing compiler errors @@ -42,27 +48,35 @@ 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), 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 } - 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) { + m, pkg, info := checkFiles(noders) + if base.Flag.G < 2 { os.Exit(0) } @@ -70,7 +84,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), @@ -82,6 +96,44 @@ func check2(noders []*noder) { } } +// 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 the instantiation that requires a subdictionary. Includes + // method and function calls (OCALL), function values (OFUNCINST), method + // values/expressions (OXDOT). + subDictCalls []ir.Node + // 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 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 + // 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 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 + + dictInfo *dictInfo +} + type irgen struct { target *ir.Package self *types2.Package @@ -92,12 +144,69 @@ type irgen struct { typs map[types2.Type]*types.Type marker dwarfgen.ScopeMarker - // Fully-instantiated generic types whose methods should be instantiated - instTypeList []*types.Type + // 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. + exprStmtOK bool + + // types which we need to finish, by doing g.fillinMethods. + typesToFinalize []*typeDelayInfo + + // 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 + + // 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 +} + +// 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) +} + +type delayInfo struct { + gf *ir.Name + targs []*types.Type + sym *types.Sym + off int + isMeth bool +} + +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() typecheck.TypecheckAllowed = true // Prevent size calculations until we set the underlying type @@ -107,7 +216,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, @@ -132,7 +241,6 @@ Outer: } } } - 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 @@ -156,8 +264,20 @@ Outer: types.ResumeCheckSize() // 3. Process all remaining declarations. - for _, declList := range declLists { - g.target.Decls = append(g.target.Decls, g.decls(declList)...) + 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 + + // 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 { @@ -167,26 +287,41 @@ Outer: } } - typecheck.DeclareUniverse() - for _, p := range noders { // Process linkname and cgo pragmas. p.processPragmas() // 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 }) } - // Create any needed stencils of generic functions - g.stencil() + 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() - // 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. + typecheck.DeclareUniverse() + + // 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 + // have been marked for export as appropriate. j := 0 for i, decl := range g.target.Decls { if decl.Op() != ir.ODCLFUNC || !decl.Type().HasTParam() { @@ -195,9 +330,17 @@ 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) { 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/linker.go b/src/cmd/compile/internal/noder/linker.go new file mode 100644 index 0000000000000000000000000000000000000000..2bc7f7c608ead06af328e49551dfb6f66e607791 --- /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) + 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 + if path == "" { + var ok bool + obj, ok = sym.Def.(*ir.Name) + + // Generic types and functions and declared constraint types won't + // have definitions. + // For now, just generically copy their extension data. + // TODO(mdempsky): Restore assertion. + if !ok && false { + base.Fatalf("missing definition for %v", sym) + } + } + + if obj != nil { + wext.sync(syncObject1) + switch tag { + case objFunc: + l.relocFuncExt(&wext, obj) + case objType: + l.relocTypeExt(&wext, obj) + case objVar: + l.relocVarExt(&wext, obj) + } + wext.flush() + } else { + l.relocCommon(pr, &wext, 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.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) { + r := pr.newDecoder(relocName, idx, syncObject1) + r.sync(syncSym) + r.sync(syncPkg) + path := pr.peekPkgPath(r.reloc(relocPkg)) + name := r.string() + assert(name != "") + + tag := codeObj(r.code(syncCodeObj)) + + return path, name, tag +} diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 5fcad096c28ae5f5aa413bfc1a0ead3f7212e630..b36db67a507a87f8cd6bd0a56791b4f34399cedc 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -5,9 +5,11 @@ package noder import ( + "errors" "fmt" "go/constant" "go/token" + "internal/buildcfg" "os" "path/filepath" "runtime" @@ -29,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 { mode |= syntax.AllowGenerics } @@ -75,6 +80,11 @@ func LoadPackage(filenames []string) { } base.Timer.AddEvent(int64(lines), "lines") + if base.Debug.Unified != 0 { + unified(noders) + return + } + if base.Flag.G != 0 { // Use types2 to type-check and possibly generate IR. check2(noders) @@ -109,45 +119,52 @@ 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) + } } } // 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++ { - 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++ } } @@ -172,13 +189,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. @@ -296,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 != "" { @@ -355,7 +381,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" { @@ -449,7 +475,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 } @@ -467,16 +493,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 { @@ -484,10 +509,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 @@ -625,6 +656,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 } @@ -914,6 +948,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])) } @@ -977,6 +1014,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 { @@ -986,11 +1025,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 } @@ -1198,7 +1237,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) @@ -1245,7 +1284,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 @@ -1497,7 +1536,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() { @@ -1507,13 +1546,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) @@ -1691,7 +1734,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, @@ -1780,24 +1823,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 != nil) + 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. @@ -1841,33 +1874,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\"") + if len(pragmaEmbeds) == 0 { return } - if len(decl.NameList) > 1 { - base.ErrorfAt(pos, "go:embed cannot apply to multiple vars") - 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 } @@ -1878,3 +1892,24 @@ 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") + 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/noder/object.go b/src/cmd/compile/internal/noder/object.go index 82cce1ace0fcff81856f1751498f009c2d5fa84b..37a995b5199cf70f127fd03feb92b9e27ef2973c 100644 --- a/src/cmd/compile/internal/noder/object.go +++ b/src/cmd/compile/internal/noder/object.go @@ -22,20 +22,35 @@ 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) } - 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. 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 } @@ -49,6 +64,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) @@ -101,25 +121,28 @@ 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)) } 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())) @@ -164,9 +187,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/posmap.go b/src/cmd/compile/internal/noder/posmap.go index a6d3e2d7ef4d9ac0aa241eede47c23b2c6595e85..f22628f845f7225c3862d00ada9066eaf7c0054e 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/quirks.go b/src/cmd/compile/internal/noder/quirks.go new file mode 100644 index 0000000000000000000000000000000000000000..914c5d2bd7115663dd34df2833e12dd86fa7bdb0 --- /dev/null +++ b/src/cmd/compile/internal/noder/quirks.go @@ -0,0 +1,450 @@ +// 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 satisfying +// toolstash -cmp is used. +func quirksMode() bool { + return base.Debug.UnifiedQuirks != 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.Crawl(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.Crawl(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.Crawl(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.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) + } + } + 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 0000000000000000000000000000000000000000..0bc9135999e0f050935e0c1558516d5a2ed19190 --- /dev/null +++ b/src/cmd/compile/internal/noder/reader.go @@ -0,0 +1,2460 @@ +// 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" + "internal/buildcfg" + "strings" + + "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" + "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 + dict *readerDict +} + +func (pri pkgReaderIndex) asReader(k reloc, marker syncMarker) *reader { + r := pri.pr.newReader(k, pri.idx, marker) + r.dict = pri.dict + 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 + + 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 + // instance. + + curfn *ir.Func + locals []*ir.Name + closureVars []*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 +} + +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 + + 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 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 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 + + 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, absFilename) + } else { + pos := r.pos0() + line := r.uint() + col := r.uint() + b = src.NewLinePragmaBase(pos, filename, absFilename, 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 { + 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 { + r.sync(syncType) + if r.bool() { + return typeInfo{idx: r.len(), derived: true} + } + return typeInfo{idx: r.reloc(relocType), derived: false} +} + +func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *types.Type { + idx := info.idx + var where **types.Type + if info.derived { + where = &dict.derivedTypes[idx] + idx = dict.derived[idx].idx + } else { + where = &pr.typs[idx] + } + + if typ := *where; typ != nil { + return typ + } + + r := pr.newReader(relocType, idx, syncTypeIdx) + r.dict = dict + + 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 prev := *where; prev != nil { + return prev + } + + 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) + } + + 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: + return r.dict.targs[r.len()] + + 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, types.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, false) +} + +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) + + 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, true) + } + + 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()) + for i := range explicits { + explicits[i] = r.typ() + } + + 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 { + rname := pr.newReader(relocName, idx, syncObject1) + _, sym := rname.qualifiedIdent() + tag := codeObj(rname.code(syncCodeObj)) + + if tag == objStub { + assert(!sym.IsBlank()) + switch sym.Pkg { + case types.BuiltinPkg, types.UnsafePkg: + return sym.Def.(ir.Node) + } + if pri, ok := objReader[sym]; ok { + return pri.pr.objIdx(pri.idx, nil, explicits) + } + if haveLegacyImports { + assert(len(explicits) == 0) + return typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) + } + base.Fatalf("unresolved stub: %v", sym) + } + + dict := pr.objDictIdx(sym, idx, implicits, explicits) + + r := pr.newReader(relocObj, idx, syncObject1) + rext := pr.newReader(relocObjExt, idx, syncObject1) + + r.dict = dict + rext.dict = dict + + 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 { + 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 objAlias: + name := do(ir.OTYPE, false) + setType(name, r.typ()) + name.SetAlias(true) + return name + + case objConst: + name := do(ir.OLITERAL, false) + typ := r.typ() + val := FixValue(typ, r.value()) + setType(name, typ) + setValue(name, val) + return name + + case objFunc: + if sym.Name == "init" { + sym = renameinit() + } + name := do(ir.ONAME, true) + setType(name, r.signature(sym.Pkg, nil)) + + name.Func = ir.NewFunc(r.pos()) + name.Func.Nname = name + + rext.funcExt(name) + return name + + case objType: + name := do(ir.OTYPE, true) + typ := types.NewNamed(name) + setType(name, typ) + + // Important: We need to do this before SetUnderlying. + rext.typeExt(name) + + // We need to defer CheckSize until we've called SetUnderlying to + // handle recursive types. + types.DeferCheckSize() + typ.SetUnderlying(r.typWrapped(false)) + types.ResumeCheckSize() + + methods := make([]*types.Field, r.len()) + for i := range methods { + methods[i] = r.method(rext) + } + if len(methods) != 0 { + typ.Methods().Set(methods) + } + + r.needWrapper(typ) + + return name + + case objVar: + name := do(ir.ONAME, false) + setType(name, r.typ()) + rext.varExt(name) + return name + } +} + +func (r *reader) mangle(sym *types.Sym) *types.Sym { + if !r.hasTypeParams() { + return sym + } + + var buf bytes.Buffer + buf.WriteString(sym.Name) + buf.WriteByte('[') + for i, targ := range r.dict.targs { + if i > 0 { + if i == r.dict.implicits { + buf.WriteByte(';') + } else { + buf.WriteByte(',') + } + } + buf.WriteString(targ.LinkString()) + } + buf.WriteByte(']') + return sym.Pkg.Lookup(buf.String()) +} + +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() + + 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)) + } + + dict.targs = append(implicits[:nimplicits:nimplicits], explicits...) + dict.implicits = nimplicits + + // For stenciling, we can just skip over the type parameters. + for range dict.targs[dict.implicits:] { + // Skip past bounds without actually evaluating them. + r.sync(syncType) + if r.bool() { + r.len() + } else { + 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() { + r.sync(syncTypeParamNames) + + for range r.dict.targs[r.dict.implicits:] { + r.pos() + r.localIdent() + } +} + +func (r *reader) method(rext *reader) *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) + setType(name, typ) + + name.Func = ir.NewFunc(r.pos()) + name.Func.Nname = name + + rext.funcExt(name) + + meth := types.NewField(name.Func.Pos(), sym, typ) + meth.Nname = name + meth.SetNointerface(name.Func.Pragma&ir.Nointerface != 0) + + 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 +} + +func (r *reader) hasTypeParams() bool { + return r.dict.hasTypeParams() +} + +func (dict *readerDict) hasTypeParams() bool { + return dict != nil && len(dict.targs) != 0 +} + +// @@@ 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()) + } + + // 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 + } + + fn.Pragma = r.pragmaFlag() + r.linkname(name) + + typecheck.Func(fn) + + 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 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 + // generated even for imported types. + var targs []*types.Type + targs = append(targs, r.dict.targs...) + 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 + +// 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 + + if fn.Nname.Defn == nil { + // Don't read in function body for imported functions. + // See comment in funcExt. + return + } + + if r.curfn == nil && !todoBodiesDone { + 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.closureVars = fn.ClosureVars + + ir.WithFunc(fn, func() { + r.funcargs(fn) + + if !r.bool() { + return + } + + body := r.stmts() + if body == nil { + pos := src.NoXPos + if quirksMode() { + pos = funcParamsEndPos(fn) + } + body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(pos, nil))} + } + fn.Body = body + fn.Endlineno = r.pos() + }) + + 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) + 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 enableSync { + 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) + if r.bool() { + return r.locals[r.len()] + } + return r.closureVars[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] + + // 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 { + 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 { + assert(ir.CurFunc == r.curfn) + 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(typecheck.Stmt(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() + + // 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 { + as := ir.NewAssignStmt(pos, name, nil) + as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name)) + out.Append(typecheck.Stmt(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) + 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) + 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() + + // 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() + + 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() + + 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 { + 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()) + 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 + +// expr reads and returns a typechecked expression. +func (r *reader) expr() (res ir.Node) { + defer func() { + if res != nil && res.Typecheck() == 0 { + base.FatalfAt(res.Pos(), "%v missed typecheck", res) + } + }() + + switch tag := codeExpr(r.code(syncExpr)); tag { + default: + panic("unhandled expression") + + case exprNone: + return nil + + case exprBlank: + // blank only allowed in LHS of assignments + // TODO(mdempsky): Handle directly in assignList instead? + return typecheck.AssignExpr(ir.BlankNode) + + case exprLocal: + return typecheck.Expr(r.useLocal()) + + case exprName: + // Callee instead of Expr allows builtins + // TODO(mdempsky): Handle builtins directly in exprCall, like method calls? + return typecheck.Callee(r.obj()) + + case exprType: + // 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 := r.typ() + val := FixValue(typ, r.value()) + op := r.op() + orig := r.string() + return typecheck.Expr(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() + 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() + pos := r.pos() + index := r.expr() + return typecheck.Expr(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 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 typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ)) + + case exprUnaryOp: + op := r.op() + pos := r.pos() + x := r.expr() + + switch op { + case ir.OADDR: + return typecheck.Expr(typecheck.NodAddrAt(pos, x)) + case ir.ODEREF: + return typecheck.Expr(ir.NewStarExpr(pos, x)) + } + return typecheck.Expr(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 typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y)) + } + return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y)) + + case exprCall: + 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() + return typecheck.Call(pos, fun, args, dots) + + case exprConvert: + typ := r.typ() + pos := r.pos() + x := r.expr() + return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, typ, x)) + } +} + +func (r *reader) compLit() ir.Node { + r.sync(syncCompLit) + pos := r.pos() + typ0 := r.typ() + + typ := typ0 + if typ.IsPtr() { + 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 := 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 +} + +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) + clo := fn.OClosure + ir.NameClosure(clo, r.curfn) + + setType(fn.Nname, xtype2) + if quirksMode() { + fn.Nname.Ntype = ir.TypeNodeAt(typPos, xtype2) + } + typecheck.Func(fn) + setType(clo, fn.Type()) + + fn.ClosureVars = make([]*ir.Name, 0, r.len()) + for len(fn.ClosureVars) < cap(fn.ClosureVars) { + ir.NewClosureVar(r.pos(), fn, r.useLocal()) + } + + r.addBody(fn) + + // TODO(mdempsky): Remove hard-coding of typecheck.Target. + return ir.UseClosure(clo, typecheck.Target) +} + +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 }() + + setType(tmpfn.Nname, fn.Type()) + r.curfn = tmpfn + + r.inlCaller = callerfn + r.inlCall = call + r.inlFunc = fn + r.inlTreeIndex = inlIndex + r.inlPosBases = make(map[*src.PosBase]*src.PosBase) + + r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars)) + for i, cv := range r.inlFunc.ClosureVars { + r.closureVars[i] = 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. Make sure to preserve these, + // if necessary (#42703). + if call.Op() == ir.OCALLFUNC { + inline.CalleeEffects(&init, call.X) + } + + var args ir.Nodes + if call.Op() == ir.OCALLMETH { + base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck") + } + 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) + + ir.WithFunc(r.curfn, func() { + r.curfn.Body = r.stmts() + r.curfn.Endlineno = r.pos() + + 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) + }) + + 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 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) + 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) + setType(tmpfn.Nname, fn.Type()) + + // Don't change parameter's Sym/Nname fields. + r.funarghack = true + + r.funcBody(tmpfn) + + ir.WithFunc(tmpfn, func() { + deadcode.Func(tmpfn) + }) + } + + 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 +} + +// @@@ Method wrappers + +// needWrapperTypes lists types for which we may need to generate +// method wrappers. +var needWrapperTypes []*types.Type + +// 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 + +// 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() { + 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. + // + // 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. + return r.p != localPkgReader && !r.hasTypeParams() +} + +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) + needWrapperTypes = append(needWrapperTypes, types.ErrorType) + + seen := make(map[string]*types.Type) + + for _, typ := range haveWrapperTypes { + wrapType(typ, target, seen, false) + } + haveWrapperTypes = nil + + for _, typ := range needWrapperTypes { + wrapType(typ, target, seen, true) + } + needWrapperTypes = nil + + for _, wrapper := range haveMethodValueWrappers { + wrapMethodValue(wrapper.rcvr, wrapper.method, target, false) + } + haveMethodValueWrappers = nil + + for _, wrapper := range needMethodValueWrappers { + wrapMethodValue(wrapper.rcvr, wrapper.method, target, true) + } + needMethodValueWrappers = nil +} + +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) { + 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) + } + for _, meth := range typ.AllMethods().Slice() { + if meth.Sym.IsBlank() || !meth.IsMethod() { + base.FatalfAt(meth.Pos, "invalid method: %v", meth) + } + + methodWrapper(0, typ, meth, target) + + // For non-interface types, we also want *T wrappers. + if !typ.IsInterface() { + 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() { + methodWrapper(2, typ, meth, target) + } + } + } +} + +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) + } + + sym := ir.MethodSym(wrapper, method.Sym) + base.Assertf(!sym.Siggen(), "already generated wrapper %v", sym) + 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 := newWrapperFunc(pos, sym, wrapper, method) + + 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) + + finishWrapperFunc(fn, target) +} + +func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) { + sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm") + if sym.Uniq() { + return + } + sym.SetUniq(true) + + // TODO(mdempsky): Use method.Pos instead? + pos := base.AutogeneratedPos + + fn := newWrapperFunc(pos, sym, nil, method) + sym.Def = fn.Nname + + // Declare and initialize variable holding receiver. + recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType) + + if !needed { + typecheck.Func(fn) + return + } + + addTailCall(pos, fn, recv, method) + + finishWrapperFunc(fn, target) +} + +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? + + name := ir.NewNameAt(pos, sym) + ir.MarkFunc(name) + name.Func = fn + name.Defn = fn + fn.Nname = name + + sig := newWrapperType(wrapper, method) + 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 + setType(name, param.Type) + + name.Curfn = fn + fn.Dcl = append(fn.Dcl, name) + + param.Nname = name + } + } + + defParams(ir.PPARAM, sig.Recvs()) + defParams(ir.PPARAM, sig.Params()) + defParams(ir.PPARAMOUT, sig.Results()) + + return fn +} + +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) +} + +// 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 +// 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 { + 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 + } + + 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 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? + + 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) + return + } + + ret := ir.NewReturnStmt(pos, nil) + ret.Results = []ir.Node{call} + fn.Body.Append(ret) +} diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go new file mode 100644 index 0000000000000000000000000000000000000000..9396c0c87c5e3501fd7ffbc4a025fc7ded331ef1 --- /dev/null +++ b/src/cmd/compile/internal/noder/reader2.go @@ -0,0 +1,508 @@ +// 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 ( + "cmd/compile/internal/base" + "cmd/compile/internal/syntax" + "cmd/compile/internal/types2" + "cmd/internal/src" +) + +type pkgReader2 struct { + pkgDecoder + + ctxt *types2.Context + imports map[string]*types2.Package + + posBases []*syntax.PosBase + pkgs []*types2.Package + typs []types2.Type +} + +func readPackage2(ctxt *types2.Context, imports map[string]*types2.Package, input pkgDecoder) *types2.Package { + pr := pkgReader2{ + pkgDecoder: input, + + ctxt: ctxt, + 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++ { + // 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) + + pkg.MarkComplete() + return pkg +} + +type reader2 struct { + decoder + + p *pkgReader2 + + dict *reader2Dict +} + +type reader2Dict struct { + bounds []typeInfo + + tparams []*types2.TypeParam + + derived []derivedInfo + derivedTypes []types2.Type +} + +type reader2TypeBound struct { + derived bool + boundIdx int +} + +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() + + if r.bool() { + b = syntax.NewTrimmedFileBase(filename, true) + } else { + pos := r.pos() + line := r.uint() + col := r.uint() + b = syntax.NewLineBase(pos, filename, true, 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 { + return r.p.typIdx(r.typInfo(), r.dict) +} + +func (r *reader2) typInfo() typeInfo { + r.sync(syncType) + if r.bool() { + return typeInfo{idx: r.len(), derived: true} + } + return typeInfo{idx: r.reloc(relocType), derived: false} +} + +func (pr *pkgReader2) typIdx(info typeInfo, dict *reader2Dict) types2.Type { + idx := info.idx + var where *types2.Type + if info.derived { + where = &dict.derivedTypes[idx] + idx = dict.derived[idx].idx + } else { + where = &pr.typs[idx] + } + + if typ := *where; typ != nil { + return typ + } + + r := pr.newReader(relocType, idx, syncTypeIdx) + r.dict = dict + + typ := r.doTyp() + assert(typ != nil) + + // See comment in pkgReader.typIdx explaining how this happens. + if prev := *where; prev != nil { + return prev + } + + *where = 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 { + t, _ := types2.Instantiate(r.p.ctxt, name.Type(), targs, false) + return t + } + return name.Type() + + case typeTypeParam: + return r.dict.tparams[r.len()] + + 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.Term, r.len()) + for i := range terms { + terms[i] = types2.NewTerm(r.bool(), r.typ()) + } + return types2.NewUnion(terms) +} + +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() + } + + return types2.NewInterfaceType(methods, embeddeds) +} + +func (r *reader2) signature(recv *types2.Var) *types2.Signature { + r.sync(syncSignature) + + params := r.params() + results := r.params() + variadic := r.bool() + + return types2.NewSignatureType(recv, nil, nil, 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) + + assert(!r.bool()) + + 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) { + rname := pr.newReader(relocName, idx, syncObject1) + + objPkg, objName := rname.qualifiedIdent() + assert(objName != "") + + tag := codeObj(rname.code(syncCodeObj)) + + if tag == objStub { + assert(objPkg == nil || objPkg == types2.Unsafe) + return objPkg, objName + } + + dict := pr.objDictIdx(idx) + + r := pr.newReader(relocObj, idx, syncObject1) + r.dict = dict + + 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 := r.typ() + val := r.value() + return types2.NewConst(pos, objPkg, objName, typ, val) + + case objFunc: + pos := r.pos() + tparams := r.typeParamNames() + sig := r.signature(nil) + sig.SetTypeParams(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.TypeParam, underlying types2.Type, methods []*types2.Func) { + tparams = r.typeParamNames() + + // 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() + } + + return + }) + + case objVar: + pos := r.pos() + typ := r.typ() + return types2.NewVar(pos, objPkg, objName, typ) + } + }) + + return objPkg, objName +} + +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) + } + + 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.TypeParam { + r.sync(syncTypeParamNames) + + // 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. + + r.dict.tparams = make([]*types2.TypeParam, len(r.dict.bounds)) + for i := range r.dict.bounds { + pos := r.pos() + pkg, name := r.localIdent() + + tname := types2.NewTypeName(pos, pkg, name, nil) + r.dict.tparams[i] = types2.NewTypeParam(tname, nil) + } + + for i, bound := range r.dict.bounds { + r.dict.tparams[i].SetConstraint(r.p.typIdx(bound, r.dict)) + } + + return r.dict.tparams +} + +func (r *reader2) method() *types2.Func { + r.sync(syncMethod) + pos := r.pos() + pkg, name := r.selector() + + rparams := r.typeParamNames() + sig := r.signature(r.param()) + sig.SetRecvTypeParams(rparams) + + _ = 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 0000000000000000000000000000000000000000..669a6182e62eb250dd2f0ac817e4b5712d06ece7 --- /dev/null +++ b/src/cmd/compile/internal/noder/reloc.go @@ -0,0 +1,42 @@ +// 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 + relocName + relocType + relocObj + relocObjExt + relocObjDict + relocBody + + numRelocs = iota +) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 3ebc8dff6d84322d2d5c2379e9497a87ebb1d73b..62c306b89e2e6862a725076a5b26e5cb9a89f68d 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -8,267 +8,750 @@ package noder import ( - "bytes" "cmd/compile/internal/base" + "cmd/compile/internal/inline" "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" - "strings" + "go/constant" ) -// For catching problems as we add more features -// TODO(danscales): remove assertions or replace with base.FatalfAt() +// Enable extra consistency checks. +const doubleCheck = false + func assert(p bool) { - if !p { - panic("assertion failed") + base.Assert(p) +} + +// 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{}) { + 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 -// 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) +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. + if preinliningMainScan { + n := len(typecheck.Target.Decls) + for i := 0; i < n; i++ { + g.scanForGenCalls(typecheck.Target.Decls[i]) + } + } - 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 - foundFuncInst := 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 - } - if n.Op() != ir.OCALL || n.(*ir.CallExpr).X.Op() != ir.OFUNCINST { - return - } + // 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 new instantiation and transform the various operations that need to make + // use of their dictionary. + 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 { + 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) + } + } + 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)) + // 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)) + 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) - st := g.getInstantiationForNode(inst) + 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) + // 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 // 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 + 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) + + 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 an OFUNCINST without a corresponding call in the - // above decl, 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. - // EditChildren is more expensive than Visit, so we only do this - // 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 + } + }) + + // 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) - return x } - edit(decl) + 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 } - if base.Flag.W > 1 && modified { - ir.Dump(fmt.Sprintf("\nmodified %v", decl), decl) + 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 *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 + 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 + valueMethod := false + 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.OMETHVALUE { + // 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. + // dictValue is the value to use for the dictionary argument. + target = g.getInstantiation(gf, targs, rcvrValue != nil).fun + dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, rcvrValue != nil) + if infoPrintMode { + dictkind := "Main dictionary" + if usingSubdict { + dictkind = "Sub-dictionary" + } + if rcvrValue == nil { + fmt.Printf("%s in %v for generic function value %v\n", dictkind, outer, inst.X) + } else { + fmt.Printf("%s in %v for generic method value %v\n", dictkind, outer, inst.X) + } + } + } 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, + // 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) + 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() { + if se.Sel == m.Sym { + gf = m.Nname.(*ir.Name) + 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).fun + dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, true) + if infoPrintMode { + dictkind := "Main dictionary" + if usingSubdict { + dictkind = "Sub-dictionary" + } + fmt.Printf("%s in %v for method expression %v\n", dictkind, outer, x) } - 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() } -} + // 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, 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. + // 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 { + dictVar = ir.NewNameAt(pos, typecheck.LookupNum(typecheck.LocalDictName, 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++ + typed(rcvrValue.Type(), rcvrVar) + rcvrAssign = ir.NewAssignStmt(pos, rcvrVar, rcvrValue) + rcvrAssign.SetTypecheck(1) + rcvrVar.Defn = rcvrAssign + if outer == nil { + rcvrVar.Class = ir.PEXTERN + typecheck.Target.Decls = append(typecheck.Target.Decls, rcvrAssign) + typecheck.Target.Externs = append(typecheck.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 + // with the additional dictionary argument. + + // First, figure out the dictionary argument. + var dict2Var ir.Node + if usingSubdict { + // Capture sub-dictionary calculated in the outer function + dict2Var = ir.CaptureName(pos, fn, dictVar) + typed(types.Types[types.TUINTPTR], dict2Var) + } else { + // Static dictionary, so can be used directly in the closure + dict2Var = dictValue + } + // 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 -// instantiateMethods instantiates all the methods 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] - // Get the base generic type by looking up the symbol of the - // generic (uninstantiated) name. - 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) + // 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++ { + 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. + arg0 := formalParams[0].Nname.(ir.Node) + 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, + // but it's a value method, add a star operator. + arg0 = ir.NewStarExpr(arg0.Pos(), arg0) } - baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) - name.Func = g.getInstantiation(baseNname, targs, true) + args = append(args, arg0) + } else { + args = append(args, formalParams[i].Nname.(*ir.Name)) } } - g.instTypeList = nil + // 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}) + } + // 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.UseClosure(fn.OClosure, typecheck.Target) + var init []ir.Node + if outer != nil { + init = append(init, dictAssign) + } + if rcvrValue != nil { + init = append(init, rcvrAssign) + } + return ir.InitExpr(init, c) } -// 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, "[")] +// 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 *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 + // 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) + } + } + } } -// getInstantiationForNode returns the function/method instantiation for a -// InstExpr node inst. -func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) *ir.Func { +// 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 *genInst) getInstNameNode(inst *ir.InstExpr) (*ir.Name, bool) { if meth, ok := inst.X.(*ir.SelectorExpr); ok { - return g.getInstantiation(meth.Selection.Nname.(*ir.Name), inst.Targs, true) + return meth.Selection.Nname.(*ir.Name), true } else { - return g.getInstantiation(inst.X.(*ir.Name), inst.Targs, false) + return inst.X.(*ir.Name), 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) - 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) - 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) +// 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 *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 { + 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 entry >= 0 { + dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictInfo.dictLen) + usingSubdict = true } } - return st + if !usingSubdict { + dict = g.getDictionaryValue(n.Pos(), nameNode, targs, isMeth) + } + return dict, usingSubdict } -// 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]) +// 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 + // 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 + } +} + +// 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 *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo { + 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 { - b.WriteString(name) + checkFetchBody(nameNode) } - b.WriteString("[") - for i, targ := range targs { - if i > 0 { - b.WriteString(",") + + // 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. + s1 := make([]*types.Type, len(shapes)) + for i, t := range shapes { + if !t.IsShape() { + s1[i] = typecheck.Shapify(t, i) + } else { + // Already a shape, but make sure it has the correct index. + s1[i] = typecheck.Shapify(shapes[i].Underlying(), i) } - b.WriteString(targ.Type().String()) } - b.WriteString("]") - if i >= 0 { - i2 := strings.Index(name[i:], "]") - assert(i2 >= 0) - b.WriteString(name[i+i2+1:]) + shapes = s1 + + 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 + // to the list of decls. + info = &instInfo{ + dictInfo: &dictInfo{}, + } + info.dictInfo.shapeToBound = make(map[*types.Type]*types.Type) + + 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 + + // 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) + typecheck.Target.Decls = append(typecheck.Target.Decls, st) + g.newInsts = append(g.newInsts, st) } - return typecheck.Lookup(b.String()) + return info } // 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 - tparams []*types.Field - targs []ir.Node - // 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 + 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 // 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. -func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []ir.Node, isMethod bool) *ir.Func { - var tparams []*types.Field +// 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.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 { // 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 @@ -283,145 +766,277 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []ir.No // depend on ir.CurFunc being set. ir.CurFunc = newf - assert(len(tparams) == len(targs)) + assert(len(tparams) == len(shapes)) subst := &subster{ g: g, isMethod: isMethod, newf: newf, - tparams: tparams, - targs: targs, - vars: make(map[*ir.Name]*ir.Name), + info: info, + ts: typecheck.Tsubster{ + Tparams: tparams, + Targs: shapes, + Vars: make(map[*ir.Name]*ir.Name), + }, + defnMap: make(map[ir.Node][]**ir.Name), } - newf.Dcl = make([]*ir.Name, len(gf.Dcl)) - for i, n := range gf.Dcl { - newf.Dcl[i] = subst.node(n).(*ir.Name) + newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) + + // Create the needed dictionary param + dictionarySym := newsym.Pkg.Lookup(typecheck.LocalDictName) + 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 == typecheck.LocalDictName { + panic("already has dictionary") + } + newf.Dcl = append(newf.Dcl, subst.localvar(n)) } + dictionaryArg := types.NewField(gf.Pos(), dictionarySym, dictionaryType) + dictionaryArg.Nname = dictionaryName + info.dictParam = dictionaryName - // Ugly: we have to insert the Name nodes of the parameters/results into + // 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. - 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.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) + 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") + } + + for i, tp := range tparams { + info.dictInfo.shapeToBound[shapes[i]] = subst.ts.Typ(tp.Bound()) + } + ir.CurFunc = savef - return newf + return subst.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.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.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 + // 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 +} + +// 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) + types.CheckSize(d.Type().Elem()) + + // 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 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.dictInfo.startSubDict { + base.Fatalf(fmt.Sprintf("bad dict index %d", i)) + } + + 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) + 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 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 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.typ(x.Type())) + return ir.TypeNode(subst.ts.Typ(x.Type())) case ir.ONAME: - name := x.(*ir.Name) - if v := subst.vars[name]; v != nil { + if v := subst.ts.Vars[x.(*ir.Name)]; v != nil { return v } - m := ir.NewNameAt(name.Pos(), name.Sym()) - if name.IsClosureVar() { - m.SetIsClosureVar(true) + 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) } - 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.ONONAME: + // This handles the identifier in a type switch guard + fallthrough case ir.OLITERAL, ir.ONIL: if x.Sym() != nil { return x } } 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 { - // 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) - 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)) + base.FatalfAt(m.Pos(), "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) - 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)) + m.SetTypecheck(1) - case ir.OADD: - m = transformAdd(m.(*ir.BinaryExpr)) + // 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)) + + 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.OINDEX: - transformIndex(m.(*ir.IndexExpr)) + case ir.OASOP: + as := m.(*ir.AssignOpStmt) + transformCheckAssign(as, as.X) - case ir.OAS2: - as2 := m.(*ir.AssignListStmt) - transformAssign(as2, as2.Lhs, as2.Rhs) + case ir.ORETURN: + transformReturn(m.(*ir.ReturnStmt)) - case ir.OAS: - as := m.(*ir.AssignStmt) - lhs, rhs := []ir.Node{as.X}, []ir.Node{as.Y} - transformAssign(as, lhs, rhs) + case ir.OSEND: + transformSend(m.(*ir.SendStmt)) - case ir.OASOP: - as := m.(*ir.AssignOpStmt) - transformCheckAssign(as, as.X) + case ir.OSELECT: + transformSelect(m.(*ir.SelectStmt)) - case ir.ORETURN: - transformReturn(m.(*ir.ReturnStmt)) + case ir.OCOMPLIT: + transformCompLit(m.(*ir.CompLitExpr)) - case ir.OSEND: - transformSend(m.(*ir.SendStmt)) + case ir.OADDR: + transformAddr(m.(*ir.AddrExpr)) - default: - base.Fatalf("Unexpected node with Typecheck() == 3") - } - } - } - - switch x.Op() { case ir.OLITERAL: t := m.Type() if t != x.Type() { @@ -439,18 +1054,17 @@ 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 OCALLPART 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. - transformDot(m.(*ir.SelectorExpr), false) - m.SetTypecheck(1) + // 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) + } case ir.OCALL: call := m.(*ir.CallExpr) @@ -458,9 +1072,11 @@ 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) + // CONVIFACE transformation was already done in noder2 + assert(m.Op() != ir.OCONVIFACE) - case ir.OCALLPART: + case ir.OMETHVALUE, ir.OMETHEXPR: // Redo the transformation of OXDOT, now that we // know the method value is being called. Then // transform the call. @@ -479,7 +1095,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, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: // Transform these builtins now that we // know the type of the args. m = transformBuiltin(call) @@ -493,54 +1109,97 @@ func (subst *subster) node(n ir.Node) ir.Node { transformCall(call) } - case ir.OCLOSURE: - 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. + transformEarlyCall(call) + + 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 + // 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: + // 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 := makeInstName(oldfn.Nname.Sym(), subst.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 != nil) + ir.NameClosure(newfn.OClosure, subst.newf) saveNewf := subst.newf ir.CurFunc = newfn subst.newf = newfn newfn.Dcl = subst.namelist(oldfn.Dcl) - newfn.ClosureVars = subst.namelist(oldfn.ClosureVars) - typed(subst.typ(oldfn.Nname.Type()), newfn.Nname) - typed(newfn.Nname.Type(), m) + // 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)...) + + // 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(typecheck.LocalDictName)) + 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 dictInfo. + cinfo := &instInfo{ + fun: newfn, + dictParam: ldict, + dictInfo: subst.info.dictInfo, + } + subst.g.instInfoMap[newfn.Nname.Sym()] = cinfo + + typed(subst.ts.Typ(oldfn.Nname.Type()), newfn.Nname) + 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) + newfn.Body.Append(subst.list(oldfn.Body)...) + subst.info = outerinfo subst.newf = saveNewf ir.CurFunc = saveNewf - subst.g.target.Decls = append(subst.g.target.Decls, newfn) + 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())) + } return m } @@ -548,16 +1207,252 @@ func (subst *subster) node(n ir.Node) ir.Node { 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 *genInst) 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: + 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. + call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT) + transformDot(call.X.(*ir.SelectorExpr), true) + } + transformCall(call) + + case ir.OCONVIFACE: + 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 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 !m.Type().HasShape() { + break + } + dt := m.(*ir.TypeAssertExpr) + var rt ir.Node + if dt.Type().IsInterface() || dt.X.Type().IsEmptyInterface() { + ix := findDictType(info, m.Type()) + assert(ix >= 0) + rt = getDictionaryType(info, info.dictParam, dt.Pos(), ix) + } else { + // nonempty interface to noninterface. Need an itab. + ix := -1 + for i, ic := range info.dictInfo.itabConvs { + if ic == m { + ix = info.dictInfo.startItabConv + i + break + } + } + assert(ix >= 0) + rt = getDictionaryEntry(dt.Pos(), info.dictParam, ix, info.dictInfo.dictLen) + } + op := ir.ODYNAMICDOTTYPE + 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 := m.(*ir.CommClause); ok { + // This is not a type switch. TODO: Should we use an OSWITCH case here instead of OCASE? + break + } + m := m.(*ir.CaseClause) + for i, c := range m.List { + if c.Op() == ir.OTYPE && c.Type().HasShape() { + // Use a *runtime._type for the dynamic type. + ix := findDictType(info, m.List[i].Type()) + assert(ix >= 0) + 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 := info.dictInfo.type2switchType[m.List[i]]; ok { + // Type switch from nonempty interface. We need a *runtime.itab + // for the dynamic type. + ix := -1 + for j, ic := range info.dictInfo.itabConvs { + if ic == m.List[i] { + ix = info.dictInfo.startItabConv + j + break + } + } + assert(ix >= 0) + dt.ITab = getDictionaryEntry(c.Pos(), info.dictParam, ix, info.dictInfo.dictLen) + } + } + typed(m.List[i].Type(), dt) + m.List[i] = dt + } + } + + } + return m + } + 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 { + for i, dt := range info.dictInfo.shapeParams { + if dt == t { + return i + } + } + for i, dt := range info.dictInfo.derivedTypes { + if types.IdenticalStrict(dt, t) { + return i + len(info.dictInfo.shapeParams) + } + } + return -1 +} + +// 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, 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() { + // 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 + } + if !in.Type().HasShape() { + // 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, in.Type()) + 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 + // will be more efficient than converting to an empty interface first + // and then type asserting to dst. + ix := -1 + 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.dictInfo.dictLen) + } else { + 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) + } + + // Figure out what the data field of the interface will be. + 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 { s := make([]*ir.Name, len(l)) for i, n := range l { - s[i] = subst.node(n).(*ir.Name) - if n.Defn != nil { - s[i].Defn = subst.node(n.Defn) - } - if n.Outer != nil { - s[i].Outer = subst.node(n.Outer).(*ir.Name) - } + s[i] = subst.localvar(n) } return s } @@ -570,348 +1465,719 @@ 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, 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. -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 { - // 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 { - newfields[i].Nname = v - } - } +// 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. +func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir.Name) []*types.Field { + // Find the starting index in dcl of declarations of the class (either + // PPARAM or PPARAMOUT). + var i int + for i = range dcl { + if dcl[i].Class == class { + break } } - if newfields != nil { - return types.NewStruct(t.Pkg(), newfields) + + // Create newfields nodes that are copies of the oldfields nodes, but + // with substitution for any type params, and with Nname set to be the node in + // Dcl for the corresponding PPARAM or PPARAMOUT. + newfields := make([]*types.Field, len(oldfields)) + for j := range oldfields { + newfields[j] = oldfields[j].Copy() + 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 + // 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++ + } + } + return newfields +} + +// 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() } 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() { + 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) } -// 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 +// getDictionarySym returns the dictionary for the named generic function gf, which +// is instantiated with the type arguments targs. +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) + } + + // Enforce that only concrete types can make it to here. + for _, t := range targs { + if t.HasShape() { + panic(fmt.Sprintf("shape %+v in dictionary for %s", t, gf.Sym().Name)) + } + } + + // Get a symbol representing the dictionary. + sym := typecheck.MakeDictSym(gf.Sym(), targs, isMeth) + + // Initialize the dictionary, if we haven't yet already. + lsym := sym.Linksym() + if len(lsym.P) > 0 { + // We already started creating this dictionary and its lsym. + return sym + } + + 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) + } + + instInfo := g.getInstantiation(gf, targs, isMeth) + info := instInfo.dictInfo + + subst := typecheck.Tsubster{ + Tparams: info.shapeParams, + Targs: targs, } - 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) + // 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, ir.OCALLFUNC, ir.OCALLMETH: + call := n.(*ir.CallExpr) + if call.X.Op() == ir.OXDOT || call.X.Op() == ir.ODOTMETH { + var nameNode *ir.Name + se := call.X.(*ir.SelectorExpr) + if se.X.Type().IsShape() { + // This is a method call enabled by a type bound. + + // 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() { + // 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 + // 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. + 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) + } + 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) + } + subtargs := typecheck.TypesOf(inst.Targs) + for i, t := range subtargs { + subtargs[i] = subst.Typ(t) + } + sym = g.getDictionarySym(nameNode, subtargs, isMeth) + } + + 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, ir.OMETHEXPR, ir.OMETHVALUE: + selExpr := n.(*ir.SelectorExpr) + 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 := typecheck.Lookdot1(selExpr, selExpr.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) + sym = g.getDictionarySym(nameNode, s2targs, true) + + default: + assert(false) } - if newfields != nil { - newfields[i] = types.NewField(f.Pos, f.Sym, t2) + + 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) } } - if newfields != nil { - return types.NewInterface(t.Pkg(), newfields) + + g.instantiateMethods() + delay := &delayInfo{ + gf: gf, + targs: targs, + sym: sym, + off: off, + isMeth: isMeth, } - return t + g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay) + return sym } -// 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 -// 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.Type == t { - return subst.targs[i].Type() - } - } - // 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(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) - } - - var newt *types.Type +// 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 *genInst) finalizeSyms() { + for _, d := range g.dictSymsToFinalize { + infoPrint("=== Finalizing dictionary %s\n", d.sym.Name) + + lsym := d.sym.Linksym() + instInfo := g.getInstantiation(d.gf, d.targs, d.isMeth) + info := instInfo.dictInfo + + subst := typecheck.Tsubster{ + Tparams: info.shapeParams, + Targs: d.targs, + } - switch t.Kind() { - case types.TTYPEPARAM: - if t.Sym() == newsym { - // The substitution did not change the type. - return t + // Emit an entry for each itab + for _, n := range info.itabConvs { + var srctype, dsttype *types.Type + switch n.Op() { + case ir.OXDOT, ir.OMETHVALUE: + se := n.(*ir.SelectorExpr) + srctype = subst.Typ(se.X.Type()) + dsttype = subst.Typ(info.shapeToBound[se.X.Type()]) + 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()) + 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()) + } + 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) + 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) + } } - // 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()) + objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA) + infoPrint("=== Finalized dictionary %s\n", d.sym.Name) + } + g.dictSymsToFinalize = nil +} + +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. + var n *ir.Name + if sym.Def != nil { + n = sym.Def.(*ir.Name) + } else { + // 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. 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. + // TODO: use a cast, or is typing directly ok? + np.SetType(types.Types[types.TUINTPTR]) + np.SetTypecheck(1) + return np +} + +// 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().HasShape() { + return true } + } + return false +} - case types.TPTR: - elem := t.Elem() - newelem := subst.typ(elem) - if newelem != elem { - newt = types.NewPtr(newelem) +// hasShapeTypes returns true if any type in targs has a shape. +func hasShapeTypes(targs []*types.Type) bool { + for _, t := range targs { + if t.HasShape() { + return true } + } + return false +} - case types.TSLICE: - elem := t.Elem() - newelem := subst.typ(elem) - if newelem != elem { - newt = types.NewSlice(newelem) +// getInstInfo get the dictionary format for a function instantiation- type params, derived +// types, and needed subdictionaries and itabs. +func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instInfo) { + info := instInfo.dictInfo + info.shapeParams = shapes + + 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) } + } - case types.TSTRUCT: - newt = subst.tstruct(t, false) - if newt == t { - newt = nil + for _, n := range st.Dcl { + addType(info, n, n.Type()) + n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1) + } + + if infoPrintMode { + fmt.Printf(">>> InstInfo for %v\n", st) + for _, t := range info.shapeParams { + fmt.Printf(" Typeparam %v\n", t) } + } - 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) + // 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) { + 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) + } + 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 { + infoPrint(" Closure&subdictionary required at generic meth value %v\n", n) } - newrecv = newrecvs.Field(0) + info.subDictCalls = append(info.subDictCalls, n) } - if newparams == t.Params() { - newparams = subst.tstruct(t.Params(), true) + 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 newresults == t.Results() { - newresults = subst.tstruct(t.Results(), true) + 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) + } + 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). + cfunc := n.(*ir.ClosureExpr).Func + for _, n1 := range cfunc.Body { + ir.Visit(n1, visitFunc) + } + for _, n := range cfunc.Dcl { + n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1) + } + 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() + } + } + } } - newt = types.NewSignature(t.Pkg(), newrecv, t.TParams().FieldSlice(), newparams.FieldSlice(), newresults.FieldSlice()) } + addType(info, n, n.Type()) + } - case types.TINTER: - newt = subst.tinter(t) - if newt == t { - newt = nil + 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 Instinfo\n") + } + 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) +} - 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 := makeInstName(oldsym, subst.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. - subst.g.instTypeList = append(subst.g.instTypeList, newt) +// 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 shape) that is different from any existing type on +// info.derivedTypes. +func addType(info *dictInfo, n ir.Node, t *types.Type) { + if t == nil || !t.HasShape() { + return + } + if t.IsShape() { + return + } + 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.shapeParams) { + 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 + } + // Ignore a derived type we've already added. + for _, et := range info.derivedTypes { + if types.IdenticalStrict(t, et) { + return } } - return newt + info.derivedTypes = append(info.derivedTypes, t) } -// 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. -func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir.Name) []*types.Field { - // Find the starting index in dcl of declarations of the class (either - // PPARAM or PPARAMOUT). - var i int - for i = range dcl { - if dcl[i].Class == class { - break +// 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 + + 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 } + if t.IsShape() { + // 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 - // Create newfields nodes that are copies of the oldfields nodes, but - // with substitution for any type params, and with Nname set to be the node in - // Dcl for the corresponding PPARAM or PPARAMOUT. - newfields := make([]*types.Field, len(oldfields)) - 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 - // 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 { - newfields[j].Nname = dcl[i] - i++ + } + switch t.Kind() { + 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: + 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() { + 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, types.TUNSAFEPTR: + 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 } - return newfields } -// defer does a single defer of type t, if it is a pointer type. -func deref(t *types.Type) *types.Type { - if t.IsPtr() { - return t.Elem() +// 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 + f.SetIsDDD(typ.Params().Field(i).IsDDD()) + formalParams = append(formalParams, f) } - return t + 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 + +} + +// assertToBound returns a new node that converts a node rcvr with interface type to +// 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(dst, rcvr) + } + return rcvr } -// 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 +// 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 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 had any needed +// transformations done. +func (g *genInst) buildClosure2(info *instInfo, m ir.Node) ir.Node { + outer := info.fun + 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()) + 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, dst) + } else { + rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, m, dst) + } + 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) + + typed(dot.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, typecheck.Target) } diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 32a1483b4aabeb2fddeb646fc897ccf216cc52cb..1e996b95c48ffa506d61573f7bde134cc80be639 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 @@ -35,24 +37,24 @@ 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 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 !g.delayTransform() { + transformSend(n) } - transformSend(n) n.SetTypecheck(1) return n case *syntax.DeclStmt: - return ir.NewBlockStmt(g.pos(stmt), g.decls(stmt.DeclList)) + 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) + return n case *syntax.AssignStmt: if stmt.Op != 0 && stmt.Op != syntax.Def { @@ -61,60 +63,40 @@ 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) - return n + if !g.delayTransform() { + transformAsOp(n) } - transformAsOp(n) n.SetTypecheck(1) 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) - - // 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.Typecheck() == 3 { - delay = true - break - } - } - for _, e := range rhs { - if e.Typecheck() == 3 { - delay = true - break - } - } + names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def) 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 !g.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 !g.delayTransform() { + transformAssign(n, n.Lhs, n.Rhs) } - transformAssign(n, n.Lhs, n.Rhs) n.SetTypecheck(1) return n @@ -124,15 +106,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 !g.delayTransform() { + transformReturn(n) } - transformReturn(n) n.SetTypecheck(1) return n case *syntax.IfStmt: @@ -141,7 +117,10 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { return g.forStmt(stmt) case *syntax.SelectStmt: n := g.selectStmt(stmt) - transformSelect(n.(*ir.SelectStmt)) + + if !g.delayTransform() { + transformSelect(n.(*ir.SelectStmt)) + } n.SetTypecheck(1) return n case *syntax.SwitchStmt: @@ -266,6 +245,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 } @@ -311,6 +296,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/sync.go b/src/cmd/compile/internal/noder/sync.go new file mode 100644 index 0000000000000000000000000000000000000000..7af558f8b207aee4f645b554a9e33981f8aaaad3 --- /dev/null +++ b/src/cmd/compile/internal/noder/sync.go @@ -0,0 +1,187 @@ +// 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" + "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 + +// 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 + syncImplicitTypes + syncObjectName +) 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 0000000000000000000000000000000000000000..655cafc9502d25332bdb9c69b50a77147b701c26 --- /dev/null +++ b/src/cmd/compile/internal/noder/syncmarker_string.go @@ -0,0 +1,156 @@ +// 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] + _ = x[syncTypeParamNames-130] + _ = x[syncTypeParamBounds-131] + _ = x[syncImplicitTypes-132] + _ = x[syncObjectName-133] +} + +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, 969} + +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/transform.go b/src/cmd/compile/internal/noder/transform.go index 2859089e69b91386010db02268764a66aa2de7aa..a673484821b0c2161f2e5eb7e2a13136c5b8c12d 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: @@ -122,8 +130,12 @@ 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) { + // 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) @@ -149,9 +161,10 @@ 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) - 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. @@ -167,6 +180,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. @@ -185,7 +204,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.HasShape() || rt.IsInterface() == lt.IsInterface() || lt.Size() >= 1<<16 { l = ir.NewConvExpr(base.Pos, aop, rt, l) l.SetTypecheck(1) } @@ -198,7 +217,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.Size() >= 1<<16 { r = ir.NewConvExpr(base.Pos, aop, lt, r) r.SetTypecheck(1) } @@ -303,6 +322,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 } @@ -323,11 +346,22 @@ assignOK: stmt := stmt.(*ir.AssignListStmt) stmt.SetOp(ir.OAS2FUNC) r := rhs[0].(*ir.CallExpr) - 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 } @@ -340,12 +374,12 @@ assignOK: } } -// Corresponds to 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) { default: - base.Fatalf("typecheckargs %+v", n.Op()) + base.Fatalf("transformArgs %+v", n.Op()) case *ir.CallExpr: list = n.Args if n.IsDDD { @@ -363,46 +397,13 @@ func transformArgs(n ir.InitNode) { return } - // Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...). - // 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 - // 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 - } - 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) - } - if static { - ir.CurFunc = nil - } - - switch n := n.(type) { - case *ir.CallExpr: - n.Args = list - case *ir.ReturnStmt: - n.Results = list - } - - transformAssign(as, as.Lhs, as.Rhs) - as.SetTypecheck(1) - n.PtrInit().Append(as) + // 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 @@ -412,11 +413,18 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node { return n } - if types.Identical(n.Type(), t) { + if n.Op() == ir.OPAREN { + n = n.(*ir.ParenExpr).X + } + + if types.IdenticalStrict(n.Type(), t) { return n } - op, _ := 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) + } r := ir.NewConvExpr(base.Pos, op, t, n) r.SetTypecheck(1) @@ -424,7 +432,34 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node { return r } -// Corresponds to typecheck.typecheckaste. +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 (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) +} + +// 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) { var t *types.Type var i int @@ -495,10 +530,16 @@ 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) + selrecv.SetInit(n.Init()) + ncase.Comm = selrecv } switch n.Op() { case ir.OAS: @@ -537,13 +578,31 @@ 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) 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() @@ -561,8 +620,9 @@ 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.SetType(typecheck.MethodValueWrapper(n).Type()) + n.SetOp(ir.OMETHVALUE) + // This converts a method type to a function type. See issue 47775. + n.SetType(typecheck.NewMethodType(n.Type(), nil)) } return n } @@ -594,7 +654,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 @@ -790,7 +854,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 } @@ -856,7 +923,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 @@ -911,9 +978,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 { @@ -922,33 +987,34 @@ 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 - - // 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())) + kv := l.(*ir.KeyExpr) + key := kv.Key - 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) + } + 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) } - 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 || 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) } @@ -959,3 +1025,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/noder/types.go b/src/cmd/compile/internal/noder/types.go index 8680559a412970277e2513fe6d1620a55d4393cc..4f6d8287201d4b685c3a8822b57e6b6f6b3f7ab8 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" @@ -22,23 +21,32 @@ 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()) } +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 { + // 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) + 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] + types.DeferCheckSize() + g.fillinMethods(info.typ, info.ntyp) + types.ResumeCheckSize() } return res } @@ -47,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 @@ -54,6 +68,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 @@ -61,25 +81,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 { - b := bytes.NewBufferString(name) - b.WriteByte('[') - for i, targ := range targs { - if i > 0 { - b.WriteByte(',') - } - tname := types2.TypeString(targ, - func(*types2.Package) string { return "" }) - 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 @@ -89,60 +96,76 @@ 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.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() // 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). - instName := instTypeName2(typ.Obj().Name(), typ.TArgs()) + // + // 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.TypeArgs()) 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() } + // 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.Origin().Obj()) + // 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. - ntyp := newIncompleteNamedType(g.pos(typ.Obj().Pos()), s) + // 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() { - rparams[i] = g.typ1(targ) + targs := typ.TypeArgs() + 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()) + // Save the symbol for the base generic type. + ntyp.SetOrigSym(g.pkg(typ.Obj().Pkg()).Lookup(typ.Obj().Name())) ntyp.SetUnderlying(g.typ1(typ.Underlying())) - g.fillinMethods(typ, ntyp) + 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()) @@ -183,12 +206,9 @@ 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 - } + + // With Go 1.18, an embedded element can be any type, not + // just an interface. embeddeds[j] = types.NewField(src.NoXPos, nil, g.typ1(e)) j++ } @@ -197,27 +217,50 @@ 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) } - return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...)) + return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...), typ.IsImplicit()) 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) + 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 { + // 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 - // 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() + bound := g.typ1(typ.Constraint()) + tp.SetBound(bound) return tp + case *types2.Union: + nt := typ.Len() + tlist := make([]*types.Type, nt) + tildes := make([]bool, nt) + for i := range tlist { + t := typ.Term(i) + tlist[i] = g.typ1(t.Type()) + tildes[i] = t.Tilde() + } + 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). @@ -238,76 +281,92 @@ 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 { - targs := make([]ir.Node, len(typ.TArgs())) - for i, targ := range typ.TArgs() { - targs[i] = ir.TypeNode(g.typ1(targ)) - } + targs2 := typ.TypeArgs() + 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) - meth := g.obj(m) - recvType := types2.AsSignature(m.Type()).Recv().Type() - ptr := types2.AsPointer(recvType) - if ptr != nil { - recvType = ptr.Elem() - } - 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.Field, len(rparams)) - for i, rparam := range rparams { - tparams[i] = types.NewField(src.NoXPos, nil, g.typ1(rparam.Type())) - } - assert(len(tparams) == len(targs)) - subst := &subster{ - g: g, - tparams: tparams, - targs: targs, - } - // Do the substitution of the type - meth2.SetType(subst.typ(meth.Type())) - newsym.Def = meth2 + 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 + 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) + } + 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, + // using m.Type().RParams() and typ.TArgs() + inst2 := g.instTypeName2("", typ.TypeArgs()) + 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()).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. 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)) } - meth = meth2 + g.curDecl = savedCurDecl + assert(len(tparams) == len(targs)) + ts := typecheck.Tsubster{ + Tparams: tparams, + Targs: targs, + } + // Do the substitution of the type + meth2.SetType(ts.Typ(meth.Type())) + 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() { - // 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. + typecheck.NeedInstType(ntyp) } } func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type { - tparams2 := sig.TParams() - tparams := make([]*types.Field, len(tparams2)) + tparams2 := sig.TypeParams() + tparams := make([]*types.Field, tparams2.Len()) for i := range tparams { - tp := tparams2[i] + tp := tparams2.At(i).Obj() tparams[i] = types.NewField(g.pos(tp), g.sym(tp), g.typ1(tp.Type())) } @@ -346,7 +405,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 @@ -356,36 +415,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) - } - } - 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": @@ -430,3 +492,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 +} diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go new file mode 100644 index 0000000000000000000000000000000000000000..ec0012db4cec44bb732597f5843ffb2db863f8b9 --- /dev/null +++ b/src/cmd/compile/internal/noder/unified.go @@ -0,0 +1,334 @@ +// 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 + +// 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() { + writeNewExportFunc = writeNewExport + } else if base.Flag.G != 0 { + base.Errorf("cannot use -G and -d=quirksmode together") + } + + 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(ctxt, 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.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 + // 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 fn.OClosure == nil && len(pri.dict.targs) != 0 { + target.Decls = append(target.Decls, fn) + } + } + todoBodies = nil + todoBodiesDone = true + + // 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 +} + +// 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) + + 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.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) { + // 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) }) + + // 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) + assert(!r.bool()) + 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) + assert(!r.bool()) + 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.bool(false) + w.reloc(relocObj, idx) + w.len(0) + } + + w.sync(syncEOF) + w.flush() + } + + l.pw.dump(out) +} 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 0000000000000000000000000000000000000000..d7334df282885f0c4ffb2ac6542c1585da7a6c04 --- /dev/null +++ b/src/cmd/compile/internal/noder/unified_test.go @@ -0,0 +1,160 @@ +// Copyright 2021 The Go Authors. 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 ( + 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") +) + +// 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) { + // 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) + } + + 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 -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)) + } + + 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, "--"} + 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) + } + 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) +} diff --git a/src/cmd/compile/internal/noder/validate.go b/src/cmd/compile/internal/noder/validate.go index b926222c89c417ccf7a691f3fc9fe60a0c68e1ae..dcacae7480c2975c50182aeb72d46d31e374d4f4 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: @@ -73,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/noder/writer.go b/src/cmd/compile/internal/noder/writer.go new file mode 100644 index 0000000000000000000000000000000000000000..2bb0b4d5d750bb01388fe31eb32f9a9d4081e522 --- /dev/null +++ b/src/cmd/compile/internal/noder/writer.go @@ -0,0 +1,1861 @@ +// 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 + + // 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). + + // 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 []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 { + 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 + + w.string(trimFilename(b)) + + 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 + +var anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName) + +func (w *writer) typ(typ types2.Type) { + w.typInfo(w.p.typIdx(typ, w.dict)) +} + +func (w *writer) typInfo(info typeInfo) { + w.sync(syncType) + if w.bool(info.derived) { + w.len(info.idx) + w.derived = true + } else { + w.reloc(relocType, info.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) typeInfo { + if quirksMode() { + typ = pw.dups.orig(typ) + } + + if idx, ok := pw.typsIdx[typ]; ok { + return typeInfo{idx: idx, derived: false} + } + if dict != nil { + if idx, ok := dict.derivedIdx[typ]; ok { + return typeInfo{idx: idx, derived: true} + } + } + + w := pw.newWriter(relocType, syncTypeIdx) + w.dict = dict + + switch typ := typ.(type) { + default: + base.Fatalf("unexpected type: %v (%T)", typ, typ) + + case *types2.Basic: + 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)) + + 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) + } + + 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(typ.TypeParams().Len() == typ.TypeArgs().Len() || typ.TypeArgs().Len() == 0) + + // TODO(mdempsky): Why do we need to loop here? + orig := typ + for orig.TypeArgs() != nil { + orig = orig.Origin() + } + + w.code(typeNamed) + w.obj(orig.Obj(), typ.TypeArgs()) + + 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) + w.len(index) + + 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: + base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ) + 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: + if typ == anyTypeName.Type() { + w.code(typeNamed) + w.obj(anyTypeName, nil) + break + } + + w.code(typeInterface) + w.interfaceType(typ) + + case *types2.Union: + w.code(typeUnion) + w.unionType(typ) + } + + if w.derived { + idx := len(dict.derived) + dict.derived = append(dict.derived, derivedInfo{idx: w.flush()}) + dict.derivedIdx[typ] = idx + return typeInfo{idx: idx, derived: true} + } + + pw.typsIdx[typ] = w.idx + return typeInfo{idx: w.flush(), derived: false} +} + +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.Len()) + for i := 0; i < typ.Len(); i++ { + t := typ.Term(i) + w.bool(t.Tilde()) + w.typ(t.Type()) + } +} + +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.TypeParams() == 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.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} + + 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) + if len(decl.implicits) != 0 { + w.derived = true + } + } + + w.sync(syncObject) + w.bool(false) + w.reloc(relocObj, info.idx) + + w.len(len(info.explicits)) + for _, info := range info.explicits { + w.typInfo(info) + } +} + +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) + wext := pw.newWriter(relocObjExt, syncObject1) + wname := pw.newWriter(relocName, syncObject1) + wdict := pw.newWriter(relocObjDict, syncObject1) + + pw.globalsIdx[obj] = w.idx // break cycles + assert(wext.idx == w.idx) + assert(wname.idx == w.idx) + assert(wdict.idx == w.idx) + + w.dict = dict + wext.dict = dict + + code := w.doObj(wext, obj) + w.flush() + wext.flush() + + wname.qualifiedIdent(obj) + wname.code(code) + wname.flush() + + wdict.objDict(obj, w.dict) + wdict.flush() + + return w.idx +} + +func (w *writer) doObj(wext *writer, obj types2.Object) codeObj { + if obj.Pkg() != w.p.curpkg { + return objStub + } + + switch obj := obj.(type) { + default: + w.p.unexpected("object", obj) + panic("unreachable") + + case *types2.Const: + w.pos(obj) + w.typ(obj.Type()) + w.value(obj.Val()) + return objConst + + case *types2.Func: + decl, ok := w.p.funDecls[obj] + assert(ok) + sig := obj.Type().(*types2.Signature) + + w.pos(obj) + w.typeParamNames(sig.TypeParams()) + w.signature(sig) + w.pos(decl) + wext.funcExt(obj) + return objFunc + + case *types2.TypeName: + decl, ok := w.p.typDecls[obj] + assert(ok) + + if obj.IsAlias() { + w.pos(obj) + w.typ(obj.Type()) + return objAlias + } + + named := obj.Type().(*types2.Named) + assert(named.TypeArgs() == nil) + + w.pos(obj) + w.typeParamNames(named.TypeParams()) + wext.typeExt(obj) + w.typExpr(decl.Type) + + w.len(named.NumMethods()) + for i := 0; i < named.NumMethods(); i++ { + w.method(wext, named.Method(i)) + } + + return objType + + case *types2.Var: + w.pos(obj) + w.typ(obj.Type()) + wext.varExt(obj) + return objVar + } +} + +// 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) +} + +// 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(dict.implicits)) + + tparams := objTypeParams(obj) + ntparams := tparams.Len() + w.len(ntparams) + for i := 0; i < ntparams; i++ { + w.typ(tparams.At(i).Constraint()) + } + + 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.TypeParamList) { + w.sync(syncTypeParamNames) + + ntparams := tparams.Len() + for i := 0; i < ntparams; i++ { + tparam := tparams.At(i).Obj() + w.pos(tparam) + w.localIdent(tparam) + } +} + +func (w *writer) method(wext *writer, meth *types2.Func) { + decl, ok := w.p.funDecls[meth] + assert(ok) + sig := meth.Type().(*types2.Signature) + + w.sync(syncMethod) + w.pos(meth) + w.selector(meth) + w.typeParamNames(sig.RecvTypeParams()) + w.param(sig.Recv()) + w.signature(sig) + + w.pos(decl) // XXX: Hack to workaround linker limitations. + wext.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) && obj.Pkg() == w.p.curpkg { + decl, ok := w.p.typDecls[obj.(*types2.TypeName)] + assert(ok) + 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()) + 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") + } + } + } + + sig, block := obj.Type().(*types2.Signature), decl.Body + body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, block, w.dict) + assert(len(closureVars) == 0) + + w.sync(syncFuncExt) + w.pragmaFlag(pragma) + w.linkname(obj) + w.bool(false) // stub extension + w.reloc(relocBody, body) + 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 (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx int, closureVars []posObj) { + w := pw.newWriter(relocBody, syncFuncBody) + w.dict = dict + + w.funcargs(sig) + if w.bool(block != nil) { + w.stmts(block.List) + w.pos(block.Rbrace) + } + + return w.flush(), w.closureVars +} + +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.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(pos syntax.Pos, obj *types2.Var) { + w.sync(syncUseObjLocal) + + 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) +} + +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.exprList(stmt.Rhs) + w.assignList(stmt.Lhs) + } + + 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 { + obj := obj.(*types2.Var) + + 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.exprList(values[i]) + w.assignList(name) + } + break + } + + w.code(stmtAssign) + w.pos(decl) + w.exprList(decl.Values) + w.assignList(namesAsExpr(decl.NameList)) + } +} + +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.expr(rang.X) + w.assignList(rang.Lhs) + } 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) + + 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 { + 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, 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". + if inst.Type != nil { + w.needType(inst.Type) + } else { + w.needType(tv.Type) + } + + 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.typ(tv.Type) + w.value(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 isGlobal(obj) { + w.code(exprName) + w.obj(obj, targs) + return + } + + obj := obj.(*types2.Var) + assert(targs.Len() == 0) + + w.code(exprLocal) + w.useLocal(expr.Pos(), obj) + 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: + 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 + } + + 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 + } + } + + 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) + } +} + +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) + + 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) + + w.len(len(closureVars)) + for _, cv := range closureVars { + w.pos(cv.pos) + if quirksMode() { + cv.pos = expr.Body.Rbrace + } + w.useLocal(cv.pos, cv.obj) + } + + w.reloc(relocBody, body) +} + +type posObj struct { + pos syntax.Pos + obj *types2.Var +} + +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)) +} + +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 +// particularly sensitive to it. + +type typeDeclGen struct { + *syntax.TypeDecl + gen int + + // Implicit type parameters in scope at this type declaration. + implicits []*types2.TypeName +} + +type fileImports struct { + importedEmbed, importedUnsafe bool +} + +type declCollector struct { + pw *pkgWriter + typegen *int + file *fileImports + withinFunc bool + implicits []*types2.TypeName +} + +func (c *declCollector) withTParams(obj types2.Object) *declCollector { + tparams := objTypeParams(obj) + n := tparams.Len() + if n == 0 { + return c + } + + 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).Obj()) + } + return © +} + +func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { + pw := c.pw + + 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": + c.file.importedEmbed = true + case "unsafe": + c.file.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 + + return c.withTParams(obj) + + case *syntax.TypeDecl: + obj := pw.info.Defs[n.Name].(*types2.TypeName) + d := typeDeclGen{TypeDecl: n, implicits: c.implicits} + + 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 c.withinFunc { + *c.typegen++ + d.gen = *c.typegen + } + } + + 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) + + 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) + } + } + + // 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 !file.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: + if decl.Name.Value == "_" { + break // skip blank functions + } + + obj := w.p.info.Defs[decl.Name].(*types2.Func) + sig := obj.Type().(*types2.Signature) + + if sig.RecvTypeParams() != nil || sig.TypeParams() != nil { + break // skip generic functions + } + + if recv := sig.Recv(); recv != nil { + 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 + } + + 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.IsMethodSet() { + 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 && named.TypeParams().Len() != 0 && named.TypeArgs().Len() == 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 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 { + args := unpackListExpr(index.Index) + if len(args) == 1 { + tv, ok := info.Types[args[0]] + assert(ok) + if tv.IsValue() { + return // normal index expression + } + } + + 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] + inst = info.Instances[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.TypeParamList { + switch obj := obj.(type) { + case *types2.Func: + sig := obj.Type().(*types2.Signature) + if sig.Recv() != nil { + return sig.RecvTypeParams() + } + return sig.TypeParams() + case *types2.TypeName: + if !obj.IsAlias() { + return obj.Type().(*types2.Named).TypeParams() + } + } + return nil +} + +func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag { + if p == nil { + return 0 + } + return p.(*pragmas).Flag +} diff --git a/src/cmd/compile/internal/pkginit/init.go b/src/cmd/compile/internal/pkginit/init.go index 7cad2622146d0e580cb257348ec234ecb05ba713..40f14082600c3d1515c3d1e9350d961f4dbcb77e 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 97d69629fbae9e5167ec68abe39c9264a8c979cc..a50975343fbced39fdd911c769575e0ceff8edb1 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) { @@ -304,7 +300,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/ppc64/galign.go b/src/cmd/compile/internal/ppc64/galign.go index 590290fa371008db507ade8df55c54b4bc160f69..20fd8cec54f397fb9d05f490798b0c4f3965ae17 100644 --- a/src/cmd/compile/internal/ppc64/galign.go +++ b/src/cmd/compile/internal/ppc64/galign.go @@ -16,13 +16,14 @@ 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 - arch.Ginsnopdefer = ginsnopdefer arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue arch.SSAGenBlock = ssaGenBlock + arch.LoadRegResult = loadRegResult + arch.SpillArgReg = spillArgReg } diff --git a/src/cmd/compile/internal/ppc64/ggen.go b/src/cmd/compile/internal/ppc64/ggen.go index c76962cfb811334d577ffc49b427533f0a8517b8..3ae6422bf9e26b0a1fb08e1f94f3a17a8965d3f1 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/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index 11226f65a0f01639359fe2992e2f266b2301be20..98316c16fab7f9b6756fa7c0cadd6f1e891c3af3 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" @@ -502,6 +503,20 @@ 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: + // 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: // For now, // @@ -886,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 @@ -1829,6 +1851,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 +2005,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, @@ -2027,3 +2047,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/reflectdata/alg.go b/src/cmd/compile/internal/reflectdata/alg.go index 0707e0b61caf4861033d424acc525d028a2bf484..d000618bd64f576153f24335ddfa31a30dabfb21 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: @@ -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/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index eb9a8a6c9bc73ade1974d19e63cdbe225224935f..b1e2902385be45fd319eb0aaff306a433118e1ad 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" @@ -19,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" @@ -28,35 +28,27 @@ 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 var ( - signatmu sync.Mutex // protects signatset and signatslice - signatset = make(map[*types.Type]struct{}) - signatslice []*types.Type + // 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 []typeAndStr gcsymmu sync.Mutex // protects gcsymset and gcsymslice gcsymset = make(map[*types.Type]struct{}) - itabs []itabEntry ptabs []*ir.Name ) @@ -105,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) } @@ -153,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) } @@ -242,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 @@ -302,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 @@ -313,6 +305,10 @@ 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() { + // Shape types have no methods. + return nil + } // method type mt := types.ReceiverBaseType(t) @@ -321,13 +317,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 @@ -341,7 +330,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 } @@ -355,11 +348,16 @@ 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), } + 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) } @@ -394,7 +392,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 @@ -719,7 +717,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)) @@ -735,7 +733,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 @@ -756,16 +754,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) { @@ -799,11 +797,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 @@ -848,16 +846,33 @@ 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()) +// 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 { - itabs = append(itabs, itabEntry{t: t, itype: itype, lsym: s.Linksym()}) + writeITab(lsym, typ, iface, true) } + 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 { + s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString()) lsym := s.Linksym() + + if !existed { + writeITab(lsym, typ, iface, false) + } + n := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8]) return typecheck.Expr(typecheck.NodAddr(n)).(*ir.AddrExpr) } @@ -914,11 +929,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 @@ -926,7 +942,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) } @@ -945,25 +961,22 @@ func writeType(t *types.Type) *obj.LSym { if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil { tbase = t.Elem() } - dupok := 0 - if tbase.Sym() == nil { - dupok = obj.DUPOK + if tbase.Kind() == types.TFORW { + base.Fatalf("unresolved defined type: %v", tbase) } - 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 { - 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 @@ -1087,20 +1100,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 } @@ -1184,7 +1197,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. @@ -1226,108 +1241,25 @@ 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() { - // Generic types don't have a runtime type descriptor (but will - // have a dictionary) + // 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 { 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()}) - delete(signatset, t) - } - signatslice = signatslice[:0] + signats := signatslice + // Sort for reproducible builds. sort.Sort(typesByString(signats)) for _, ts := range signats { t := ts.t @@ -1336,6 +1268,7 @@ func WriteRuntimeTypes() { writeType(types.NewPtr(t)) } } + signatslice = signatslice[len(signats):] } // Emit GC data symbols. @@ -1349,29 +1282,67 @@ 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 +// 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 + 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) + if m.isym == nil { + panic("NO ISYM") + } + sigs = sigs[1:] + if len(sigs) == 0 { + break + } + } + } + completeItab := len(sigs) == 0 + if !allowNonImplement && !completeItab { + 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 { + 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(i.lsym, int32(o), int16(obj.DUPOK|obj.RODATA)) - i.lsym.Set(obj.AttrContentAddressable, true) } + // 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 @@ -1426,6 +1397,9 @@ func WriteBasicTypes() { } writeType(types.NewPtr(types.Types[types.TSTRING])) writeType(types.NewPtr(types.Types[types.TUNSAFEPTR])) + 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. @@ -1446,6 +1420,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", "")) } @@ -1453,7 +1430,7 @@ func WriteBasicTypes() { type typeAndStr struct { t *types.Type - short string + short string // "short" here means NameString regular string } @@ -1466,8 +1443,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 } @@ -1594,7 +1576,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) @@ -1603,8 +1585,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 } @@ -1653,7 +1635,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 } @@ -1685,16 +1667,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() { @@ -1741,6 +1723,49 @@ 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 == types.UnsafePkg): + // 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 + + 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 + } +} + // Generate a wrapper function to convert from // a receiver of type T to a receiver of type U. // That is, @@ -1761,7 +1786,39 @@ 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 + // 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 := 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 + if rcvr.HasShape() { + base.Fatalf("method on type instantiated with shapes, rcvr:%+v", rcvr) + } + } + } + newnam := ir.MethodSym(rcvr, method.Sym) lsym := newnam.Linksym() if newnam.Siggen() { @@ -1769,19 +1826,19 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { } newnam.SetSiggen(true) - if types.Identical(rcvr, method.Type.Recv().Type) { + // Except in quirks mode, unified IR creates its own wrappers. + if base.Debug.Unified != 0 && base.Debug.UnifiedQuirks == 0 { return lsym } - // Only generate (*T).M wrappers for T.M in T's own package. - if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && - rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg { + 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, methodrcvr) { return lsym } - // 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 { + if !NeedEmit(rcvr) || rcvr.IsPtr() && !NeedEmit(rcvr.Elem()) { return lsym } @@ -1801,10 +1858,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()) @@ -1814,7 +1871,6 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { } dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, nthis, method.Sym)) - // 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 @@ -1822,24 +1878,72 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { // 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) && !buildcfg.Experiment.RegabiArgs { - // 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))) - } else { - fn.SetWrapper(true) // ignore frame for panic+recover matching + 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 + + if generic && dot.X != nthis { + // 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 { + 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() && !methodrcvr.IsPtr() { + baseOrig = baseOrig.Elem() + } else if !baseOrig.IsPtr() && methodrcvr.IsPtr() { + baseOrig = types.NewPtr(baseOrig) + } + 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() { + // 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, dot.X) + } + args = append(args, ir.ParamNames(tfn.Type())...) + + // Target method uses shaped names. + targs2 := make([]*types.Type, len(targs)) + for i, t := range targs { + targs2[i] = typecheck.Shapify(t, i) + } + targs = targs2 + + 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 + // 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) + // 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()) + } + call.IsDDD = tfn.Type().IsVariadic() if method.Type.NumResults() > 0 { ret := ir.NewReturnStmt(base.Pos, nil) ret.Results = []ir.Node{call} @@ -1858,13 +1962,10 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { 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. - 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) @@ -1872,11 +1973,21 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { 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. // This information is used in the linker in dead method elimination. func MarkTypeUsedInInterface(t *types.Type, from *obj.LSym) { + if t.HasShape() { + // 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 // to an interface if "from" is reachable. @@ -1894,12 +2005,88 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) { } dot := n.X.(*ir.SelectorExpr) ityp := dot.X.Type() + if ityp.HasShape() { + // 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 - // dot.Xoffset is the method index * PtrSize (the offset of code pointer + // dot.Offset() is the method index * PtrSize (the offset of code pointer // in itab). midx := dot.Offset() / int64(types.PtrSize) r.Add = InterfaceMethodOffset(ityp, midx) 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 { + 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.MakeDictSym(gf, targs, true) + + // 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) + } + + // 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) + // 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. + np.SetType(types.Types[types.TUINTPTR]) + np.SetTypecheck(1) + return np +} + +func deref(t *types.Type) *types.Type { + if t.IsPtr() { + return t.Elem() + } + return t +} diff --git a/src/cmd/compile/internal/riscv64/galign.go b/src/cmd/compile/internal/riscv64/galign.go index 338248a7cf27ab13b71ec4ed25f90a015fdc6511..846ed8fb3802e43d603abe6bb0de2617a177dca8 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/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index 64a9b3b33b9aca34cfd15284ff14eb765a67d52a..1359b6a0c388b416dbcda35ef746d0c88497ef44 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() @@ -282,7 +283,54 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.Reg = r1 p.To.Type = obj.TYPE_REG p.To.Reg = r - case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD, + 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.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.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.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, @@ -365,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 @@ -677,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/galign.go b/src/cmd/compile/internal/s390x/galign.go index b004a2db0a39b3f61c9b8e1d93d648d3d44bcd0a..d880834c220d91c763667614a46b241fb23484bb 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/s390x/ssa.go b/src/cmd/compile/internal/s390x/ssa.go index ddc05b36add0fa1b9fd22c3697c12be3b124e6eb..deb6c790069ca29870bbe2a96ba9e6c53725a554 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/block.go b/src/cmd/compile/internal/ssa/block.go index 71ca774431e33cb99a4344d1aaa6e341a052997a..6ff3188f9b20159bcd71cefd626c1221e03d40ef 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/branchelim.go b/src/cmd/compile/internal/ssa/branchelim.go index 1d34f8160b1ea50a5b9d30fa7fdbb4e01c0bc393..be5f9e0a8b45454df60cf16b423d5f05347a8775 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/check.go b/src/cmd/compile/internal/ssa/check.go index 969fd96dbf573cf67483a1f740f5880fb5d8940e..28edfd2237d9253c88731c3c6791e2db5700663b 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/compile.go b/src/cmd/compile/internal/ssa/compile.go index cd8eba405d5c7bc95fa23175aca1652bde7b13db..f87ea5b893ef7561d06144bea1805232b9185ef4 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/config.go b/src/cmd/compile/internal/ssa/config.go index a8393a19995a5f922a419fdd899acedf76a12bef..5ab7240acf683da59192ba04fc91c12770bfe664 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 @@ -177,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 @@ -196,7 +190,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 @@ -228,6 +222,8 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config c.registers = registersARM64[:] c.gpRegMask = gpRegMaskARM64 c.fpRegMask = fpRegMaskARM64 + c.intParamRegs = paramIntRegARM64 + c.floatParamRegs = paramFloatRegARM64 c.FPReg = framepointerRegARM64 c.LinkReg = linkRegARM64 c.hasGReg = true @@ -243,9 +239,10 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config 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) c.hasGReg = true case "mips64": c.BigEndian = true @@ -324,6 +321,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/critical.go b/src/cmd/compile/internal/ssa/critical.go index b85721eba488323fa1ce39c6aeb8707157f4e832..500ce3ae61ce093de51b3c703160d042db2121ca 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 5d10dfe025e97ccd2dcad6af9500eeb04f7df40f..b47b106975ac13f36b4b14784019dcdd1f673cf1 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/debug.go b/src/cmd/compile/internal/ssa/debug.go index 8e2872363b6edbceaa5a3c1c00c396569092b9bc..aad59fa24ec9c46e60b49315bc4a2aeacfe77ec7 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 @@ -378,7 +381,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 { @@ -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 @@ -1120,54 +1122,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 @@ -1554,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, @@ -1562,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()) @@ -1577,7 +1617,7 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta } } if numRegParams == 0 { - return &fd + return } state := debugState{f: f} @@ -1587,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. @@ -1603,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 @@ -1623,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++ @@ -1649,7 +1689,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 { @@ -1688,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/ssa/debug_lines_test.go b/src/cmd/compile/internal/ssa/debug_lines_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c0ccdb1c93e32281fa41479546ff237d60831189 --- /dev/null +++ b/src/cmd/compile/internal/ssa/debug_lines_test.go @@ -0,0 +1,258 @@ +// Copyright 2021 The Go Authors. 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" + "internal/buildcfg" + "runtime" + "sort" + + "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. +// 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 + +var testGoArchFlag = flag.String("arch", "", "run test for specified architecture") + +func testGoArch() string { + if *testGoArchFlag == "" { + return runtime.GOARCH + } + return *testGoArchFlag +} + +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, + // at least for now. + + switch testGoArch() { + case "arm64", "amd64": // register ABI + 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, "-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 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 + 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) + 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, 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 + 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 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/debug_test.go b/src/cmd/compile/internal/ssa/debug_test.go index 33463125424f27b8185ca2c7cd392894cdedf4cf..b20041c1b575a02926aefcf591c5993fe16c349a 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 { diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 7e973ab20591fb8ae42eddcc542f6ca6c1c67451..a3cea855f2fa456a31e18ae0560d9d773ca5f689 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 { @@ -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 @@ -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 @@ -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 @@ -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 > 1 { + 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) @@ -462,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()) } } @@ -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.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) @@ -610,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 { @@ -676,19 +682,19 @@ 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())) } - if x.debug { + if x.debug > 1 { x.Printf("decompose arg %s has %d locs\n", source.LongString(), len(locs)) } 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) @@ -699,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 @@ -730,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()) @@ -804,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()) @@ -830,13 +836,13 @@ 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()) } - 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) @@ -846,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) } @@ -871,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()) @@ -917,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 } @@ -946,22 +952,23 @@ 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) } 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.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 @@ -985,6 +992,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, 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) @@ -995,7 +1003,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()) @@ -1054,7 +1062,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 @@ -1065,18 +1073,23 @@ 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{} 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) @@ -1087,9 +1100,20 @@ 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, x.sp, a, mem, aOffset, aux.SizeOfArg(auxI), aType, pos) + mem = x.rewriteDereference(v.Block, sp, a, mem, aOffset, aux.SizeOfArg(auxI), aType, a.Pos) } else { var rc registerCursor var result *[]*Value @@ -1099,11 +1123,19 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) { } else { aOffset = aux.OffsetOfArg(auxI) } - if x.debug { + 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) } - rc.init(aRegs, aux.abiInfo, result, x.sp) - mem = x.storeArgOrLoad(pos, v.Block, a, mem, aType, aOffset, 0, rc) + rc.init(aRegs, aux.abiInfo, result, sp) + mem = x.storeArgOrLoad(a.Pos, v.Block, a, mem, aType, aOffset, 0, rc) } } var preArgStore [2]*Value @@ -1114,16 +1146,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 @@ -1142,7 +1189,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, @@ -1164,7 +1211,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) } @@ -1187,7 +1234,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: @@ -1204,9 +1251,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 @@ -1227,7 +1273,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? @@ -1251,13 +1297,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) @@ -1311,7 +1357,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]) } } @@ -1320,7 +1366,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]) } } @@ -1331,7 +1377,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]) } } @@ -1416,7 +1462,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: @@ -1445,7 +1491,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) @@ -1461,12 +1507,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 { @@ -1506,6 +1552,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()) @@ -1528,7 +1578,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() { @@ -1543,7 +1593,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) @@ -1577,7 +1627,7 @@ func expandCalls(f *Func) { v.SetArg(i, aa) for a.Uses == 0 { b := a.Args[0] - a.invalidateRecursively() + x.invalidateRecursively(a) a = b } } @@ -1613,7 +1663,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()) @@ -1628,9 +1678,9 @@ 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 { + if w != nil && w.Uses != 0 { // do not reuse dead value v.copyOf(w) break } @@ -1644,7 +1694,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 @@ -1654,16 +1704,22 @@ 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) } - key := selKey{baseArg, offset, t.Width, t} + 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 } @@ -1690,7 +1746,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 @@ -1721,7 +1777,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/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index 8ed8a0c4a6e3b725f5f621b0ea8855a3a6b9bac7..c4e87ec7d0f9e8c74d5ff10703f27f09b5e5fa01 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 @@ -39,7 +41,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 @@ -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() } diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index fac876c23ebc2eede4fabfc5a085a962bb99f11b..7728a395e05cb666e242631d1e219570623cc3b2 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/fuse_branchredirect.go b/src/cmd/compile/internal/ssa/fuse_branchredirect.go index 1b8b307bcac7a213880b25ca64f71eff41639dc7..751dca7468bc748af777e83d3565511e002473d6 100644 --- a/src/cmd/compile/internal/ssa/fuse_branchredirect.go +++ b/src/cmd/compile/internal/ssa/fuse_branchredirect.go @@ -78,7 +78,7 @@ func fuseBranchRedirect(f *Func) bool { if v.Op != OpPhi { continue } - v.RemoveArg(k) + b.removePhiArg(v, k) phielimValue(v) } // Fix up child to have one more predecessor. diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules index 199b73c42f436fcfc88e422d196ffd8904780787..7bdebedafef81f6a1e1f3821e1a5fc1d59322365 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 c4b49fbb23067d4e52e5940a25e6351b7adc4060..f4c89b0bb3152926b03599f1e48bf87b78d8f6ba 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 @@ -297,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 @@ -454,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, 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/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 4cd00732fc3f5e5f8a4098f6a0b0261f01c9a4a8..47a6af003c9ecd9b6d9f376d608e646cdc8d0296 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 @@ -362,26 +368,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) @@ -408,6 +414,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 @@ -460,12 +467,12 @@ (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 ...) -(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) @@ -638,6 +645,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 @@ -1134,8 +1142,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 +1153,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 +1905,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)) @@ -2013,50 +2029,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) - -(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) - // 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) @@ -2235,3 +2207,41 @@ && isInlinableMemmove(dst, src, sz, config) && clobber(call) => (Move [sz] dst src mem) + +// 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) + +(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 67b3293903cd915f5ef2e3839b806fe0230370fd..a6906bec7c74eae3768d6577524ba3661beb2382 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{ @@ -511,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. @@ -679,20 +681,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 +718,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 ... @@ -763,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, 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 @@ -900,6 +903,31 @@ 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}, + + // 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) + // 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}, + + // 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/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index bcacbafe3a5f0299dd47e45962a46170bd9896d4..2bc58a3c47c82c0280414ca094f848ac61c07e02 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 ...) @@ -497,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)) @@ -507,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)) @@ -1072,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) @@ -1135,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)) @@ -1237,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 62699f290c2149e6308c4f0d3d82b9b20e3d7738..d34e1899db50909a1e0cabd212840c36400bef88 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 ...) @@ -567,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) @@ -1174,6 +1178,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)) @@ -1359,6 +1366,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) @@ -1596,6 +1604,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]) @@ -1605,21 +1614,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]) @@ -1632,6 +1647,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])) @@ -1640,12 +1656,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]))) @@ -1655,11 +1674,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))]) @@ -1672,21 +1693,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)]) @@ -1696,29 +1723,36 @@ (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]) -(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 -(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 => (MOVDconst [0]) -(XORshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [0]) -(XORshiftRA x (SRAconst 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]) -(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]) -(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]) +(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) @@ -1824,16 +1858,26 @@ // 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) +// 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 (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) +// 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() @@ -1843,42 +1887,48 @@ => (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) +(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() @@ -2860,6 +2910,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 @@ -2868,3 +2922,14 @@ && 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) + +((REV|REVW) ((REV|REVW) p)) => p diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index 18a5666b40f0dfcce916f12efb228ee6b2ec1100..e052ce09f423bee903fe537da9655546d7a572c2 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 @@ -301,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. @@ -313,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. @@ -337,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 @@ -482,9 +491,10 @@ 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: "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 // pseudo-ops {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem. @@ -729,6 +739,13 @@ 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}, + + // Publication barrier + {name: "DMB", argLength: 1, aux: "Int64", asm: "DMB", hasSideEffects: true}, // Do data barrier. arg0=memory, aux=option. } blocks := []blockData{ @@ -759,15 +776,17 @@ func init() { } archs = append(archs, arch{ - name: "ARM64", - pkg: "cmd/internal/obj/arm64", - genfile: "../../arm64/ssa.go", - ops: ops, - blocks: blocks, - regnames: regNamesARM64, - gpregmask: gp, - fpregmask: fp, - framepointerreg: -1, // not used - linkreg: int8(num["R30"]), + 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"]), }) } diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go index d1f86039a36e5c98ab7d6681928d67ea50e66302..2f004205a55b357406a8f5cc32b42eeba653a0a8 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 @@ -431,6 +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, 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/MIPS.rules b/src/cmd/compile/internal/ssa/gen/MIPS.rules index 4ac9668ea9cb566154a506ba1c3c0ecac7a144e7..639dda4b075492d3d8a499b71fa6616a2cbcb10c 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 fd04a6c3a85c7ae768fa36d3a4a9bafb65b53012..292ff2fc7966092fac267f78a39a1d939e221c12 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 77f251c0d3f920ed3c1e43fefe781e5257b3748e..7b18c42ffb91e35c73e202a7e0b62f9dbb3b9754 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 @@ -275,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, 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 b92e8cb9f1ee64b38db0a24a78cc2058ddb7b0da..523847badc9ce2d77db0c54757e81e50e2d706bd 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 @@ -257,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, 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/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index ce4b324b5e10227bef0406b69f33b2bdef3652c9..c3f07a4e22cf3929a4af63e5a7482d70d7aafa60 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) @@ -580,7 +582,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) @@ -670,6 +672,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // Miscellaneous (GetClosurePtr ...) => (LoweredGetClosurePtr ...) @@ -847,6 +850,8 @@ (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) +(NEG (NEG x)) => x // Use register moves instead of stores and loads to move int<=>float values // Common with math Float64bits, Float64frombits @@ -1018,6 +1023,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 @@ -1084,7 +1091,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) @@ -1135,6 +1142,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) @@ -1450,3 +1460,26 @@ && 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) + +// 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 f7198b90c32e48ce940e6b52530aee7dea47c4fb..59d8af1a9d3952fb1bfeee88af01200fc618cf6a 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 @@ -148,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 @@ -335,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 @@ -390,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 @@ -427,9 +433,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: "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, 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 // large or unaligned zeroing // arg0 = address of memory to zero (in R3, changed as side effect) @@ -703,15 +710,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/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 9cdd62edbe01c004f4b79951d38a4d5cd123a2a3..3379e1dac50cc36720367505e474cc4fba901e78 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 @@ -29,6 +27,8 @@ (Sub64F ...) => (FSUBD ...) (Mul64 ...) => (MUL ...) +(Mul64uhilo ...) => (LoweredMuluhilo ...) +(Mul64uover ...) => (LoweredMuluover ...) (Mul32 ...) => (MULW ...) (Mul16 x y) => (MULW (SignExt16to32 x) (SignExt16to32 y)) (Mul8 x y) => (MULW (SignExt8to32 x) (SignExt8to32 y)) @@ -94,6 +94,12 @@ (Sqrt ...) => (FSQRTD ...) (Sqrt32 ...) => (FSQRTS ...) +(Copysign ...) => (FSGNJD ...) + +(Abs ...) => (FABSD ...) + +(FMA ...) => (FMADDD ...) + // Sign and zero extension. (SignExt8to16 ...) => (MOVBreg ...) @@ -221,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]))) @@ -538,6 +544,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // Atomic Intrinsics (AtomicLoad8 ...) => (LoweredAtomicLoad8 ...) @@ -586,6 +593,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) @@ -594,11 +605,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) @@ -690,16 +705,49 @@ (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. +// +// 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 0ac9c5f62ad176700958b5b648992cd3a3410e3e..076919773b47a3deb19862f5ebf74e6b5e79fa65 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 @@ -28,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 @@ -79,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 @@ -122,6 +124,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}} @@ -130,6 +133,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}} @@ -156,6 +160,9 @@ 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: "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"}, {name: "DIVW", argLength: 2, reg: gp21, asm: "DIVW", typ: "Int32"}, @@ -234,9 +241,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: "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) @@ -420,8 +428,14 @@ 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: "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/gen/S390X.rules b/src/cmd/compile/internal/ssa/gen/S390X.rules index 88762f704589067c018bb110090397d7d51261de..b3928c6a1e6e4df84c241835c310dde974287b1d 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 5b33ba710e9818799df21ca130049381ced03c5b..eef8a2557ca39d51e91cb5c5715d3b4d5678c0a2 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 @@ -479,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, 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 @@ -507,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/gen/Wasm.rules b/src/cmd/compile/internal/ssa/gen/Wasm.rules index 7ad3d1c72e1fb04db56f2b937410dd030de4fea7..9e683b116c1613423505e365cc7ffc3bfd071901 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 c92878ca73b844a1a906829ba70b903e48391f90..edfba4ee99b774962a26cedf43994527ee939d11 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 @@ -123,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, 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/dec64Ops.go b/src/cmd/compile/internal/ssa/gen/dec64Ops.go index 8c5883bc5691348147d6845b20af96e961007100..78fcea885aa8b250304d0064e32ad0b03f52bc8e 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 b826481c9fbb2fdcb90b41742d66561f88a64014..d5cd79378c76a3041e007bc197c171f7272a4bda 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/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 5cbc70cf41d1c68c928c203c9fc77c53baa8882d..6dbe9b47d011fabd3c83e493b126a981efa45191 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]) @@ -590,6 +593,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]) @@ -2004,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/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 9f6664386c9d1749e51c4d6bd3a29c6fecd7d37d..4f133b1ff6a1b85de79dec35a4360d9cb2d2a231 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 @@ -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"}, @@ -615,9 +617,16 @@ 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 + + // 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 @@ -634,7 +643,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/gen/main.go b/src/cmd/compile/internal/ssa/gen/main.go index 8e5997b25a447339b1bd80b1604a772e2ef82b16..2cf0a919fa6ebc2b07871249ce391439c44bb4e9 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/html.go b/src/cmd/compile/internal/ssa/html.go index 4d191199fbafe1b3f5f61882a40aced0e836cf36..d9a78b396243beb32e912549f89a83ef72c692a5 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) @@ -1221,7 +1218,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/location.go b/src/cmd/compile/internal/ssa/location.go index 252c47cdebc8b6ab4a4523e4042c3d34724520be..b575febd72741158bab236eeea768e8ac2677874 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 = "," diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index f09a08abcf752102944a3aba872105ac9ebe392d..a1835dcd3026ecb3f9ef137e38af0033831440cf 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) @@ -102,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 @@ -254,13 +259,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/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 1c37fbe0db4a49b7c7ff6d6a9668a6fdc745218a..81fe5d4c23cbc6d99054e54f7e2c95688a465063 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 @@ -962,7 +963,6 @@ const ( OpAMD64MOVQstore OpAMD64MOVOload OpAMD64MOVOstore - OpAMD64MOVOstorezero OpAMD64MOVBloadidx1 OpAMD64MOVWloadidx1 OpAMD64MOVWloadidx2 @@ -983,6 +983,7 @@ const ( OpAMD64MOVWstoreconst OpAMD64MOVLstoreconst OpAMD64MOVQstoreconst + OpAMD64MOVOstoreconst OpAMD64MOVBstoreconstidx1 OpAMD64MOVWstoreconstidx1 OpAMD64MOVWstoreconstidx2 @@ -993,6 +994,7 @@ const ( OpAMD64DUFFZERO OpAMD64REPSTOSQ OpAMD64CALLstatic + OpAMD64CALLtail OpAMD64CALLclosure OpAMD64CALLinter OpAMD64DUFFCOPY @@ -1029,6 +1031,22 @@ const ( OpAMD64ANDLlock OpAMD64ORBlock OpAMD64ORLlock + OpAMD64PrefetchT0 + OpAMD64PrefetchNTA + OpAMD64ANDNQ + OpAMD64ANDNL + OpAMD64BLSIQ + OpAMD64BLSIL + OpAMD64BLSMSKQ + OpAMD64BLSMSKL + OpAMD64BLSRQ + OpAMD64BLSRL + OpAMD64TZCNTQ + OpAMD64TZCNTL + OpAMD64MOVBELload + OpAMD64MOVBELstore + OpAMD64MOVBEQload + OpAMD64MOVBEQstore OpARMADD OpARMADDconst @@ -1267,6 +1285,7 @@ const ( OpARMCMOVWLSconst OpARMSRAcond OpARMCALLstatic + OpARMCALLtail OpARMCALLclosure OpARMCALLinter OpARMLoweredNilCheck @@ -1407,6 +1426,7 @@ const ( OpARM64MVNshiftLL OpARM64MVNshiftRL OpARM64MVNshiftRA + OpARM64MVNshiftRO OpARM64NEGshiftLL OpARM64NEGshiftRL OpARM64NEGshiftRA @@ -1419,21 +1439,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 @@ -1443,6 +1469,7 @@ const ( OpARM64TSTshiftLL OpARM64TSTshiftRL OpARM64TSTshiftRA + OpARM64TSTshiftRO OpARM64BFI OpARM64BFXIL OpARM64SBFIZ @@ -1550,6 +1577,7 @@ const ( OpARM64CSNEG OpARM64CSETM OpARM64CALLstatic + OpARM64CALLtail OpARM64CALLclosure OpARM64CALLinter OpARM64LoweredNilCheck @@ -1610,6 +1638,8 @@ const ( OpARM64LoweredPanicBoundsA OpARM64LoweredPanicBoundsB OpARM64LoweredPanicBoundsC + OpARM64PRFM + OpARM64DMB OpMIPSADD OpMIPSADDconst @@ -1694,6 +1724,7 @@ const ( OpMIPSMOVFD OpMIPSMOVDF OpMIPSCALLstatic + OpMIPSCALLtail OpMIPSCALLclosure OpMIPSCALLinter OpMIPSLoweredAtomicLoad8 @@ -1810,6 +1841,7 @@ const ( OpMIPS64MOVFD OpMIPS64MOVDF OpMIPS64CALLstatic + OpMIPS64CALLtail OpMIPS64CALLclosure OpMIPS64CALLinter OpMIPS64DUFFZERO @@ -1966,6 +1998,7 @@ const ( OpPPC64MOVDBRloadidx OpPPC64FMOVDloadidx OpPPC64FMOVSloadidx + OpPPC64DCBT OpPPC64MOVDBRstore OpPPC64MOVWBRstore OpPPC64MOVHBRstore @@ -2022,6 +2055,7 @@ const ( OpPPC64LoweredRound32F OpPPC64LoweredRound64F OpPPC64CALLstatic + OpPPC64CALLtail OpPPC64CALLclosure OpPPC64CALLinter OpPPC64LoweredZero @@ -2069,6 +2103,8 @@ const ( OpRISCV64MULW OpRISCV64MULH OpRISCV64MULHU + OpRISCV64LoweredMuluhilo + OpRISCV64LoweredMuluover OpRISCV64DIV OpRISCV64DIVU OpRISCV64DIVW @@ -2123,6 +2159,7 @@ const ( OpRISCV64SLTIU OpRISCV64MOVconvert OpRISCV64CALLstatic + OpRISCV64CALLtail OpRISCV64CALLclosure OpRISCV64CALLinter OpRISCV64DUFFZERO @@ -2172,8 +2209,14 @@ const ( OpRISCV64FSUBD OpRISCV64FMULD OpRISCV64FDIVD + OpRISCV64FMADDD + OpRISCV64FMSUBD + OpRISCV64FNMADDD + OpRISCV64FNMSUBD OpRISCV64FSQRTD OpRISCV64FNEGD + OpRISCV64FABSD + OpRISCV64FSGNJD OpRISCV64FMVDX OpRISCV64FCVTDW OpRISCV64FCVTDL @@ -2375,6 +2418,7 @@ const ( OpS390XMOVDstoreconst OpS390XCLEAR OpS390XCALLstatic + OpS390XCALLtail OpS390XCALLclosure OpS390XCALLinter OpS390XInvertFlags @@ -2428,6 +2472,7 @@ const ( OpS390XLoweredZero OpWasmLoweredStaticCall + OpWasmLoweredTailCall OpWasmLoweredClosureCall OpWasmLoweredInterCall OpWasmLoweredAddr @@ -2774,9 +2819,11 @@ const ( OpClosureCall OpStaticCall OpInterCall + OpTailCall OpClosureLECall OpStaticLECall OpInterLECall + OpTailLECall OpSignExt8to16 OpSignExt8to32 OpSignExt8to64 @@ -2910,8 +2957,11 @@ const ( OpAtomicAnd32Variant OpAtomicOr8Variant OpAtomicOr32Variant + OpPubBarrier OpClobber OpClobberReg + OpPrefetchCache + OpPrefetchCacheStreamed ) var opcodeTable = [...]opInfo{ @@ -4687,7 +4737,6 @@ var opcodeTable = [...]opInfo{ name: "NOTL", argLen: 1, resultInArg0: true, - clobberFlags: true, asm: x86.ANOTL, reg: regInfo{ inputs: []inputInfo{ @@ -5893,6 +5942,17 @@ 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, + tailCall: true, + reg: regInfo{ + clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -10721,7 +10781,6 @@ var opcodeTable = [...]opInfo{ name: "NOTQ", argLen: 1, resultInArg0: true, - clobberFlags: true, asm: x86.ANOTQ, reg: regInfo{ inputs: []inputInfo{ @@ -10736,7 +10795,6 @@ var opcodeTable = [...]opInfo{ name: "NOTL", argLen: 1, resultInArg0: true, - clobberFlags: true, asm: x86.ANOTL, reg: regInfo{ inputs: []inputInfo{ @@ -12623,19 +12681,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, @@ -12952,6 +12997,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, @@ -13090,6 +13148,17 @@ 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, + 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 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -13553,6 +13622,230 @@ 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: "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: "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: "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", @@ -16904,6 +17197,17 @@ 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, + 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 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -18730,6 +19034,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, @@ -18907,6 +19225,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, @@ -18952,6 +19285,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, @@ -18997,6 +19345,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, @@ -19042,6 +19405,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, @@ -19087,6 +19465,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, @@ -19132,6 +19525,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, @@ -19240,6 +19648,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, @@ -20664,17 +21084,28 @@ var opcodeTable = [...]opInfo{ { name: "CALLstatic", auxType: auxCallOff, - argLen: 1, + 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: "CALLtail", + auxType: auxCallOff, + 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 + }, + }, { name: "CALLclosure", auxType: auxCallOff, - argLen: 3, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ @@ -20688,7 +21119,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLinter", auxType: auxCallOff, - argLen: 2, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ @@ -21445,6 +21876,26 @@ 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: "DMB", + auxType: auxInt64, + argLen: 1, + hasSideEffects: true, + asm: arm64.ADMB, + reg: regInfo{}, + }, { name: "ADD", @@ -22592,6 +23043,17 @@ 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, + 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 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -24151,6 +24613,17 @@ 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, + 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 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -26310,6 +26783,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, @@ -26972,9 +27457,20 @@ var opcodeTable = [...]opInfo{ { name: "CALLstatic", auxType: auxCallOff, - argLen: 1, + 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: "CALLtail", + auxType: auxCallOff, + 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 }, @@ -26982,7 +27478,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLclosure", auxType: auxCallOff, - argLen: 3, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ @@ -26996,7 +27492,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLinter", auxType: auxCallOff, - argLen: 2, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ @@ -27453,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 }, }, }, @@ -27468,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 }, }, }, @@ -27482,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 }, }, }, @@ -27495,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 }, }, }, @@ -27508,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 }, }, }, @@ -27521,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 }, }, }, @@ -27535,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 }, }, }, @@ -27550,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 }, }, }, @@ -27565,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 }, }, }, @@ -27580,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 }, }, }, @@ -27595,11 +28091,41 @@ 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 + }, + }, + }, + { + name: "LoweredMuluhilo", + argLen: 2, + resultNotInArgs: true, + reg: regInfo{ + inputs: []inputInfo{ + {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, 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 + }, + }, + }, + { + name: "LoweredMuluover", + argLen: 2, + resultNotInArgs: true, + reg: regInfo{ + inputs: []inputInfo{ + {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, 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 }, }, }, @@ -27609,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 }, }, }, @@ -27623,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 }, }, }, @@ -27637,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 }, }, }, @@ -27651,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 }, }, }, @@ -27665,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 }, }, }, @@ -27679,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 }, }, }, @@ -27693,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 }, }, }, @@ -27707,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 }, }, }, @@ -27724,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 }, }, }, @@ -27739,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 }, }, }, @@ -27752,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 }, }, }, @@ -27768,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 }, }, }, @@ -27784,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 }, }, }, @@ -27800,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 }, }, }, @@ -27816,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 }, }, }, @@ -27832,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 }, }, }, @@ -27848,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 }, }, }, @@ -27864,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 }, }, }, @@ -27878,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 }, }, }, @@ -27892,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 }, }, }, @@ -27906,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 }, }, }, @@ -27920,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 }, }, }, @@ -27933,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 }, }, }, @@ -27946,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 }, }, }, @@ -27959,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 }, }, }, @@ -27969,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 }, }, }, @@ -27982,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 }, }, }, @@ -27995,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 }, }, }, @@ -28008,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 }, }, }, @@ -28021,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 }, }, }, @@ -28034,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 }, }, }, @@ -28047,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 }, }, }, @@ -28060,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 }, }, }, @@ -28073,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 }, }, }, @@ -28087,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 }, }, }, @@ -28101,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 }, }, }, @@ -28116,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 }, }, }, @@ -28130,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 }, }, }, @@ -28144,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 }, }, }, @@ -28158,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 }, }, }, @@ -28173,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 }, }, }, @@ -28187,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 }, }, }, @@ -28202,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 }, }, }, @@ -28216,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 }, }, }, @@ -28231,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 }, }, }, @@ -28244,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 }, }, }, @@ -28257,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 }, }, }, @@ -28270,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 }, }, }, @@ -28283,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 }, }, }, @@ -28298,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 }, }, }, @@ -28311,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 }, }, }, @@ -28326,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 }, }, }, @@ -28339,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 }, }, }, @@ -28352,7 +28878,17 @@ 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 + }, + }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: 1, + call: true, + tailCall: true, + reg: regInfo{ + 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 }, }, { @@ -28363,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 }, }, { @@ -28375,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 }, }, { @@ -28414,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 }, @@ -28429,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 }, @@ -28440,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 }, }, }, @@ -28453,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 }, }, }, @@ -28466,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 }, }, }, @@ -28480,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 }, }, }, @@ -28492,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 }, }, }, @@ -28504,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 }, }, }, @@ -28517,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 }, }, }, @@ -28533,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 }, }, }, @@ -28550,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 }, }, }, @@ -28567,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 }, }, }, @@ -28584,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 }, }, }, @@ -28602,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 }, }, }, @@ -28619,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 }, }, }, @@ -28632,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 }, }, }, @@ -28644,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 }, }, }, @@ -28663,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 }, }, }, @@ -28673,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 }, }, }, @@ -28817,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 @@ -28830,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 @@ -28843,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 @@ -28859,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 }, }, }, @@ -28872,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 }, }, }, @@ -28885,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 @@ -28901,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 }, }, @@ -28917,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 }, }, }, @@ -28932,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 }, }, }, @@ -28946,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 }, }, }, @@ -28960,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 }, }, }, @@ -29022,6 +29558,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, @@ -29048,13 +29648,40 @@ 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, 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 @@ -29067,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 @@ -29080,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 @@ -29096,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 }, }, }, @@ -29109,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 }, }, }, @@ -29148,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 @@ -29164,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 }, }, @@ -29180,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 }, }, }, @@ -29195,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 }, }, }, @@ -29209,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 }, }, }, @@ -29223,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 }, }, }, @@ -32019,6 +32646,17 @@ 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, + 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 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -32141,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 }, }, { @@ -32689,6 +33327,16 @@ 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, + 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 + }, + }, { name: "LoweredClosureCall", auxType: auxCallOff, @@ -35465,6 +36113,13 @@ var opcodeTable = [...]opInfo{ call: true, generic: true, }, + { + name: "TailCall", + auxType: auxCallOff, + argLen: -1, + call: true, + generic: true, + }, { name: "ClosureLECall", auxType: auxCallOff, @@ -35486,6 +36141,13 @@ var opcodeTable = [...]opInfo{ call: true, generic: true, }, + { + name: "TailLECall", + auxType: auxCallOff, + argLen: -1, + call: true, + generic: true, + }, { name: "SignExt8to16", argLen: 1, @@ -36201,6 +36863,12 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, generic: true, }, + { + name: "PubBarrier", + argLen: 1, + hasSideEffects: true, + generic: true, + }, { name: "Clobber", auxType: auxSymOff, @@ -36213,6 +36881,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 } @@ -36220,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 } @@ -36400,8 +37081,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) @@ -36602,44 +37283,44 @@ 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"}, {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"}, @@ -36677,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/cmd/compile/internal/ssa/print.go b/src/cmd/compile/internal/ssa/print.go index d917183c70f5e8f23ff904a6421983e8a1770b25..96cd2c7c90a539677ec393f03708c49106a6372d 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" @@ -17,22 +18,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 +49,8 @@ type funcPrinter interface { } type stringFuncPrinter struct { - w io.Writer + w io.Writer + printDead bool } func (p stringFuncPrinter) header(f *Func) { @@ -50,6 +60,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,14 +77,33 @@ 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 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) { - fmt.Fprint(p.w, " ") - //fmt.Fprint(p.w, v.Block.Func.fe.Pos(v.Pos)) - //fmt.Fprint(p.w, ": ") + if !p.printDead && !live { + return + } + fmt.Fprintf(p.w, " %s", StmtString(v.Pos)) fmt.Fprint(p.w, v.LongString()) if !live { fmt.Fprint(p.w, " DEAD") @@ -103,7 +135,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 +183,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/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 3b90b8769c2f1d8ffe484b0ab40d832aea650175..64792d0c80b241663f70ae336024fd773bc20a97 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 the return PC or need a frame return false } } @@ -620,20 +621,22 @@ 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 "riscv64": // X3 (aka GP) and X4 (aka TP) already reserved. + // nothing to do case "s390x": s.allocatable &^= 1 << 11 // R11 default: @@ -1840,7 +1843,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 @@ -1865,23 +1868,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 } diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 375c4d5a5605f531b6b5ab761be276f41d72031b..9136c59e65494f8ee56341965a652f04bd1466ab 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 { @@ -389,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)) } @@ -745,27 +776,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 +801,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 } @@ -795,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 } @@ -1263,7 +1288,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. @@ -1287,7 +1312,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. @@ -1311,7 +1336,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. @@ -1551,12 +1576,16 @@ 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 { 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/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go index 1ec2d26f750f6b7998933fca8cbeb668d9188f1a..34f37867cf6149140eb883b4f67f37e26c1cb179 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 5045ba7351f447ce13814b8ee6b3580cb9ed7ea6..0c789d6b496477c66c4213b220d1cd9d4a2e6708 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -54,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: @@ -66,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: @@ -214,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: @@ -250,6 +262,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: @@ -641,13 +655,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: @@ -655,8 +667,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 @@ -950,6 +961,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 @@ -1096,6 +1113,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: @@ -2749,6 +2769,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 { @@ -3027,6 +3096,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] @@ -3128,6 +3239,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 { @@ -3455,6 +3615,108 @@ 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 + } + // 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 { + 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 + } + // 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 { v_0 := v.Args[0] // match: (BTCLconst [c] (XORLconst [d] x)) @@ -9211,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 @@ -9631,49 +9939,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)))]) @@ -10878,51 +11143,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 { @@ -11021,49 +11241,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 { @@ -11492,49 +11669,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 { @@ -11836,51 +11970,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) @@ -12260,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 { @@ -12364,49 +12475,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 { @@ -12545,6 +12613,54 @@ 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 + } + return false +} func rewriteValueAMD64_OpAMD64MOVQatomicload(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -12713,49 +12829,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 { @@ -12858,51 +12931,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) @@ -13282,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 { @@ -13332,9 +13382,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) @@ -13343,61 +13393,43 @@ 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 && 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 } - // 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) + // 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 { - 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)) { + a := auxIntToValAndOff(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + x := v_1 + if x.Op != OpAMD64MOVQstoreconst { 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 { + c := auxIntToValAndOff(x.AuxInt) + if auxToSym(x.Aux) != s { break } - off := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(sc.canAdd32(off)) { + 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(OpAMD64MOVQstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(makeValAndOff(0, a.Off())) v.Aux = symToAux(s) - v.AddArg2(ptr, mem) + v.AddArg2(p, mem) return true } return false @@ -14018,49 +14050,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))]) @@ -14454,51 +14443,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 { @@ -14597,49 +14541,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 { @@ -18924,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 { @@ -26915,6 +26891,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 { @@ -27391,6 +27382,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 { @@ -28960,14 +28966,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) @@ -28977,16 +29027,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)) @@ -28999,21 +29094,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] @@ -29031,6 +29144,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] @@ -29339,11 +29480,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) @@ -29356,11 +29497,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) @@ -33459,7 +33600,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 @@ -33472,14 +33613,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 @@ -33492,7 +33634,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) @@ -33500,7 +33642,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 @@ -33510,13 +33652,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 @@ -33526,18 +33669,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 @@ -33547,23 +33689,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 @@ -33573,23 +33712,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) diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index febb5566e338492cb6f42e30d013b454b579fa4a..496f9b4ae2ef117031e08f43f97c575c371721d1 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: @@ -855,6 +857,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 @@ -1119,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 @@ -1128,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) @@ -1199,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 @@ -1208,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) @@ -1279,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 @@ -1288,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) @@ -1740,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 @@ -1748,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) @@ -1814,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 @@ -1822,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) @@ -1888,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 @@ -1896,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) @@ -2124,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 @@ -2132,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) @@ -2198,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 @@ -2206,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) @@ -2288,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 @@ -2296,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) @@ -2614,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) @@ -2655,6 +2694,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 @@ -2663,6 +2703,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) @@ -2705,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) @@ -2746,6 +2787,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 @@ -2754,6 +2796,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) @@ -2796,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) @@ -2837,6 +2880,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 @@ -2845,6 +2889,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) @@ -3091,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) @@ -3115,6 +3160,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 @@ -3123,6 +3169,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) @@ -3147,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) @@ -3171,6 +3218,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 @@ -3179,6 +3227,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) @@ -3203,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) @@ -3227,6 +3276,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 @@ -3235,6 +3285,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) @@ -3437,6 +3490,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 @@ -3445,6 +3499,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) @@ -3511,6 +3568,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 @@ -3519,6 +3577,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) @@ -3585,6 +3646,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 @@ -3593,6 +3655,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) @@ -4090,6 +4155,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 @@ -4098,6 +4164,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) @@ -4168,6 +4237,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 @@ -4176,6 +4246,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) @@ -4246,6 +4319,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 @@ -4254,6 +4328,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) @@ -8101,6 +8178,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 @@ -8108,6 +8186,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) @@ -8135,6 +8216,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 @@ -8142,6 +8224,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) @@ -8169,6 +8254,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 @@ -8176,6 +8262,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) @@ -8556,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) @@ -8597,6 +8684,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 @@ -8605,6 +8693,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) @@ -8647,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) @@ -8688,6 +8777,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 @@ -8696,6 +8786,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) @@ -8754,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) @@ -8795,6 +8886,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 @@ -8803,6 +8895,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) @@ -9090,6 +9185,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 @@ -9098,6 +9194,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) @@ -9164,6 +9263,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 @@ -9172,6 +9272,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) @@ -9238,6 +9341,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 @@ -9246,6 +9350,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) @@ -9346,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) @@ -9387,6 +9492,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 @@ -9395,6 +9501,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) @@ -9437,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) @@ -9478,6 +9585,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 @@ -9486,6 +9594,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) @@ -9528,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) @@ -9569,6 +9678,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 @@ -9577,6 +9687,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) @@ -9683,6 +9796,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 @@ -9692,6 +9806,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) @@ -9763,6 +9880,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 @@ -9772,6 +9890,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) @@ -9843,6 +9964,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 @@ -9852,6 +9974,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) @@ -10166,6 +10291,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 @@ -10175,6 +10301,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) @@ -10246,6 +10375,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 @@ -10255,6 +10385,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) @@ -10326,6 +10459,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 @@ -10335,6 +10469,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) @@ -10346,15 +10483,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 } @@ -10380,15 +10521,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 } @@ -10472,15 +10617,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 } @@ -10520,6 +10669,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] @@ -11058,6 +11225,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 @@ -11066,6 +11234,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) @@ -11132,6 +11303,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 @@ -11140,6 +11312,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) @@ -11206,6 +11381,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 @@ -11214,6 +11390,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) @@ -11368,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) @@ -11409,6 +11586,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 @@ -11417,6 +11595,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) @@ -11459,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) @@ -11500,6 +11679,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 @@ -11508,6 +11688,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) @@ -11550,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) @@ -11591,6 +11772,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 @@ -11599,6 +11781,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) @@ -11801,6 +11986,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 @@ -11809,6 +11995,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) @@ -11875,6 +12064,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 @@ -11883,6 +12073,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) @@ -11949,6 +12142,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 @@ -11957,6 +12151,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) @@ -12159,6 +12356,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 @@ -12167,6 +12365,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) @@ -12233,6 +12434,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 @@ -12241,6 +12443,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) @@ -12307,6 +12512,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 @@ -12315,6 +12521,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) @@ -12595,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) @@ -12636,6 +12843,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 @@ -12644,6 +12852,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) @@ -12686,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) @@ -12727,6 +12936,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 @@ -12735,6 +12945,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) @@ -12793,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) @@ -12834,6 +13045,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 @@ -12842,6 +13054,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) @@ -14901,19 +15116,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 3cdc4d36cb5a400fbb419aa5b896074bc5243d61..ad34855c30f6be4e70f6c4af52e5104c1f54abf8 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,16 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64ORshiftRA(v) case OpARM64ORshiftRL: 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: + return rewriteValueARM64_OpARM64RORW(v) case OpARM64RORWconst: return rewriteValueARM64_OpARM64RORWconst(v) case OpARM64RORconst: @@ -367,6 +387,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: @@ -389,6 +411,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 @@ -896,6 +920,12 @@ 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 OpPubBarrier: + return rewriteValueARM64_OpPubBarrier(v) case OpRotateLeft16: return rewriteValueARM64_OpRotateLeft16(v) case OpRotateLeft32: @@ -1038,6 +1068,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 @@ -2103,6 +2136,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 { @@ -2265,18 +2320,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) @@ -2319,18 +2372,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) @@ -2373,18 +2424,68 @@ 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 { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64SRLconst || auxIntToInt64(y.AuxInt) != c { + break + } + x := y.Args[0] + if x != v_1 { + break + } + v.copyOf(y) + return true + } + 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 - y := v_1 - if y.Op != OpARM64SRLconst { + 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 y:(RORconst x [c]) x [c]) + // result: y + for { + 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) @@ -2476,6 +2577,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 { @@ -2495,17 +2615,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) @@ -2531,17 +2649,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) @@ -2567,17 +2683,49 @@ 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 { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c { + break + } + x := v_0.Args[0] + if x != v_1 { + break + } + v.reset(OpARM64MOVDconst) + v.AuxInt = int64ToAuxInt(0) + return true + } + 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 != OpARM64SRLconst { + if v_1.Op != OpARM64MOVDconst { break } c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + v.reset(OpARM64ANDconst) + v.AuxInt = int64ToAuxInt(^rotateRight64(c, d)) + v.AddArg(x) + return true + } + // match: (BICshiftRO (RORconst x [c]) x [c]) + // result: (MOVDconst [0]) + for { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORconst || auxIntToInt64(v_0.AuxInt) != c { + break + } + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -3926,6 +4074,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 { @@ -3945,17 +4112,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) @@ -3981,17 +4146,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) @@ -4017,17 +4180,49 @@ 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 { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c { + break + } + x := v_0.Args[0] + if x != v_1 { + break + } + v.reset(OpARM64MOVDconst) + v.AuxInt = int64ToAuxInt(-1) + return true + } + 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 != OpARM64SRLconst { + if v_1.Op != OpARM64MOVDconst { break } c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + v.reset(OpARM64XORconst) + v.AuxInt = int64ToAuxInt(^rotateRight64(c, d)) + v.AddArg(x) + return true + } + // match: (EONshiftRO (RORconst x [c]) x [c]) + // result: (MOVDconst [-1]) + for { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORconst || auxIntToInt64(v_0.AuxInt) != c { + break + } + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -7153,37 +7348,54 @@ 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 !(rc < 8) { + break + } + v.reset(OpARM64UBFX) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 8)) + 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 !(isARM64BFMask(sc, 1<<8-1, 0)) { + if !(bfc.getARM64BFwidth() <= 8) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 8)) + v.AuxInt = arm64BitFieldToAuxInt(bfc) v.AddArg(x) return true } @@ -7401,6 +7613,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 { @@ -10665,37 +10894,54 @@ 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 !(rc < 16) { + break + } + v.reset(OpARM64UBFX) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 16)) + 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 !(isARM64BFMask(sc, 1<<16-1, 0)) { + if !(bfc.getARM64BFwidth() <= 16) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 16)) + v.AuxInt = arm64BitFieldToAuxInt(bfc) v.AddArg(x) return true } @@ -11096,17 +11342,34 @@ func rewriteValueARM64_OpARM64MOVHreg(v *Value) bool { v.AddArg(x) return true } - return false -} -func rewriteValueARM64_OpARM64MOVHstore(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem) - // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared) - // result: (MOVHstore [off1+int32(off2)] {sym} ptr val mem) + // 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 { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + config := b.Func.Config + // match: (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem) + // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared) + // result: (MOVHstore [off1+int32(off2)] {sym} ptr val mem) for { off1 := auxIntToInt32(v.AuxInt) sym := auxToSym(v.Aux) @@ -12777,37 +13040,54 @@ 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 !(rc < 32) { + break + } + v.reset(OpARM64UBFX) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 32)) + 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 !(isARM64BFMask(sc, 1<<32-1, 0)) { + if !(bfc.getARM64BFwidth() <= 32) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 32)) + v.AuxInt = arm64BitFieldToAuxInt(bfc) v.AddArg(x) return true } @@ -13266,6 +13546,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 { @@ -15502,6 +15799,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 { @@ -15552,6 +15867,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)) @@ -15578,6 +15909,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 { @@ -15831,6 +16172,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)) @@ -17800,6 +18163,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 { @@ -17819,17 +18201,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) @@ -17855,17 +18235,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) @@ -17891,17 +18269,49 @@ 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 { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c { + break + } + x := v_0.Args[0] + if x != v_1 { + break + } + v.reset(OpARM64MOVDconst) + v.AuxInt = int64ToAuxInt(-1) + return true + } + 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 != OpARM64SRLconst { + if v_1.Op != OpARM64MOVDconst { break } c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + v.reset(OpARM64ORconst) + v.AuxInt = int64ToAuxInt(^rotateRight64(c, d)) + v.AddArg(x) + return true + } + // match: (ORNshiftRO (RORconst x [c]) x [c]) + // result: (MOVDconst [-1]) + for { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORconst || auxIntToInt64(v_0.AuxInt) != c { + break + } + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -18014,18 +18424,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) @@ -19694,18 +20102,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) @@ -19748,18 +20154,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) @@ -19847,58 +20251,174 @@ func rewriteValueARM64_OpARM64ORshiftRL(v *Value) bool { } return false } -func rewriteValueARM64_OpARM64RORWconst(v *Value) bool { +func rewriteValueARM64_OpARM64ORshiftRO(v *Value) bool { + v_1 := v.Args[1] v_0 := v.Args[0] - // match: (RORWconst [c] (RORWconst [d] x)) - // result: (RORWconst [(c+d)&31] x) + b := v.Block + // match: (ORshiftRO (MOVDconst [c]) x [d]) + // result: (ORconst [c] (RORconst x [d])) for { - c := auxIntToInt64(v.AuxInt) - if v_0.Op != OpARM64RORWconst { + d := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVDconst { break } - d := auxIntToInt64(v_0.AuxInt) - x := v_0.Args[0] - v.reset(OpARM64RORWconst) - v.AuxInt = int64ToAuxInt((c + d) & 31) + 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 y:(RORconst x [c]) x [c]) + // result: y + for { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64RORconst || auxIntToInt64(y.AuxInt) != c { + break + } + x := y.Args[0] + if x != v_1 { + break + } + v.copyOf(y) + return true + } return false } -func rewriteValueARM64_OpARM64RORconst(v *Value) bool { +func rewriteValueARM64_OpARM64REV(v *Value) bool { v_0 := v.Args[0] - // match: (RORconst [c] (RORconst [d] x)) - // result: (RORconst [(c+d)&63] x) + // match: (REV (REV p)) + // result: p for { - c := auxIntToInt64(v.AuxInt) - if v_0.Op != OpARM64RORconst { + if v_0.Op != OpARM64REV { break } - d := auxIntToInt64(v_0.AuxInt) - x := v_0.Args[0] - v.reset(OpARM64RORconst) - v.AuxInt = int64ToAuxInt((c + d) & 63) - v.AddArg(x) + p := v_0.Args[0] + v.copyOf(p) return true } return false } -func rewriteValueARM64_OpARM64SBCSflags(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] +func rewriteValueARM64_OpARM64REVW(v *Value) bool { v_0 := v.Args[0] - b := v.Block - typ := &b.Func.Config.Types - // match: (SBCSflags x y (Select1 (NEGSflags (NEG (NGCzerocarry bo))))) - // result: (SBCSflags x y bo) + // match: (REVW (REVW p)) + // result: p for { - x := v_0 - y := v_1 - if v_2.Op != OpSelect1 || v_2.Type != types.TypeFlags { + if v_0.Op != OpARM64REVW { break } - v_2_0 := v_2.Args[0] - if v_2_0.Op != OpARM64NEGSflags { + 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] + // 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)) + // result: (RORWconst [(c+d)&31] x) + for { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORWconst { + break + } + d := auxIntToInt64(v_0.AuxInt) + x := v_0.Args[0] + v.reset(OpARM64RORWconst) + v.AuxInt = int64ToAuxInt((c + d) & 31) + v.AddArg(x) + return true + } + return false +} +func rewriteValueARM64_OpARM64RORconst(v *Value) bool { + v_0 := v.Args[0] + // match: (RORconst [c] (RORconst [d] x)) + // result: (RORconst [(c+d)&63] x) + for { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORconst { + break + } + d := auxIntToInt64(v_0.AuxInt) + x := v_0.Args[0] + v.reset(OpARM64RORconst) + v.AuxInt = int64ToAuxInt((c + d) & 63) + v.AddArg(x) + return true + } + return false +} +func rewriteValueARM64_OpARM64SBCSflags(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (SBCSflags x y (Select1 (NEGSflags (NEG (NGCzerocarry bo))))) + // result: (SBCSflags x y bo) + for { + x := v_0 + y := v_1 + if v_2.Op != OpSelect1 || v_2.Type != types.TypeFlags { + break + } + v_2_0 := v_2.Args[0] + if v_2_0.Op != OpARM64NEGSflags { break } v_2_0_0 := v_2_0.Args[0] @@ -19985,72 +20505,99 @@ 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] (MOVWreg x)) + // result: (SBFIZ [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 != OpARM64MOVWreg { break } - ac := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, ac, 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 } - v.reset(OpARM64UBFIZ) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(ac, 0))) + x := v_0.Args[0] + v.reset(OpARM64SBFIZ) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(16, 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] (MOVBreg x)) + // result: (SBFIZ [armBFAuxInt(lc, min(8, 64-lc))] x) for { - sc := auxIntToInt64(v.AuxInt) - if v_0.Op != OpARM64MOVWUreg { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVBreg { break } x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<32-1, 0)) { + v.reset(OpARM64SBFIZ) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(8, 64-lc))) + v.AddArg(x) + return true + } + // match: (SLLconst [lc] (MOVWUreg x)) + // result: (UBFIZ [armBFAuxInt(lc, min(32, 64-lc))] x) + for { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVWUreg { break } + x := v_0.Args[0] v.reset(OpARM64UBFIZ) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 32)) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(32, 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] (MOVHUreg x)) + // result: (UBFIZ [armBFAuxInt(lc, min(16, 64-lc))] x) for { - sc := auxIntToInt64(v.AuxInt) + lc := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVHUreg { break } x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<16-1, 0)) { + v.reset(OpARM64UBFIZ) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(16, 64-lc))) + v.AddArg(x) + return true + } + // match: (SLLconst [lc] (MOVBUreg x)) + // result: (UBFIZ [armBFAuxInt(lc, min(8, 64-lc))] x) + for { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVBUreg { break } + x := v_0.Args[0] 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 } @@ -20343,90 +20890,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 } @@ -20836,17 +21383,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) @@ -20872,17 +21417,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) @@ -20908,17 +21451,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) @@ -21012,6 +21553,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 { @@ -21178,6 +21741,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)) @@ -21637,6 +22237,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)) @@ -22007,17 +22629,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) @@ -22219,17 +22839,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) @@ -22273,17 +22891,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) @@ -22326,6 +22942,58 @@ 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 (RORconst x [c]) x [c]) + // result: (MOVDconst [0]) + for { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORconst || auxIntToInt64(v_0.AuxInt) != c { + break + } + x := v_0.Args[0] + if x != v_1 { + 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) @@ -24951,6 +25619,46 @@ 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_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] @@ -25997,7 +26705,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) @@ -26031,6 +26739,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 { diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS.go b/src/cmd/compile/internal/ssa/rewriteMIPS.go index 429369d631eb37bf910c4b6a845fbac06da68463..811ea9d9d326f239a20e3d2c1d06fd62a7f9c914 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 772d7b66efeebdf3bd3048c2d5285be80ea69b03..1fbd556b5cbcd7d32cb9ad6424d5c5d2a14580e7 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 96dee0bd21baf6d9f753dcbf615fee2797506fee..7592b4f50582405812ba82999ed599e8e3a43cce 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: @@ -720,6 +724,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 @@ -772,6 +778,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 @@ -1159,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 @@ -1184,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) @@ -5901,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 { @@ -7084,6 +7100,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 @@ -10540,6 +10570,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 @@ -11335,6 +11379,28 @@ 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 + } + // 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 { @@ -13875,6 +13941,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 { @@ -13899,6 +13967,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 { @@ -14000,6 +14122,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] @@ -16436,6 +16586,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 @@ -16502,14 +16728,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) diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 431fb1aaf66e0dd288704707d9ed909780533d4b..885bbaf4a1d0bf1cd3732264da50f23ed8deeaa0 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 @@ -209,6 +215,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 @@ -356,6 +365,12 @@ func rewriteValueRISCV64(v *Value) bool { case OpMul64F: v.Op = OpRISCV64FMULD return true + case OpMul64uhilo: + v.Op = OpRISCV64LoweredMuluhilo + return true + case OpMul64uover: + v.Op = OpRISCV64LoweredMuluover + return true case OpMul8: return rewriteValueRISCV64_OpMul8(v) case OpNeg16: @@ -426,6 +441,16 @@ 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: + return rewriteValueRISCV64_OpRISCV64FMSUBD(v) + case OpRISCV64FNMADDD: + return rewriteValueRISCV64_OpRISCV64FNMADDD(v) + case OpRISCV64FNMSUBD: + return rewriteValueRISCV64_OpRISCV64FNMSUBD(v) case OpRISCV64MOVBUload: return rewriteValueRISCV64_OpRISCV64MOVBUload(v) case OpRISCV64MOVBUreg: @@ -472,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: @@ -616,6 +657,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 @@ -2796,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 { @@ -2823,6 +2883,222 @@ 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] + 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] @@ -4413,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] @@ -4438,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] @@ -4456,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] @@ -4474,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] @@ -4492,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] @@ -6096,6 +6522,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 { @@ -6123,6 +6561,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) @@ -6163,6 +6647,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 { diff --git a/src/cmd/compile/internal/ssa/rewriteS390X.go b/src/cmd/compile/internal/ssa/rewriteS390X.go index 8b41d62c315bd25de6fa2adbdd553c17e1ca2a3e..0d6358614929c1adc323bd5eaadd7bb12c41a796 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 5dab09f85b35780f7113c4cb5e89e70337c7ae49..defd40ddd195e6a233e6205fcb74896ce5b52550 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/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 52258201ca105163e20197a200794c7604176ad2..fbf227562a92fc4e708aaa94746c6800d9a07918 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)) @@ -9899,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 { @@ -9914,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 { @@ -9949,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 { @@ -9964,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 { @@ -10019,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 { @@ -10034,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 { @@ -10089,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 { @@ -10104,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 { @@ -21402,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) @@ -21436,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 { @@ -22590,6 +23034,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 +23349,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 +23688,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 +24027,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/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go index 4e3e5e75e358d7f1d75a0a5c2888efdfe8fe398a..c5130b2ee50b99157fd86c04c245d926cebf03be 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 diff --git a/src/cmd/compile/internal/ssa/shortcircuit.go b/src/cmd/compile/internal/ssa/shortcircuit.go index 29abf3c591f902748ef2affd7869d8636e053d12..c0b9eacf4174d8bbb80784d7fb026a87e0bc9835 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)} diff --git a/src/cmd/compile/internal/ssa/softfloat.go b/src/cmd/compile/internal/ssa/softfloat.go index a8a8f836294b9790c4864f9674aa4dad2b94fe7c..351f824a9f579a2f8d4675e0be4d6d2a256631f2 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/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go index a510d0b3d0607c268d76b444790ed7744bd1a802..088f9802e6484f849667b54f2edea84863f8cbdb 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/quoted" "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 := quoted.Split(extld) + if err != nil { + t.Fatal(err) + } + enabled, err := cmddwarf.IsDWARFEnabledOnAIXLd(extldArgs) if err != nil { t.Fatal(err) } @@ -84,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/cmd/compile/internal/ssa/testdata/convertline.go b/src/cmd/compile/internal/ssa/testdata/convertline.go new file mode 100644 index 0000000000000000000000000000000000000000..08f3ae8a35be3fcbaaf9574a08ad665287e80aa1 --- /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/ssa/testdata/inline-dump.go b/src/cmd/compile/internal/ssa/testdata/inline-dump.go new file mode 100644 index 0000000000000000000000000000000000000000..97893b6f212f986b9931fd5f678759b6e0ded95d --- /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/pushback.go b/src/cmd/compile/internal/ssa/testdata/pushback.go new file mode 100644 index 0000000000000000000000000000000000000000..754e6cbb2307876bb4bed202c968f64c88658acd --- /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) +} 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 0000000000000000000000000000000000000000..680e1eb3a18f35ee0190a5673416cd292df5d72d --- /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/ssa/value.go b/src/cmd/compile/internal/ssa/value.go index 630e4814b99f1b38c182d684bb2b6c16f30de704..7b411a46124130b6fea4d5e04d53bd931b21c031 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) @@ -351,11 +345,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 +360,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 +372,7 @@ func (v *Value) invalidateRecursively() { v.AuxInt = 0 v.Aux = nil + return lostStmt } // copyOf is called from rewrite rules. diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index 419d91d0d367e609dcf9874cced1a58c04acdb4a..5120cd1086ac6088b54636180a6f44364d4dc550 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 @@ -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 } @@ -647,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/ssagen/abi.go b/src/cmd/compile/internal/ssagen/abi.go index e460adaf95d143f2403f40a0ab0607a68ef2ffb1..3a653e46b4b542c744feaf90b780e78cafee76b1 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 } @@ -215,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 } @@ -248,16 +249,11 @@ 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) } - if !buildcfg.Experiment.RegabiWrappers { - // Create ABI aliases instead of wrappers. - forEachWrapperABI(f, makeABIAlias) - } } if hasBody { setupTextLSym(f, 0) @@ -278,22 +274,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) { @@ -379,18 +359,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/arch.go b/src/cmd/compile/internal/ssagen/arch.go index 7215f42c059a147272500b7916df51287e7bdd7b..483e45cad43c7445c46032111434fffe16cd62a7 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) @@ -42,10 +41,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/pgen.go b/src/cmd/compile/internal/ssagen/pgen.go index 62567535d76caccdd37e1fdea3996b51a0fac13c..86d40e239d67a11816fc109bd90ab1504fa72e66 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 @@ -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) { @@ -114,7 +129,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 @@ -129,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") } @@ -141,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/pgen_test.go b/src/cmd/compile/internal/ssagen/pgen_test.go deleted file mode 100644 index 69ed8ad74e974490714d93321c62239cd0b1bb89..0000000000000000000000000000000000000000 --- 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) - } - } - } -} diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index dfa76006de790110b05def67fe3d8a4451584245..265ef1aab32e5fcc213168123c6e4a7c4fb87e55 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) @@ -97,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") @@ -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") @@ -279,18 +281,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 { @@ -324,66 +314,22 @@ 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") + x.Set(obj.AttrContentAddressable, true) 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 := 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++ - } - 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))) - } } } @@ -424,6 +370,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, @@ -537,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 { @@ -580,7 +540,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 { @@ -650,7 +610,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 { @@ -768,6 +727,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 { @@ -865,16 +849,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 { @@ -930,10 +904,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 @@ -1285,10 +1260,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 } @@ -1367,6 +1342,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") } @@ -1491,7 +1476,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 { @@ -1732,9 +1722,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) @@ -2387,8 +2379,181 @@ 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 { + 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. @@ -2536,6 +2701,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 } @@ -2547,8 +2715,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()) { @@ -2574,180 +2742,18 @@ 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) 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) @@ -3021,7 +3027,7 @@ func (s *state) expr(n ir.Node) *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) @@ -3073,7 +3079,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 @@ -3137,7 +3144,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) @@ -3149,6 +3157,10 @@ 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 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) case ir.OSLICESTR: @@ -3183,7 +3195,7 @@ 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) @@ -3191,6 +3203,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) @@ -3212,6 +3232,11 @@ func (s *state) expr(n ir.Node) *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: @@ -3653,6 +3678,7 @@ const ( callDefer callDeferStack callGo + callTail ) type sfRtCallDef struct { @@ -3703,6 +3729,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, @@ -3715,7 +3751,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) } @@ -3808,7 +3856,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]) @@ -3834,6 +3882,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 { @@ -3856,6 +3911,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, sys.PPC64) + addF("runtime/internal/sys", "PrefetchStreamed", makePrefetchFunc(ssa.OpPrefetchCacheStreamed), + sys.AMD64, sys.ARM64, sys.PPC64) + /******** runtime/internal/atomic ********/ addF("runtime/internal/atomic", "Load", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { @@ -4183,23 +4253,28 @@ 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]) }, - 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 { 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 @@ -4262,6 +4337,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 @@ -4367,7 +4446,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 { @@ -4376,7 +4455,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 { @@ -4466,8 +4545,12 @@ 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 { + 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 @@ -4481,10 +4564,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) @@ -4499,7 +4578,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 { @@ -4507,7 +4586,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 { @@ -4515,7 +4594,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 { @@ -4528,15 +4607,15 @@ 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 { 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]) @@ -4687,17 +4766,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 buildcfg.Experiment.RegabiDefer && (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) } @@ -4705,48 +4781,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(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< 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. @@ -5881,7 +5867,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) @@ -5936,7 +5922,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 @@ -6089,7 +6074,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") @@ -6210,14 +6195,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) +} + +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) +} - if n.Type().IsInterface() { - if n.Type().IsEmptyInterface() { +// 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. @@ -6225,7 +6234,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 } @@ -6247,7 +6256,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 } @@ -6255,7 +6264,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 } @@ -6277,62 +6286,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) @@ -6346,8 +6355,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) @@ -6356,10 +6365,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 @@ -6373,14 +6382,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() @@ -6389,9 +6398,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() @@ -6400,10 +6409,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]) @@ -6568,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 } @@ -6586,6 +6611,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. @@ -6599,6 +6625,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] @@ -6713,7 +6742,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 } @@ -6735,6 +6770,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 { @@ -6753,7 +6789,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) @@ -6791,10 +6828,13 @@ 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 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 @@ -6804,6 +6844,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 { @@ -6860,11 +6907,18 @@ 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 } - if f.PrintOrHtmlSSA { + if gatherPrintInfo { for ; x != s.pp.Next; x = x.Link { progToValue[x] = v } @@ -6894,7 +6948,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 } @@ -6921,8 +6975,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) @@ -6975,12 +7033,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 { @@ -7069,6 +7127,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) @@ -7446,6 +7552,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). @@ -7460,18 +7574,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. @@ -7542,10 +7644,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 @@ -7676,9 +7774,8 @@ func max8(a, b int8) int8 { return b } -// deferstruct makes a runtime._defer structure, with additional space for -// stksize bytes of args. -func deferstruct(stksize int64) *types.Type { +// deferstruct makes a runtime._defer structure. +func deferstruct() *types.Type { makefield := func(name string, typ *types.Type) *types.Field { // Unlike the global makefield function, this one needs to set Pkg // because these types might be compared (in SSA CSE sorting). @@ -7686,13 +7783,9 @@ func deferstruct(stksize int64) *types.Type { sym := &types.Sym{Name: name, Pkg: types.LocalPkg} return types.NewField(src.NoXPos, sym, typ) } - argtype := types.NewArray(types.Types[types.TUINT8], stksize) - argtype.Width = stksize - argtype.Align = 1 // These fields must match the ones in runtime/runtime2.go:_defer and - // cmd/compile/internal/gc/ssa.go:(*state).call. + // (*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]), @@ -7704,10 +7797,9 @@ func deferstruct(stksize int64) *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("args", argtype), + makefield("varp", types.Types[types.TUINTPTR]), + makefield("framepc", types.Types[types.TUINTPTR]), } // build struct holding the above fields diff --git a/src/cmd/compile/internal/staticdata/data.go b/src/cmd/compile/internal/staticdata/data.go index abb0bba646e0caacf183e436cc084784b5907250..57c15a34a0cd4c82bc1add58b3eb61dfeea8a6a9 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. @@ -275,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) { diff --git a/src/cmd/compile/internal/staticdata/embed.go b/src/cmd/compile/internal/staticdata/embed.go index 8936c4f5b44e44c7f03edf81a137e49eb68ac564..627c98ba447f004b1c78394a291cab1f40467103 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 @@ -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 diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go index 0c97b6de747660541c604beb3c7f4046f8dae10a..636199de47642a3bae215ae0897769a205fd545c 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++ } @@ -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: @@ -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/syntax/dumper_test.go b/src/cmd/compile/internal/syntax/dumper_test.go index 22680dce786c52214dce93b05b579cecc8f89b51..033283a3528784ce6dde2cfc13ebf7a57b08d9e5 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/error_test.go b/src/cmd/compile/internal/syntax/error_test.go index e4bedf54fdc04fec00253a41a00640c5fdafc7c8..d87e8eaee3213e8b31f6f19c1d8e61a4a306e1ab 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/nodes.go b/src/cmd/compile/internal/syntax/nodes.go index fb9786daa325c580d5402603e9241ae67ab36ddc..2f9b43edef98ad42edd4ad01e676fff5d83c26e0 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 e7b8840b337e679bb11e32ef844c1bf32764412a..770175fe54f8d2b5aee7071e924d37cea019a2df 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 { @@ -146,11 +148,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 { @@ -274,7 +278,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: @@ -580,35 +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 + if p.allowGenerics() && p.tok == _Lbrack { + // d.Name "[" ... + // array/slice or type parameter list pos := p.pos() p.next() switch p.tok { - case _Rbrack: - p.next() - d.Type = p.sliceType(pos) case _Name: - // array or generic type - p.xnest++ - x := p.expr() - p.xnest-- - if name0, ok := x.(*Name); p.mode&AllowGenerics != 0 && ok && p.tok != _Rbrack { - // generic type - 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 - if debug && x == nil { - panic("internal error: nil expression") - } d.Type = p.arrayType(pos, x) } + case _Rbrack: + // d.Name "[" "]" ... + p.next() + d.Type = p.sliceType(pos) default: + // d.Name "[" ... d.Type = p.arrayType(pos, nil) } } else { @@ -683,15 +708,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl { } f.Name = p.name() - if p.mode&AllowGenerics != 0 && 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() } @@ -723,14 +740,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() @@ -738,7 +757,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 @@ -833,7 +852,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'. @@ -847,7 +866,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 @@ -917,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++ @@ -963,12 +982,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 { @@ -1049,7 +1070,16 @@ loop: } // x[i:... - p.want(_Colon) + // For better error message, don't simply use p.want(_Colon) here (issue #47704). + if !p.got(_Colon) { + 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) t.pos = pos @@ -1100,7 +1130,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 +1157,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 { @@ -1231,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 @@ -1304,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. @@ -1397,7 +1459,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) @@ -1415,39 +1477,27 @@ 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 { - type_ := NewName(p.pos(), "type") // cannot have a method named "type" - p.next() - if p.tok != _Semi && p.tok != _Rbrace { + default: + if p.allowGenerics() { + pos := p.pos() + if t := p.typeOrNil(); t != nil { 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") + f.pos = pos + f.Type = t + typ.MethodList = append(typ.MethodList, p.embeddedElem(f)) + return false } - return false } } - 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.allowGenerics() { + p.syntaxError("expecting method or embedded element") + p.advance(_Semi, _Rbrace) return false } @@ -1525,7 +1575,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, ...] @@ -1656,14 +1706,16 @@ 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.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). @@ -1680,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 @@ -1697,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 } @@ -1708,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. @@ -1796,39 +1848,70 @@ 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")() + defer p.trace("paramDeclOrNil")() + } + + // type set notation is ok in type parameter lists + typeSetsOk := follow == _Rbrack + + pos := p.pos() + if name != nil { + pos = name.pos + } else if typeSetsOk && p.tok == _Operator && p.op == Tilde { + // "~" ... + return p.embeddedElem(nil) } f := new(Field) - f.pos = p.pos() + 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 } + if typeSetsOk && p.tok == _Operator && p.op == Or { + // name "[" ... "]" "|" ... + // name "[" n "]" E "|" ... + f = p.embeddedElem(f) + } 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() @@ -1841,13 +1924,23 @@ func (p *parser) paramDeclOrNil(name *Name) *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 } - p.syntaxError("expecting )") - p.advance(_Comma, _Rparen) + p.syntaxError("expecting " + tokstring(follow)) + p.advance(_Comma, follow) return nil } @@ -1861,9 +1954,10 @@ 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 { - par := p.paramDeclOrNil(name) + 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, close) name = nil // 1st name was consumed if present if par != nil { if debug && par.Name == nil && par.Type == nil { @@ -1872,6 +1966,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 @@ -1882,7 +1979,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 { @@ -1890,18 +1987,16 @@ 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) - 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() + pos = StartPos(typ) par.Name = NewName(pos, "_") } } else if typ != nil { @@ -1917,7 +2012,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" } @@ -2157,7 +2257,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). @@ -2598,7 +2698,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 340ca6bb6f637b05d5756a44f09a371eec69819f..68f3c376c929216693493d99894f0273c8f86e67 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 diff --git a/src/cmd/compile/internal/syntax/pos.go b/src/cmd/compile/internal/syntax/pos.go index baebcc995c759bbcb4719600e658b0a4920f881a..1494c0989fb11a1258649f6f0e45c39f7e147747 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 diff --git a/src/cmd/compile/internal/syntax/positions.go b/src/cmd/compile/internal/syntax/positions.go index b00f86c67cdab32322449056a2caf9c7e7aa7a50..93596559a02328a3a23296c15ffa2983630a20a1 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/printer.go b/src/cmd/compile/internal/syntax/printer.go index e557f5d9247b521a67984f5b60d8963174b45a1d..c8d31799afcb4e479f31e6a07b004b8de028d5ae 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 ec4b1de573f6bec08883996037bccf320cb210ad..604f1fc1ca71a296ed449126a4e685a47145aeb4 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) @@ -64,18 +60,22 @@ 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]) _()", "package p; func (*R[A, B, C]) _()", "package p; func (_ *R[A, B, C]) _()", + // type constraint literals with elided interfaces + "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)", @@ -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 diff --git a/src/cmd/compile/internal/syntax/testdata/go2/linalg.go2 b/src/cmd/compile/internal/syntax/testdata/go2/linalg.go2 index 0d27603a5837a2747922d9c1e52802b840ca8c4e..822d0287e7490ada0681ce74a10de3ab0122c765 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 e5cfba061254165a62c45bc04a2ea055033785d1..42efb4252755c2400bf9b334f2b048b70fa3017f 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 6e2104a5150da8fead95d91dc7cdad447fc59f8d..76b8d5591fbf99cfa49264e51f13c67e6d154046 100644 --- a/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 +++ b/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 @@ -148,56 +148,32 @@ 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{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 } -// 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 { - 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 +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/go2/typeparams.go2 b/src/cmd/compile/internal/syntax/testdata/go2/typeparams.go2 index f78037f0f5d033c63236e8246644b2b401509713..111f7c10042389ce70c659529f95cc279b06edf3 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) { } diff --git a/src/cmd/compile/internal/syntax/testdata/interface.go2 b/src/cmd/compile/internal/syntax/testdata/interface.go2 index a817327a43f4c289e55b541880974981c1b54278..dbc41879896920495d064f92cb1c16cc0c8d71fb 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 } @@ -25,12 +20,55 @@ type _ interface { ~int | ~string } - type _ interface { m() ~int T[int, string] | string int | ~T[string, struct{}] ~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 } 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 0000000000000000000000000000000000000000..dd2c9b1272f79d28c21bcf3b38eb72a8940937af --- /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/issue46558.src b/src/cmd/compile/internal/syntax/testdata/issue46558.src new file mode 100644 index 0000000000000000000000000000000000000000..a22b6008258464503dd41b037a3094dccec10ebb --- /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 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 0000000000000000000000000000000000000000..4e65857f3b191c8f94523f39ed8bc999d421258d --- /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 \] + ] +} 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 0000000000000000000000000000000000000000..0156af7d8d1b040963c3a707a17f44a636c77f01 --- /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 \] + ] +} 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 0000000000000000000000000000000000000000..1e8f4b0ec646d4b7ad1ca77d09ed360190089232 --- /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]() +} diff --git a/src/cmd/compile/internal/syntax/testdata/tparams.go2 b/src/cmd/compile/internal/syntax/testdata/tparams.go2 index 42031c32774f9419625b21b3ea14d005a2cf5449..80e155bfe05213df73abaa04ffea861e377cfd49 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,7 @@ 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 */ ]() + +func f[a b, /* ERROR expecting ] */ 0] () 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 0000000000000000000000000000000000000000..19b74f28eacdb8e24ceea65735167ec1c5bd5369 --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/typeset.go2 @@ -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. + +// This file contains test cases for typeset-only constraint elements. + +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 + + // 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 +// 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 +) diff --git a/src/cmd/compile/internal/syntax/walk.go b/src/cmd/compile/internal/syntax/walk.go index c26e97a0d8f88771986be07a4a300ff98b993f4e..b02584420488442a3e284d5b611fa025001bd59e 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") + panic("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/test/abiutils_test.go b/src/cmd/compile/internal/test/abiutils_test.go index b752c486126dc37acfb08bef3ee8205f5ab032e2..12b4a0c361360564e9d7bab8a45bbe6045577828 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() @@ -245,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}, @@ -309,9 +311,9 @@ 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, nil, fldt) - nei := types.NewInterface(types.LocalPkg, []*types.Field{field}) + []*types.Type{types.Types[types.TSTRING]}) + field := types.NewField(src.NoXPos, typecheck.Lookup("F"), fldt) + 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}) @@ -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 { () 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 { () 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 { () 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 `) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index 6f100033cf5b8b9666c458ce82b894db12d2a914..b10d37a17cfd0d242775b60ece9eaed8b30bfbb0 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -42,13 +42,11 @@ func TestIntendedInlining(t *testing.T) { "bucketMask", "bucketShift", "chanbuf", - "deferArgs", - "deferclass", "evacuated", "fastlog2", "fastrand", "float64bits", - "funcPC", + "funcspdelta", "getArgInfoFast", "getm", "getMCache", @@ -65,10 +63,10 @@ func TestIntendedInlining(t *testing.T) { "subtract1", "subtractb", "tophash", - "totaldefersize", "(*bmap).keys", "(*bmap).overflow", "(*waitq).enqueue", + "funcInfo.entry", // GC-related ones "cgoInRange", @@ -126,9 +124,14 @@ func TestIntendedInlining(t *testing.T) { "FullRune", "FullRuneInString", "RuneLen", + "AppendRune", "ValidRune", }, "reflect": { + "Value.CanInt", + "Value.CanUint", + "Value.CanFloat", + "Value.CanComplex", "Value.CanAddr", "Value.CanSet", "Value.CanInterface", 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 0000000000000000000000000000000000000000..951f6a05aa57df1a3daf55700f48eb760d47aa4f --- /dev/null +++ b/src/cmd/compile/internal/test/inst_test.go @@ -0,0 +1,73 @@ +// Copyright 2021 The Go Authors. 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) + } + // 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)) + } + + // 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/ssa_test.go b/src/cmd/compile/internal/test/ssa_test.go index 2f3e24c2d37ca0b6c9b6226e6611de369ff39cc9..af7d9626f95f9efb596614bf2c6061d5a502eed3 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/cmd/compile/internal/test/testdata/mysort/mysort.go b/src/cmd/compile/internal/test/testdata/mysort/mysort.go new file mode 100644 index 0000000000000000000000000000000000000000..14852c868a79452d153f3dc6eff834d5d9a58841 --- /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 0000000000000000000000000000000000000000..6cc7ba4851bba39fef93918ed78aa76d2fb17397 --- /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 0000000000000000000000000000000000000000..41f1621d1a29b5977888b8b7d2572f23117a059b --- /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/src/cmd/compile/internal/typebits/typebits.go b/src/cmd/compile/internal/typebits/typebits.go index 1c1b077423dc973c20767f0b6d96280e07899e88..fddad6e7e84b8176fd3d2865433d53d0b95236b2 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/bexport.go b/src/cmd/compile/internal/typecheck/bexport.go index 4a84bb13fa48ebfc63eb1dd36a5b7206af21a5c5..352f7a96ad3eac4ec468bfb6d4baf4e276a2920b 100644 --- a/src/cmd/compile/internal/typecheck/bexport.go +++ b/src/cmd/compile/internal/typecheck/bexport.go @@ -96,6 +96,12 @@ func predeclared() []*types.Type { // any type, for builtin export data types.Types[types.TANY], + + // comparable + types.ComparableType, + + // any + types.AnyType, } } return predecl diff --git a/src/cmd/compile/internal/typecheck/builtin.go b/src/cmd/compile/internal/typecheck/builtin.go index 833b17b4148ed5ab022e0b859084573227151ed3..67597cebb463025cc3db34e74b052eec973b83ca 100644 --- a/src/cmd/compile/internal/typecheck/builtin.go +++ b/src/cmd/compile/internal/typecheck/builtin.go @@ -71,137 +71,139 @@ 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}, + {"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, 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, 140}, + {"racewriterange", funcTag, 140}, + {"msanread", funcTag, 140}, + {"msanwrite", funcTag, 140}, + {"msanmove", funcTag, 141}, + {"asanread", funcTag, 140}, + {"asanwrite", funcTag, 140}, + {"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}, @@ -224,7 +226,7 @@ func params(tlist ...*types.Type) []*types.Field { } func runtimeTypes() []*types.Type { - var typs [145]*types.Type + var typs [149]*types.Type typs[0] = types.ByteType typs[1] = types.NewPtr(typs[0]) typs[2] = types.Types[types.TANY] @@ -282,93 +284,97 @@ 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[143] = newSig(params(typs[60], typs[60]), nil) - typs[144] = newSig(params(typs[24], typs[24]), 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] = 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 2b29ea3c08ca72be0b35a2db22755490f76a4f11..04ae4f23a387790c11cc5d9e98360c55beff5019 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) @@ -230,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) @@ -251,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/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go index 761b043794062d7dbb4c985d99319b35ba24f3eb..fbe7c02c49821eb587ea97bf5e27b9f507e3bff6 100644 --- a/src/cmd/compile/internal/typecheck/const.go +++ b/src/cmd/compile/internal/typecheck/const.go @@ -874,14 +874,16 @@ 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. 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 } @@ -901,7 +903,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 new file mode 100644 index 0000000000000000000000000000000000000000..ae6542d071976ffc0a80457364c8f2138a4e203e --- /dev/null +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -0,0 +1,284 @@ +// Copyright 2021 The Go Authors. 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. 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), + embedded: make(map[*types.Type]bool), + generic: 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 + 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) +func (p *crawler) markObject(n *ir.Name) { + if n.Op() == ir.ONAME && n.Class == ir.PFUNC { + 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()) +} + +// 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.OrigSym() != nil { + // Convert to the base generic type. + t = t.OrigSym().Def.Type() + } + if p.marked[t] { + return + } + p.marked[t] = true + + // 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 + // 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: + if t.IsFuncArgStruct() { + break + } + for _, f := range t.FieldSlice() { + // 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) + } + } + + case types.TFUNC: + for _, f := range t.Results().FieldSlice() { + p.markType(f.Type) + } + + case types.TINTER: + 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. + } +} + +// 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.OrigSym() != nil { + // Convert to the base generic type. + t = t.OrigSym().Def.Type() + } + + 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) + } + } + } +} + +// 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) { + 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 !HaveInlineBody(fn) { + return + } + + if fn.ExportInline() { + return + } + fn.SetExportInline(true) + + ImportedBody(fn) + + var doFlood func(n ir.Node) + doFlood = func(n ir.Node) { + t := n.Type() + if t != nil { + if t.HasTParam() || t.IsFullyInstantiated() { + p.markGeneric(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. + if t.IsStruct() { + for _, f := range t.FieldSlice() { + if f.Embedded != 0 { + p.markEmbed(f.Type) + } + } + } + } + } + + 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.OMETHVALUE: + // 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) +} + +// 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/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go index 5b771e3c0b1d836cb915efcd776aba3820464d41..68ab05a538e8fd52e56686892025dab8e59663e1 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" @@ -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 { @@ -363,22 +356,18 @@ 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++ - } - if n.Sym.IsBlank() { + n.Sym = LookupNum("~r", i) + } 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) // 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) @@ -431,6 +420,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 @@ -443,20 +433,50 @@ 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. + 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 } // 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/src/cmd/compile/internal/typecheck/export.go b/src/cmd/compile/internal/typecheck/export.go index 63d0a1ec6c656ce23e504458eacb456e01d12783..30726d4327f7ce8edf3d0879d73d939f094d90b0 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/expr.go b/src/cmd/compile/internal/typecheck/expr.go index 24d141e8a2ce9149573b481b42541d353a2be704..9b74bf7a9d3762ce60c7fbc414fc9e2770885fcd 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. @@ -114,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) } @@ -133,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) } @@ -311,14 +307,23 @@ 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") - 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) @@ -328,77 +333,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 } } @@ -409,6 +370,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 @@ -522,8 +537,8 @@ 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.SetType(MethodValueWrapper(n).Type()) + n.SetOp(ir.OMETHVALUE) + n.SetType(NewMethodType(n.Type(), nil)) } return n } diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index fbcc784627d6ce8d64bb17eab49b7a679af10ab5..57b15b7a2bc78e615b42e673d842840ff1863941 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -8,28 +8,29 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/types" + "cmd/internal/src" "fmt" "go/constant" "go/token" ) -// package all the arguments that match a ... T parameter into a []T. -func MakeDotArgs(typ *types.Type, args []ir.Node) ir.Node { +// 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 { - 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 } @@ -56,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. @@ -73,8 +93,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() @@ -88,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 OCALLPART 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()), @@ -123,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 @@ -181,153 +223,38 @@ 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 -// 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.OCALLPART { - 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 // 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 { fn.Iota = x } - 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) @@ -353,14 +280,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 @@ -390,10 +320,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() { @@ -509,6 +435,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 } @@ -979,6 +906,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/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 64d68ef62550d8a4b5c2d3046336e48c46c8352c..7ebabe7314536694e9f13e7cc974c5d6eba4f0af 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,13 @@ // Type typeOff // } // +// // "Automatic" declaration of each typeparam +// type TypeParam struct { +// Tag byte // 'P' +// Pos Pos +// Implicit bool +// Constraint typeOff +// } // // typeOff means a uvarint that either indicates a predeclared type, // or an offset into the Data section. If the uvarint is less than @@ -100,11 +109,11 @@ // 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. // // -// 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,6 +181,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 +// } +// } +// +// // // type Signature struct { // Params []Param @@ -202,7 +235,6 @@ package typecheck import ( - "bufio" "bytes" "crypto/md5" "encoding/binary" @@ -221,9 +253,19 @@ 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. 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 + iexportVersionGenerics = 2 + iexportVersionGo1_18 = 2 + + iexportVersionCurrent = 2 +) // predeclReserved is the number of type offsets reserved for types // implicitly declared in the universe block. @@ -244,6 +286,9 @@ const ( signatureType structType interfaceType + typeParamType + instanceType // Instantiation of a generic type + unionType ) const ( @@ -251,13 +296,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() { @@ -293,7 +347,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) @@ -379,6 +433,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. @@ -406,7 +462,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 } @@ -449,7 +505,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) { @@ -457,10 +515,25 @@ 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 + // 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. + if n.Type().TParams().NumFields() > 0 { + 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) @@ -476,10 +549,29 @@ 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 types.IsDotAlias(n.Sym()) { + 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 + // definition. + w.tag('P') + // 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 + } + + if n.Alias() { // Alias. w.tag('A') w.pos(n.Pos()) @@ -488,9 +580,18 @@ 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 len(n.Type().RParams()) > 0 { + // 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 @@ -501,26 +602,43 @@ 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() if t.IsInterface() { - w.typeExt(t) + if w.p.extensions { + w.typeExt(t) + } 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()...) + if base.Debug.UnifiedQuirks != 0 { + 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()) w.signature(m.Type) } - w.typeExt(t) - for _, m := range ms.Slice() { - w.methExt(m) + if w.p.extensions { + w.typeExt(t) + for _, m := range methods { + w.methExt(m) + } } default: @@ -803,8 +921,46 @@ 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 { + 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 { + base.Fatalf("incorrect name for instantiated type") + } + 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 + // *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 + } + + // 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.IsTypeParam() && t.Underlying() == t { + assert(base.Flag.G > 0) + 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. + // 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 == types.UnsafePkg { base.Fatalf("builtin type missing from typIndex: %v", t) } @@ -865,6 +1021,14 @@ 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. + if base.Debug.UnifiedQuirks != 0 { + sort.Sort(types.MethodsByName(methods)) + sort.Stable(types.EmbeddedsByName(embeddeds)) + } + w.startType(interfaceType) w.setPkg(t.Pkg(), true) @@ -881,6 +1045,19 @@ func (w *exportWriter) doTyp(t *types.Type) { w.signature(f.Type) } + case types.TUNION: + assert(base.Flag.G > 0) + // 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++ { + typ, tilde := t.Term(i) + w.bool(tilde) + w.typ(typ) + } + default: base.Fatalf("unexpected type: %v", t) } @@ -906,6 +1083,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.IsTypeParam() { + 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 { @@ -948,26 +1142,57 @@ func constTypeOf(typ *types.Type) constant.Kind { } func (w *exportWriter) value(typ *types.Type, v constant.Value) { - ir.AssertValidTypeForConst(typ, v) w.typ(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. + if iexportVersionCurrent >= iexportVersionGo1_18 { + w.int64(int64(v.Kind())) + } + + var kind constant.Kind + var valType *types.Type - switch constTypeOf(typ) { + if typ.IsTypeParam() { + kind = v.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: + 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.Kind() here. However, switching on the type + // (in the non-typeparam case) increases symmetry with import logic and + // provides a useful consistency check. + + 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) } } @@ -1185,10 +1410,20 @@ func (w *exportWriter) funcExt(n *ir.Name) { } } - // Inline 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)) - if n.Func.ExportInline() { + 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) } @@ -1270,10 +1505,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) && 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) @@ -1309,8 +1557,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: @@ -1331,8 +1581,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) @@ -1370,6 +1622,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) @@ -1432,7 +1685,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) } } @@ -1460,7 +1718,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) @@ -1469,7 +1729,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: @@ -1477,6 +1741,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()) @@ -1488,15 +1754,51 @@ 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.bool(n.Sym().Pkg == types.UnsafePkg) + w.string(n.Sym().Name) + break + } w.localName(n) - // case OPACK, ONONAME: + case ir.ONONAME: + w.op(ir.ONONAME) + // 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) + if go117ExportTypes { + w.typ(n.Type()) + } + + // case OPACK: // should have been resolved by typechecking - handled by default case case ir.OTYPE: 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) @@ -1562,7 +1864,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()) @@ -1585,12 +1887,11 @@ 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 { - 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) @@ -1600,11 +1901,16 @@ 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 OCALLPART. It will - // be reconstructed during import. + // n.Selection is not required for OMETHEXPR, ODOTMETH, and OMETHVALUE. It will + // be reconstructed during import. n.Selection is computed during + // transformDot() for OXDOT. } case ir.ODOTTYPE, ir.ODOTTYPE2: @@ -1618,6 +1924,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 { @@ -1629,7 +1943,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) } @@ -1677,7 +1991,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()) @@ -1732,7 +2046,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: @@ -1759,8 +2072,16 @@ 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: + 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()) @@ -1796,7 +2117,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()) @@ -1829,6 +2150,28 @@ 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.stmtList(n.Init()) + w.exprList(n.Lhs) + w.exprList(n.Rhs) + w.bool(n.Def) + default: base.Fatalf("cannot export %v (%d) node\n"+ "\t==> please file an issue and assign to gri@", n.Op(), int(n.Op())) @@ -1864,11 +2207,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)) - } } } @@ -1902,8 +2242,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_") { + // 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, LocalDictName) { base.Fatalf("unexpected dot in identifier: %v", name) } @@ -1939,3 +2286,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/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 37f5a7bba0ac9a351c2373c969e8dce025b57185..09f87df5803eec2bfac3b2c1c00b1947a6ff3d59 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -11,7 +11,6 @@ import ( "encoding/binary" "fmt" "go/constant" - "io" "math/big" "os" "strings" @@ -19,8 +18,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" ) @@ -84,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 { @@ -94,7 +112,7 @@ func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset } type intReader struct { - *bio.Reader + *strings.Reader pkg *types.Pkg } @@ -116,33 +134,30 @@ 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() - if version != iexportVersion { + switch version { + case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: + default: base.Errorf("import %q: unknown export format version %d", pkg.Path, version) base.ErrorExit() } - sLen := ird.uint64() - dLen := 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:] + sLen := int64(ird.uint64()) + dLen := int64(ird.uint64()) - 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{ - ipkg: pkg, + exportVersion: version, + ipkg: pkg, pkgCache: map[uint64]*types.Pkg{}, posBaseCache: map[uint64]*src.PosBase{}, @@ -178,7 +193,7 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT } 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 { @@ -192,7 +207,7 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT pkg := p.pkgAt(ird.uint64()) 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 := inlineImporter[s]; !ok { @@ -200,18 +215,11 @@ 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 { - ipkg *types.Pkg + exportVersion uint64 + ipkg *types.Pkg pkgCache map[uint64]*types.Pkg posBaseCache map[uint64]*src.PosBase @@ -233,6 +241,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 @@ -273,6 +297,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 { @@ -287,6 +312,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()) } @@ -302,37 +328,49 @@ 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 - case 'F': - typ := r.signature(nil) + case 'F', 'G': + var tparams []*types.Field + if tag == 'G' { + tparams = r.tparamList() + } + typ := r.signature(nil, tparams) - n := importfunc(r.p.ipkg, pos, sym, typ) + n := importfunc(pos, sym, typ) r.funcExt(n) return n - case 'T': + case 'T', 'U': // 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 tag == 'U' { + rparams := r.typeList() + 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 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 } @@ -342,7 +380,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)) @@ -358,16 +396,50 @@ 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) + } + // 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 + nname.SetType(t) + t.SetNod(nname) + 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': typ := r.typ() - n := importvar(r.p.ipkg, pos, sym, typ) + n := importvar(pos, sym, typ) r.varExt(n) return n @@ -377,27 +449,54 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { } } -func (p *importReader) value(typ *types.Type) constant.Value { - switch constTypeOf(typ) { +func (r *importReader) value(typ *types.Type) constant.Value { + var kind constant.Kind + var valType *types.Type + + 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] + 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()) + 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, typ) + r.mpint(&i, valType) return constant.Make(&i) case constant.Float: - return p.float(typ) + return r.float(valType) case constant.Complex: - return makeComplex(p.float(typ), p.float(typ)) + 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 @@ -408,7 +507,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 { @@ -429,30 +528,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) } @@ -462,8 +561,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) } @@ -472,7 +578,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) @@ -503,7 +609,14 @@ 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. + types.DeferCheckSize() + deferDoInst() + t := r.p.typAt(r.uint64()) + resumeDoInst() + types.ResumeCheckSize() + return t } func (r *importReader) exoticType() *types.Type { @@ -538,7 +651,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() } @@ -641,7 +754,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 @@ -680,7 +799,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,16 +837,64 @@ func (r *importReader) typ1() *types.Type { for i := range methods { pos := r.pos() sym := r.selector() - typ := r.signature(fakeRecvField()) + typ := r.signature(types.FakeRecv(), nil) methods[i] = types.NewField(pos, sym, typ) } - t := types.NewInterface(r.currPkg, append(embeddeds, methods...)) + if len(embeddeds)+len(methods) == 0 { + return types.Types[types.TINTER] + } + + t := types.NewInterface(r.currPkg, append(embeddeds, methods...), false) // Ensure we expand the interface in the frontend (#25055). types.CheckSize(t) return t + + case typeParamType: + if r.p.exportVersion < iexportVersionGenerics { + base.Fatalf("unexpected type param 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() + } + 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 instanceType: + if r.p.exportVersion < iexportVersionGenerics { + base.Fatalf("unexpected instantiation type") + } + 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 + + 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 { + tildes[i] = r.bool() + terms[i] = r.typ() + } + return types.NewUnion(terms, tildes) } } @@ -735,13 +902,42 @@ 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() + if ts[i].IsTypeParam() { + ts[i].SetIndex(i) + } + } + 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() + typ.SetIndex(i) + fs[i] = types.NewField(typ.Pos(), typ.Sym(), typ) + } + return fs } func (r *importReader) paramList() []*types.Field { @@ -809,7 +1005,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 { @@ -821,7 +1019,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() } @@ -852,7 +1051,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} } @@ -860,6 +1065,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 { @@ -936,6 +1142,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 { @@ -1004,10 +1214,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 } @@ -1032,7 +1258,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 } @@ -1083,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) @@ -1095,6 +1333,14 @@ func (r *importReader) node() ir.Node { return n case ir.ONAME: + isBuiltin := r.bool() + if isBuiltin { + pkg := types.BuiltinPkg + if r.bool() { + pkg = types.UnsafePkg + } + return pkg.Lookup(r.string()).Def.(*ir.Name) + } return r.localName() // case OPACK, ONONAME: @@ -1103,6 +1349,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 @@ -1117,28 +1371,18 @@ 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 - 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, true) fn.Nname.SetType(typ) 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 @@ -1159,12 +1403,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) } - return clo case ir.OSTRUCTLIT: @@ -1179,7 +1421,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 { @@ -1202,35 +1448,56 @@ 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.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. + 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.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.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 { + // Lookdot clobbers the opcode and type, undo that. + n.SetOp(op) + n.SetType(typ) + } } } return n @@ -1243,11 +1510,16 @@ 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 { n.SetOp(op) - n.SetType(r.typ()) + n.SetType(r.exoticType()) if op == ir.OINDEXMAP { n.Assigned = r.bool() } @@ -1267,7 +1539,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 @@ -1314,11 +1586,10 @@ 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()) - n.Use = ir.CallUse(r.uint64()) } return n @@ -1343,8 +1614,15 @@ 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: + 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()) @@ -1368,7 +1646,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()) @@ -1412,7 +1690,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) @@ -1429,7 +1712,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()) @@ -1443,26 +1731,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: @@ -1470,7 +1760,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: @@ -1496,6 +1786,31 @@ 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: + 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"+ "\t==> please file an issue and assign to gri@", op, int(op)) @@ -1517,11 +1832,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 } @@ -1544,3 +1855,147 @@ 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) } + +// NewIncompleteNamedType returns a TFORW type t with name specified by sym, such +// 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) + 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 { + // May match existing type from previous import or + // 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) + t.SetRParams(targs) + 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 + // 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 { + assert(t.Kind() == types.TFORW) + 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) { + assert(t.Kind() == types.TFORW) + 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() { + 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). + msubst := Tsubster{ + Tparams: recvType.RParams(), + Targs: targs, + SubstForwFunc: doInst, + } + t2 := msubst.Typ(f.Type) + oldsym := f.Nname.Sym() + newsym := MakeFuncInstSym(oldsym, targs, true, true) + var nname *ir.Name + if newsym.Def != nil { + nname = newsym.Def.(*ir.Name) + } 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) + newfields[i].Nname = nname + } + t.Methods().Set(newfields) + 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) + } +} diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index 922a01bfbe9aa7d6dea6ab34e03e5955ef883105..9a02c1752caf13f6c89e26866e01ba553a767e62 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 } @@ -201,7 +205,6 @@ assignOK: stmt := stmt.(*ir.AssignListStmt) stmt.SetOp(ir.OAS2FUNC) r := rhs[0].(*ir.CallExpr) - r.Use = ir.CallUseList rtyp := r.Type() mismatched := false @@ -217,7 +220,7 @@ assignOK: } } if mismatched && !failed { - rewriteMultiValueCall(stmt, r) + RewriteMultiValueCall(stmt, r) } return } @@ -237,6 +240,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()) @@ -383,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: @@ -653,29 +666,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.LongString() - 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/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 9ee7a94b1f24af5bea061042a8d471c8c4758b69..5b5b04371517516c8af7e3a5d79f39cfa4b9b38d 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" @@ -13,6 +14,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/types" + "cmd/internal/objabi" "cmd/internal/src" ) @@ -158,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 @@ -351,10 +353,14 @@ func Assignop(src, dst *types.Type) (ir.Op, string) { if types.Identical(src, dst) { return ir.OCONVNOP, "" } + return Assignop1(src, dst) +} - // 2. src and dst have identical underlying types - // and either src or dst is not a named type or - // both are empty interface types. +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 + // 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 @@ -371,21 +377,24 @@ 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) { - // 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, "" } @@ -722,13 +731,30 @@ 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() { + // 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() for _, im := range iface.AllMethods().Slice() { @@ -874,3 +900,563 @@ 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 +} + +// 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(',') + } + // 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("]") +} + +// 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. +func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string { + b := bytes.NewBufferString("") + i := strings.Index(name, "[") + assert(hasBrackets == (i >= 0)) + if i >= 0 { + b.WriteString(name[0:i]) + } else { + b.WriteString(name) + } + addTargs(b, targs) + if i >= 0 { + i2 := strings.LastIndex(name[i:], "]") + assert(i2 >= 0) + b.WriteString(name[i+i2+1:]) + } + return b.String() +} + +// MakeFuncInstSym makes the unique sym for a stenciled generic function or method, +// 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 +// 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 +// +// 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 { + 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 := makeInstName1(gf.Name, targs, hasBrackets) + name = fmt.Sprintf("%s.%s", objabi.GlobalDictPrefix, name) + return gf.Pkg.Lookup(name) +} + +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-instantiated type to instTypeList. +func NeedInstType(t *types.Type) { + instTypeList = append(instTypeList, t) +} + +// GetInstTypeList returns the current contents of instTypeList. +func GetInstTypeList() []*types.Type { + r := instTypeList + 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 + 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 + // 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 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. + types.DeferCheckSize() + r := ts.typ1(t) + types.ResumeCheckSize() + return r +} + +func (ts *Tsubster) typ1(t *types.Type) *types.Type { + 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() || t.IsShape() { + 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 targsChanged bool + var forw *types.Type + + 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.IdenticalStrict(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 + // 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.SetOrigSym(t.OrigSym()) + } + + var newt *types.Type + + switch t.Kind() { + case types.TTYPEPARAM: + if t.Sym() == newsym && !targsChanged { + // 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.typ1(t.Underlying()) + assert(newt != t) + + case types.TARRAY: + elem := t.Elem() + newelem := ts.typ1(elem) + if newelem != elem || targsChanged { + newt = types.NewArray(newelem, t.NumElem()) + } + + case types.TPTR: + elem := t.Elem() + newelem := ts.typ1(elem) + if newelem != elem || targsChanged { + newt = types.NewPtr(newelem) + } + + case types.TSLICE: + elem := t.Elem() + newelem := ts.typ1(elem) + if newelem != elem || targsChanged { + newt = types.NewSlice(newelem) + } + + case types.TSTRUCT: + newt = ts.tstruct(t, targsChanged) + 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) + // 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 + // 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) + } + 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: + newt = ts.tinter(t, targsChanged) + if newt == t { + newt = nil + } + + case types.TMAP: + 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.typ1(elem) + if newelem != elem || targsChanged { + newt = types.NewChan(newelem, t.ChanDir()) + } + case types.TFORW: + if ts.SubstForwFunc != nil { + return ts.SubstForwFunc(forw) + } 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, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, types.TUNSAFEPTR: + 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.typ1(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 + // 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 forw != nil { + forw.SetUnderlying(newt) + newt = forw + } + + 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()). + 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.typ1(f.Type) + oldsym := f.Nname.Sym() + newsym := MakeFuncInstSym(oldsym, ts.Targs, true, true) + var nname *ir.Name + if newsym.Def != nil { + nname = newsym.Def.(*ir.Name) + } 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) + newfields[i].Nname = nname + } + newt.Methods().Set(newfields) + if !newt.HasTParam() && !newt.HasShape() { + // Generate all the methods for a new fully-instantiated type. + + NeedInstType(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() || t.HasShape() { + // 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.typ1(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 { + 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) + } + if f.Nointerface() { + newfields[i].SetNointerface(true) + } + 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 { + news := types.NewStruct(t.Pkg(), newfields) + news.StructType().Funarg = t.StructType().Funarg + return news + } + return t + +} + +// tinter substitutes type params in types of the methods of an interface 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, false) + } + 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 { + 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, t.IsImplicit()) + } + 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, "[")] +} + +// 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. +// +// 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() + + // All pointers have the same shape. + // TODO: Make unsafe.Pointer the same shape as normal pointers. + // 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() + } + + 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 + } + + // 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 { + // Use any existing type with the same name + submap[u] = sym.Def.Type() + return submap[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) + name.SetType(s) + name.SetTypecheck(1) + submap[u] = s + return s +} + +var shapeMap map[int]map[*types.Type]*types.Type diff --git a/src/cmd/compile/internal/typecheck/syms.go b/src/cmd/compile/internal/typecheck/syms.go index f29af82db2cc25670a60ef4192fd5623a4ee4806..ed3aaecc5a2a2a777cd748d22eca98f4b65f2ce1 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) } diff --git a/src/cmd/compile/internal/typecheck/type.go b/src/cmd/compile/internal/typecheck/type.go index af694c2d94a30fb4a5bf1a74e3afd1a48fddfaa8..c4c1ef58cadb103a91c1a0e79d3c1aa6acd4cbda 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/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 359f66236969fb4e34867ba35ea9d56b9480f5ba..42970f6a5e279fa4a133c2d56d946d7d3dbfe9b2 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, @@ -24,7 +25,6 @@ var inimport bool // set during import var TypecheckAllowed bool var ( - NeedITab = func(t, itype *types.Type) {} NeedRuntimeType = func(*types.Type) {} ) @@ -35,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 { @@ -59,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 } } @@ -777,6 +769,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) @@ -787,11 +783,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) @@ -814,6 +806,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) @@ -879,8 +879,13 @@ 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: + n := n.(*ir.UnaryExpr) + return tcCheckNil(n) + case ir.OSELECT: tcSelect(n.(*ir.SelectStmt)) return n @@ -951,12 +956,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 @@ -1732,11 +1737,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) @@ -1744,8 +1744,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 { @@ -1913,11 +1912,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/typecheck/universe.go b/src/cmd/compile/internal/typecheck/universe.go index de185ab94471d640c834341e2a38432ff43acc09..0254d96e6825e5adac1735e78df950694e0d62b7 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,77 +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) - - 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) @@ -174,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") @@ -190,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) @@ -198,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) @@ -210,19 +111,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 { @@ -320,22 +208,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 { - 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}) } // DeclareUniverse makes the universe block visible within the current package. diff --git a/src/cmd/compile/internal/types/alg.go b/src/cmd/compile/internal/types/alg.go index 2c2700f345730e2b0a99d472aedc5962953ca78a..f5675c66b4f4ec679e039fc3c26037fe652cad87 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/fmt.go b/src/cmd/compile/internal/types/fmt.go index 8b988952a78d2c689714ddfe2d61260fcdb75e19..3198a1f53c8674c6234d6d2fcaa1eb402718a36f 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 @@ -61,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 ( @@ -137,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 @@ -239,17 +248,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) } @@ -278,7 +307,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 { @@ -289,7 +318,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(',') @@ -299,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()] @@ -316,31 +345,34 @@ 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 + // 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-- } - - if t.Sym().Pkg == LocalPkg && t.Vargen != 0 { - sconv2(b, t.Sym(), 'v', mode) - fmt.Fprintf(b, "·%d", t.Vargen) - return + 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, t.Sym(), 'v', mode) + sconv2(b, sym, verb, mode) + + // 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) + } return } @@ -567,6 +599,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") @@ -671,7 +715,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/identity.go b/src/cmd/compile/internal/types/identity.go index dde9f5185687ad6869d0961f85928df97e8a133b..a164b84da929b3259396cc0b7410c405cc7c9406 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -4,16 +4,30 @@ package types -// Identical reports whether t1 and t2 are identical types, following -// the spec rules. Receiver parameter types are ignored. +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 { @@ -21,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 } @@ -29,6 +43,14 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b return false } if t1.sym != nil || t2.sym != nil { + 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 + } + // 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 { @@ -36,10 +58,18 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b 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: + // 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 } } +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 @@ -66,7 +96,7 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b } 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 } } @@ -78,10 +108,10 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b } 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 } } @@ -99,7 +129,7 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b } 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 } } @@ -117,10 +147,10 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b } 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) } diff --git a/src/cmd/compile/internal/types/kind_string.go b/src/cmd/compile/internal/types/kind_string.go index ae24a58b9219d483b710e69af65ce892bf7759e8..3e6a8bc064edf4cf0306d959eda9d07ca05346a5 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/pkg.go b/src/cmd/compile/internal/types/pkg.go index a6d2e2007b0424d4927ef5cda15fb67d94d27186..0b822a450c9893e669af8d7ed8de93fe99f1c021 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.") && !strings.Contains(path, "/") { + // 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 @@ -137,7 +144,3 @@ func CleanroomDo(f func()) { f() pkgMap = saved } - -func IsDotAlias(sym *Sym) bool { - return sym.Def != nil && sym.Def.Sym() != sym -} diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index f0e695ab964ac532dbeb3ad2bfdcae2e1e8479c2..fb6accdc642f74acf21f57ea663729db2b536428 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 @@ -104,8 +124,17 @@ func expandiface(t *Type) { continue } + if m.Type.IsUnion() { + continue + } + + // In 1.18, embedded types can be anything. In Go 1.17, we disallow + // embedding anything other than interfaces. if !m.Type.IsInterface() { - base.ErrorfAt(m.Pos, "interface contains embedded non-interface %v", m.Type) + 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) // Add to fields so that error messages @@ -120,10 +149,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)) @@ -155,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 @@ -197,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 } @@ -316,14 +350,14 @@ 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 } - if t.WidthCalculated() { + if t.widthCalculated() { return } @@ -338,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 } @@ -350,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 { @@ -383,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) @@ -402,24 +436,35 @@ 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) + case TCHAN: // implemented as pointer w = int64(PtrSize) 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 - if t1.Elem().Width >= 1<<16 { - base.ErrorfAt(typePos(t1), "channel element type too large (>64kB)") + // 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.Errorf("channel element type too large (>64kB)") } w = 1 // anything will do @@ -441,7 +486,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 { @@ -449,14 +494,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) + base.Errorf("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 { @@ -464,7 +509,7 @@ func CalcSize(t *Type) { } w = SliceSize CheckSize(t.Elem()) - t.Align = uint8(PtrSize) + t.align = uint8(PtrSize) case TSTRUCT: if t.IsFuncArgStruct() { @@ -486,11 +531,11 @@ 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) } - t.Align = 1 + t.align = 1 case TTYPEPARAM: // TODO(danscales) - remove when we eliminate the need @@ -499,15 +544,15 @@ 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 - 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 @@ -519,7 +564,19 @@ 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 + CalcSize(t) +} + +func (t *Type) widthCalculated() bool { + return t.align > 0 } // when a type's width should be known, we call CheckSize @@ -582,17 +639,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: @@ -606,24 +669,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/sizeof_test.go b/src/cmd/compile/internal/types/sizeof_test.go index 702893874214874080dfa1a148048303279050d9..d37c1730581c38be38a36d8e067d66deac34b94d 100644 --- a/src/cmd/compile/internal/types/sizeof_test.go +++ b/src/cmd/compile/internal/types/sizeof_test.go @@ -21,12 +21,12 @@ 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}, {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/sort.go b/src/cmd/compile/internal/types/sort.go index dc59b064153282cd0808a0fd3d2b4d51cd98680b..765c070cd94193c4c37db0f4415d1ee3ea06b031 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()) } diff --git a/src/cmd/compile/internal/types/sym.go b/src/cmd/compile/internal/types/sym.go index 534cf7e2376d726e9d3cb3568de4b4d7c5ea9125..fb642f52f881418302738b26d3665f8d2040441f 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/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 1a9aa6916a2faca5a12a999226cea51cef0c4234..7d22e2da234e6fd8b3d075ff956fe198888cb22e 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" ) @@ -26,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. @@ -73,6 +68,7 @@ const ( TSTRING TUNSAFEPTR TTYPEPARAM + TUNION // pseudo-types for literals TIDEAL // untyped numeric constants @@ -110,32 +106,38 @@ 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 // Predeclared error interface type. ErrorType *Type + // Predeclared comparable interface type. + 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. 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. // @@ -151,11 +153,11 @@ type Type struct { // TARRAY: *Array // TSLICE: Slice // TSSA: string - // TTYPEPARAM: *Interface (though we may not need to store/use the Interface info) - Extra interface{} + // 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 @@ -174,20 +176,27 @@ 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) + align uint8 // the required alignment of this type, in bytes (0 means Width and Align have not yet been computed) 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() {} @@ -199,6 +208,8 @@ 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 + typeHasShape // there is a shape somewhere in the type ) func (t *Type) NotInHeap() bool { return t.flags&typeNotInHeap != 0 } @@ -207,13 +218,21 @@ 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) 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) 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) } + +// 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 } @@ -222,6 +241,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 } @@ -255,9 +279,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). @@ -266,9 +287,33 @@ func (t *Type) SetRParams(rparams []*Type) { t.SetHasTParam(true) break } + if rparam.HasShape() { + t.SetHasShape(true) + break + } } } +// 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) IsFullyInstantiated() 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. @@ -283,11 +328,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 @@ -307,7 +352,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. @@ -319,7 +364,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. @@ -340,7 +385,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. @@ -369,12 +414,25 @@ 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. type Interface struct { - pkg *Pkg + pkg *Pkg + implicit bool +} + +// Typeparam contains Type fields specific to typeparam types. +type Typeparam struct { + index int // type parameter index in source order, starting at 0 + 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. @@ -401,7 +459,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 { @@ -467,7 +525,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. @@ -527,38 +585,40 @@ 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, + width: BADWIDTH, } t.underlying = t // 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(Interface) + t.extra = new(Typeparam) + case TUNION: + t.extra = new(Union) } return t } @@ -568,12 +628,15 @@ func NewArray(elem *Type, bound int64) *Type { if bound < 0 { base.Fatalf("NewArray: invalid bound %v", bound) } - t := New(TARRAY) - t.Extra = &Array{Elem: elem, Bound: bound} + t := newType(TARRAY) + t.extra = &Array{Elem: elem, Bound: bound} t.SetNotInHeap(elem.NotInHeap()) if elem.HasTParam() { t.SetHasTParam(true) } + if elem.HasShape() { + t.SetHasShape(true) + } return t } @@ -583,43 +646,55 @@ 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 } - t := New(TSLICE) - t.Extra = Slice{Elem: elem} + t := newType(TSLICE) + t.extra = Slice{Elem: elem} elem.cache.slice = t if elem.HasTParam() { t.SetHasTParam(true) } + if elem.HasShape() { + t.SetHasShape(true) + } return t } // 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 if elem.HasTParam() { t.SetHasTParam(true) } + if elem.HasShape() { + t.SetHasShape(true) + } return t } func NewTuple(t1, t2 *Type) *Type { - t := New(TTUPLE) - t.Extra.(*Tuple).first = t1 - t.Extra.(*Tuple).second = t2 + t := newType(TTUPLE) + t.extra.(*Tuple).first = t1 + t.extra.(*Tuple).second = t2 if t1.HasTParam() || t2.HasTParam() { t.SetHasTParam(true) } + if t1.HasShape() || t2.HasShape() { + t.SetHasShape(true) + } return t } func newResults(types []*Type) *Type { - t := New(TRESULTS) - t.Extra.(*Results).Types = types + t := newType(TRESULTS) + t.extra.(*Results).Types = types return t } @@ -631,20 +706,23 @@ func NewResults(types []*Type) *Type { } func newSSA(name string) *Type { - t := New(TSSA) - t.Extra = name + 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 if k.HasTParam() || v.HasTParam() { t.SetHasTParam(true) } + if k.HasShape() || v.HasShape() { + t.SetHasShape(true) + } return t } @@ -663,39 +741,39 @@ 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.HasTParam() != t.HasTParam() || elem.HasShape() != t.HasShape() { + base.Fatalf("Incorrect HasTParam/HasShape flag for cached pointer type") } return t } - t := New(TPTR) - t.Extra = Ptr{Elem: elem} - t.Width = int64(PtrSize) - t.Align = uint8(PtrSize) + t := newType(TPTR) + t.extra = Ptr{Elem: elem} + t.width = int64(PtrSize) + t.align = uint8(PtrSize) if NewPtrCacheEnabled { elem.cache.ptr = t } if elem.HasTParam() { t.SetHasTParam(true) } + if elem.HasShape() { + t.SetHasShape(true) + } return t } // NewChanArgs returns a new TCHANARGS type for channel type c. func NewChanArgs(c *Type) *Type { - t := New(TCHANARGS) - t.Extra = ChanArgs{T: c} + 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.Extra = FuncArgs{T: f} + t := newType(TFUNCARGS) + t.extra = FuncArgs{T: f} return t } @@ -734,28 +812,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: @@ -763,8 +841,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: @@ -805,26 +883,28 @@ 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: base.Fatalf("ssa types cannot be copied") } @@ -891,7 +971,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. @@ -899,15 +979,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 @@ -916,18 +996,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. +// 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. @@ -958,7 +1038,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. @@ -980,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) @@ -1004,15 +1084,11 @@ 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 { t.wantEtype(TFUNC) - return t.Extra.(*Func).Argwid + return t.extra.(*Func).Argwid } func (t *Type) Size() int64 { @@ -1023,12 +1099,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 { @@ -1133,6 +1209,12 @@ func (t *Type) cmp(x *Type) Cmp { if (t == Types[RuneType.kind] || t == RuneType) && (x == Types[RuneType.kind] || x == RuneType) { return CMPeq } + + case TINTER: + // Make sure named any type matches any empty interface. + if t == AnyType && x.IsEmptyInterface() || x == AnyType && t.IsEmptyInterface() { + return CMPeq + } } } @@ -1142,8 +1224,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 } @@ -1155,8 +1237,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 { @@ -1173,16 +1255,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 { @@ -1436,6 +1518,14 @@ func (t *Type) IsInterface() bool { return t.kind == TINTER } +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 @@ -1461,7 +1551,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() } @@ -1469,15 +1559,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 } @@ -1490,7 +1580,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 @@ -1552,15 +1642,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 } } @@ -1589,56 +1679,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 -} - -// 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' + return PtrDataSize(t) > 0 } var recvType *Type @@ -1646,11 +1687,15 @@ 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 } +func FakeRecv() *Field { + return NewField(src.NoXPos, nil, FakeRecvType()) +} + var ( // TSSA types. HasPointers assumes these are pointer-free. TypeInvalid = newSSA("invalid") @@ -1666,10 +1711,14 @@ 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 { - t := New(TFORW) +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 } @@ -1681,6 +1730,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) { @@ -1694,9 +1762,9 @@ 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.extra = underlying.extra + t.width = underlying.width + t.align = underlying.align t.underlying = underlying.underlying if underlying.NotInHeap() { @@ -1708,6 +1776,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 @@ -1739,9 +1810,18 @@ 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) +func newBasic(kind Kind, obj Object) *Type { + t := newType(kind) t.sym = obj.Sym() t.nod = obj return t @@ -1749,8 +1829,8 @@ 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) +func NewInterface(pkg *Pkg, methods []*Field, implicit bool) *Type { + t := newType(TINTER) t.SetInterface(methods) for _, f := range methods { // f.Type could be nil for a broken interface declaration @@ -1758,22 +1838,101 @@ 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) } - t.Extra.(*Interface).pkg = pkg + t.extra.(*Interface).pkg = pkg + t.extra.(*Interface).implicit = implicit return t } -// NewTypeParam returns a new type param. -func NewTypeParam(pkg *Pkg) *Type { - t := New(TTYPEPARAM) - t.Extra.(*Interface).pkg = pkg +// 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 := newType(TTYPEPARAM) + 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 +} + +// 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) + 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 +} + +// 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 +} + +// 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 { + t := newType(TUNION) + if len(terms) != len(tildes) { + base.Fatalf("Mismatched terms and tildes for NewUnion") + } + 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 +} + +// 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) { @@ -1790,7 +1949,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 { @@ -1817,21 +1976,27 @@ 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 } // 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) } - t.Extra.(*Struct).pkg = pkg + t.extra.(*Struct).pkg = pkg if fieldsHasTParam(fields) { t.SetHasTParam(true) } + if fieldsHasShape(fields) { + t.SetHasShape(true) + } return t } @@ -2028,7 +2193,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 @@ -2044,3 +2209,5 @@ var ( ) var SimType [NTYPE]Kind + +var ShapePkg = NewPkg("go.shape", "go.shape") diff --git a/src/cmd/compile/internal/types/type_test.go b/src/cmd/compile/internal/types/type_test.go index fe3f380b21f2d994ec77cd2c1d7be471d202b28b..1fd05b3f5e8c7677beebde97c47b622f5ac0431c 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) } } } diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go new file mode 100644 index 0000000000000000000000000000000000000000..54b04bda2239c142eadbed33a112f8c7f5b4215f --- /dev/null +++ b/src/cmd/compile/internal/types/universe.go @@ -0,0 +1,159 @@ +// 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] = newType(TANY) // note: an old placeholder type, NOT the new builtin 'any' alias for interface{} + Types[TINTER] = NewInterface(LocalPkg, nil, false) + CheckSize(Types[TINTER]) + + defBasic := func(kind Kind, pkg *Pkg, name string) *Type { + typ := newType(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)? + // 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") + 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() + + // any type (interface) + DeferCheckSize() + AnyType = defBasic(TFORW, BuiltinPkg, "any") + AnyType.SetUnderlying(NewInterface(BuiltinPkg, []*Field{}, false)) + ResumeCheckSize() + + if base.Flag.G == 0 { + ComparableType.Sym().Def = nil + } + + Types[TUNSAFEPTR] = defBasic(TUNSAFEPTR, UnsafePkg, "Pointer") + + Types[TBLANK] = newType(TBLANK) + Types[TNIL] = newType(TNIL) + + // 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}, false) +} + +// makeComparableInterface makes the the predefined "comparable" interface in the +// built-in package. It has a unique name, but no methods. +func makeComparableInterface() *Type { + return NewInterface(NoPkg, nil, false) +} diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 2939dcc0bdf27356ae1c5a99abfd44c836004060..ed5bced643428dc852cb4eb6fc134132e7e1da2a 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -55,6 +55,15 @@ func (err Error) FullError() string { return fmt.Sprintf("%s: %s", err.Pos, err.Full) } +// An ArgumentError holds an error associated with an argument index. +type ArgumentError struct { + Index int + Err error +} + +func (e *ArgumentError) Error() string { return e.Err.Error() } +func (e *ArgumentError) Unwrap() error { return e.Err } + // An Importer resolves import paths to Packages. // // CAUTION: This interface does not support the import of locally @@ -96,6 +105,10 @@ 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 { + // 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 // empty; an empty string indicates the latest language version. @@ -189,13 +202,27 @@ 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 - // 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). @@ -352,11 +379,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 []Type - 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 @@ -412,23 +441,31 @@ 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 } // 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. // 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/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 873390c1e9280d6b961ad02592e52e16f39096c3..fc8b5cd4ee01edbf48e13a1d8368e2f1ebbef273 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" @@ -17,25 +18,14 @@ import ( . "cmd/compile/internal/types2" ) -func unimplemented() { - panic("unimplemented") -} - -// 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) { @@ -149,6 +139,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< 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) } @@ -82,7 +86,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) @@ -153,6 +161,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 } @@ -161,7 +170,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 } @@ -212,9 +221,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 @@ -236,14 +242,89 @@ func (check *Checker) assignVar(lhs syntax.Expr, x *operand) Type { return x.typ } -// 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()) +// 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) + 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 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 for _, obj := range lhs { + obj.used = true // avoid declared but not used errors if obj.typ == nil { obj.typ = Typ[Invalid] } @@ -254,16 +335,32 @@ 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 } - 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 } context := "assignment" - if returnPos.IsKnown() { + if returnStmt != nil { context = "return statement" } @@ -276,8 +373,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 + } } } @@ -285,14 +392,18 @@ 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 { 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 } @@ -305,8 +416,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 + } + } + } + } } } @@ -337,7 +466,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 @@ -385,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/basic.go b/src/cmd/compile/internal/types2/basic.go new file mode 100644 index 0000000000000000000000000000000000000000..2fd973cafbc5e66022c8455e9073237e15de2c64 --- /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/builtins.go b/src/cmd/compile/internal/types2/builtins.go index f90e06f226791ddb7630c8b5c6d79788378bf486..fcf02a697591ac20864a70d98fe54e6d8a2acbff 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 { @@ -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, _ := structuralType(S).(*Slice); s != nil { T = s.elem } else { check.errorf(x, invalidArg+"%s is not a slice", x) @@ -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 @@ -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 @@ -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 = arrayPtrDeref(under(x.typ)); t := typ.(type) { case *Basic: if isString(t) && id == _Len { if x.mode == constant_ { @@ -178,9 +178,12 @@ 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 *Interface: + if !isTypeParam(x.typ) { + break + } + if t.typeSet().underIs(func(t Type) bool { + switch t := arrayPtrDeref(t).(type) { case *Basic: if isString(t) && id == _Len { return true @@ -212,19 +215,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: @@ -281,14 +288,16 @@ 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 } // 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(!isTypeParam(typ)) + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -321,33 +330,26 @@ 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, _ := structuralType(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 + 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) return } - if !check.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 } @@ -358,25 +360,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: @@ -405,8 +422,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(!isTypeParam(typ)) + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -451,39 +470,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 := optype(t).(type) { - case *Slice: - m = 2 - case *Map, *Chan: - m = 1 - case *Sum: - return t.is(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 structuralType(T).(type) { + case *Slice: + min = 2 + case *Map, *Chan: + min = 1 + case nil: + 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) 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 } @@ -580,7 +581,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 } @@ -603,19 +604,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 @@ -635,7 +639,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) @@ -653,39 +657,61 @@ 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) + // 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- + // 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 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 } - typ := asPointer(x.typ) + typ, _ := under(x.typ).(*Pointer) if typ == nil { check.errorf(x, invalidArg+"%s is not a pointer", x) return @@ -735,7 +761,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 } @@ -748,6 +774,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 u := under(t).(type) { + case *Array: + return hasVarSize(u.elem) + case *Struct: + for _, f := range u.fields { + if hasVarSize(f.typ) { + return true + } + } + case *Interface: + return isTypeParam(t) + case *Named, *Union: + 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 @@ -756,13 +801,16 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // 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 rtypes []Type - if !tp.Bound().is(func(x Type) bool { - if r := f(x); r != nil { - rtypes = append(rtypes, r) + var terms []*Term + 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 } return false @@ -770,16 +818,12 @@ 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 - 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} + // 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 + ptyp.index = tp.index return ptyp } @@ -803,12 +847,11 @@ 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 { + if a, _ := under(p.base).(*Array); a != nil { return a } } diff --git a/src/cmd/compile/internal/types2/builtins_test.go b/src/cmd/compile/internal/types2/builtins_test.go index 82c786b86ea20e5f8775d533b34d7cca8dadb3c1..be5707cdfeac4dce2820226470cf2b1fc16608a4 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) 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) 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) 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/call.go b/src/cmd/compile/internal/types2/call.go index 6d149340b285b3e6bd8fc241e7dd5a50a8036370..ed8b67c6074c2d572575e04499fa01e52ca115fc 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.versionErrorf(inst.Pos(), "go1.18", "function instantiation") + } + xlist := unpackExpr(inst.Index) targs := check.typeList(xlist) if targs == nil { @@ -26,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), len(sig.tparams) + 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 @@ -34,10 +38,8 @@ 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.tparams, 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 @@ -45,27 +47,48 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { return } got = len(targs) - inferred = true } 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.instantiate(x.Pos(), sig, targs, poslist).(*Signature) - assert(res.tparams == nil) // signature is not generic anymore - if inferred { - check.recordInferred(inst, targs, res) - } + 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 x.mode = value x.expr = inst } +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()) + + 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.bestContext(nil)).(*Signature) + 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(xlist) { + pos = syntax.StartPos(xlist[i]) + } + check.softErrorf(pos, "%s", err) + } else { + check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist) + } + + 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 { @@ -79,8 +102,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: @@ -90,6 +114,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 { @@ -98,10 +126,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 { - check.completeInterface(nopos, t) - if t.IsConstraint() { - check.errorf(call, "cannot use interface %s in conversion (contains type list or is comparable)", T) + 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 } } @@ -119,6 +146,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 @@ -132,9 +160,11 @@ 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) + // a type parameter may be "called" if all types have the same signature + sig, _ := structuralType(x.typ).(*Signature) if sig == nil { check.errorf(x, invalidOp+"cannot call non-function %s", x) x.mode = invalid @@ -143,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...) @@ -156,7 +187,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.TypeParams().Len() if got > want { check.errorf(xlist[want], "got %d type arguments but want %d", got, want) check.use(call.ArgList...) @@ -168,7 +199,13 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { // evaluate arguments args, _ := check.exprList(call.ArgList, false) - sig = check.arguments(call, sig, targs, args) + isGeneric := sig.TypeParams().Len() > 0 + 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 + check.recordTypeAndValue(call.Fun, value, sig, nil) + } // determine result switch sig.results.Len() { @@ -190,7 +227,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.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ) { x.mode = invalid } @@ -237,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 @@ -308,42 +346,63 @@ 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 } // infer type arguments and instantiate signature if necessary - if len(sig.tparams) > 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) + if sig.TypeParams().Len() > 0 { + if !check.allowVersion(check.pkg, 1, 18) { + if iexpr, _ := call.Fun.(*syntax.IndexExpr); iexpr != nil { + check.versionErrorf(iexpr.Pos(), "go1.18", "function instantiation") + } else { + check.versionErrorf(call.Pos(), "go1.18", "implicit function instantiation") + } + } + targs := check.infer(call.Pos(), sig.TypeParams().list(), targs, sigParams, args) if targs == nil { return // error already reported } // compute result signature - rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) - assert(rsig.tparams == nil) // signature is not generic anymore - check.recordInferred(call, targs, rsig) + rsig = check.instantiateSignature(call.Pos(), sig, targs, xlist) + assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore + 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 // 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.TypeParams().list(), targs), nil).(*Tuple) } else { sigParams = rsig.params } } // 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 @@ -461,14 +520,12 @@ 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 } - 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: @@ -478,13 +535,12 @@ 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". - switch obj := tpar.Bound().obj.(type) { - case 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) - 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) @@ -498,7 +554,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 } } @@ -511,58 +567,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 len(sig.rparams) > 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.rparams, 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.rparams, targs)) - 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 { @@ -576,17 +581,37 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { check.recordSelection(e, MethodExpr, x.typ, m, index, indirect) - // 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.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 if sig.params != nil { params = sig.params.vars } + // 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, - params: NewTuple(append([]*Var{NewVar(nopos, check.pkg, "_", x.typ)}, params...)...), + params: NewTuple(params...), results: sig.results, variadic: sig.variadic, } @@ -641,56 +666,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 { - continue - } - if l, _ := e.(*syntax.ListExpr); l != nil { - check.use(l.ElemList...) + 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 - } - check.rawExpr(&x, e, nil) - } -} - -// 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 - } - } - } - check.rawExpr(&x, e, nil) - if v != nil { - v.used = v_used // restore v.used + case *syntax.ListExpr: + check.use(n.ElemList...) + continue } - } -} - -// 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] + check.rawExpr(&x, e, nil, false) } } diff --git a/src/cmd/compile/internal/types2/chan.go b/src/cmd/compile/internal/types2/chan.go new file mode 100644 index 0000000000000000000000000000000000000000..77650dfb09daad6b56df0138063676b381b84fcc --- /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/check.go b/src/cmd/compile/internal/types2/check.go index 8d6cd1edab9d4c61cd1f1d5d7a99798def7fdcde..aacbb25b3b4f4dc981edf4813acc5168ec1232ca 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -39,22 +39,24 @@ 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) 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 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 } @@ -71,7 +73,29 @@ type importKey struct { // A dotImportKey describes a dot-imported object in the given scope. type dotImportKey struct { scope *Scope - obj Object + 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. @@ -80,13 +104,13 @@ 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 - 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 // 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 @@ -101,19 +125,22 @@ 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 + 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 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) + 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 @@ -144,8 +171,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. @@ -183,13 +214,12 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker { return &Checker{ conf: conf, + ctxt: conf.Context, pkg: pkg, Info: info, version: version, objMap: make(map[Object]*declInfo), impMap: make(map[importKey]*Package), - posMap: make(map[*Interface][]syntax.Pos), - typMap: make(map[string]*Named), } } @@ -256,6 +286,7 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { print := func(msg string) { if check.conf.Trace { + fmt.Println() fmt.Println(msg) } } @@ -272,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() @@ -283,9 +317,9 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { print("== recordUntyped ==") check.recordUntyped() - if check.Info != nil { - print("== sanitizeInfo ==") - sanitizeInfo(check.Info) + if check.firstErr == nil { + // TODO(mdempsky): Ensure monomorph is safe when errors exist. + check.monomorph() } check.pkg.complete = true @@ -295,6 +329,9 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { check.dotImportMap = nil check.pkgPathMap = nil check.seenPkgMap = nil + check.recvTParamMap = nil + check.defTypes = nil + check.ctxt = nil // TODO(gri) There's more memory we should release at this point. @@ -310,12 +347,40 @@ 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] } +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 @@ -365,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} @@ -418,12 +483,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{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/check_test.go b/src/cmd/compile/internal/types2/check_test.go index 41b0c54702d8d782ad42d4cf0c129f9540919253..f13679d1e3685b8ddb9915df86ae5dfdc0f2796a 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -20,14 +20,12 @@ // _ = 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 ( "cmd/compile/internal/syntax" "flag" + "internal/buildcfg" "internal/testenv" "os" "path/filepath" @@ -96,13 +94,30 @@ 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, + "issue49705.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") { + if strings.HasSuffix(filenames[0], ".go2") || manual { mode |= syntax.AllowGenerics } // parse files and collect parser errors @@ -280,7 +295,8 @@ 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/compilersupport.go b/src/cmd/compile/internal/types2/compilersupport.go new file mode 100644 index 0000000000000000000000000000000000000000..b35e752b8f7ce51f0e6af8af5b51ede6a81180fe --- /dev/null +++ b/src/cmd/compile/internal/types2/compilersupport.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. + +// 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 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/context.go b/src/cmd/compile/internal/types2/context.go new file mode 100644 index 0000000000000000000000000000000000000000..7abea6b654b34dd738a707c21c3cd11a3ee48669 --- /dev/null +++ b/src/cmd/compile/internal/types2/context.go @@ -0,0 +1,123 @@ +// Copyright 2021 The Go Authors. 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" +) + +// 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 Context struct { + 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 { + orig Type + targs []Type + instance Type // = orig[targs] +} + +// NewContext creates a new Context. +func NewContext() *Context { + return &Context{ + typeMap: make(map[string][]ctxtEntry), + originIDs: make(map[Type]int), + } +} + +// 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(orig != nil) + var buf bytes.Buffer + + h := newTypeHasher(&buf, ctxt) + 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. + h.typeList(targs) + } + + return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4 +} + +// lookup returns an existing instantiation of orig with targs, if it exists. +// Otherwise, it returns nil. +func (ctxt *Context) lookup(h string, orig Type, targs []Type) Type { + ctxt.mu.Lock() + defer ctxt.mu.Unlock() + + for _, e := range ctxt.typeMap[h] { + 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.instance)) + } + } + + 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, orig Type, targs []Type, inst Type) Type { + assert(inst != nil) + + ctxt.mu.Lock() + defer ctxt.mu.Unlock() + + for _, e := range ctxt.typeMap[h] { + 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", inst, e.instance)) + } + } + + ctxt.typeMap[h] = append(ctxt.typeMap[h], ctxtEntry{ + orig: orig, + targs: targs, + instance: inst, + }) + + return inst +} + +// 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.originIDs[t] + if !ok { + id = ctxt.nextID + ctxt.originIDs[t] = id + ctxt.nextID++ + } + return id +} 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 0000000000000000000000000000000000000000..aa649b14481f76100988eef817ff1720a9ebd540 --- /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/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 30201e2b7f4232a147d17a2bdbc8cbb5bc301be3..253868cf931b20adbd7861ad21b094c35a0c245c 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" ) @@ -16,32 +17,74 @@ import ( func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ - var ok bool - switch { - case constArg && isConstType(T): - // constant conversion - switch t := asBasic(T); { - case representableConst(x.val, check, t, &x.val): - ok = true + constConvertibleTo := func(T Type, val *constant.Value) bool { + switch t, _ := under(T).(*Basic); { + 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 } - case x.convertibleTo(check, T): + 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 = 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) + 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): // non-constant conversion - x.mode = value ok = true + x.mode = value } if !ok { - if x.mode != invalid { - check.errorf(x, "cannot convert %s to %s", x, T) - x.mode = invalid + var err error_ + 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 return } @@ -59,9 +102,9 @@ 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) && isString(T) { + } else if isInteger(x.typ) && allString(T) { final = x.typ } check.updateExprType(x.expr, final, true) @@ -80,108 +123,173 @@ 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 } - // "x's type 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 check.identicalIgnoreTags(Vu, Tu) { + Vp, _ := V.(*TypeParam) + Tp, _ := T.(*TypeParam) + if IdenticalIgnoreTags(Vu, Tu) && Vp == nil && Tp == nil { return true } - // "x's type and T are unnamed pointer types and their pointer base types - // have identical underlying types if tags are ignored" + // "V and T are unnamed pointer types and their pointer base types + // 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 check.identicalIgnoreTags(under(V.base), under(T.base)) { + if IdenticalIgnoreTags(under(V.base), under(T.base)) && !isTypeParam(V.base) && !isTypeParam(T.base) { return true } } } - // "x's type and T are both integer or floating point types" - if isIntegerOrFloat(V) && isIntegerOrFloat(T) { + // "V and T are both integer or floating point types" + if isIntegerOrFloat(Vu) && isIntegerOrFloat(Tu) { return true } - // "x's type and T are both complex types" - if isComplex(V) && isComplex(T) { + // "V and T are both complex types" + if isComplex(Vu) && isComplex(Tu) { return true } - // "x is an integer or a slice of bytes or runes and T is a string type" - if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { + // "V is an integer or a slice of bytes or runes and T is a string type" + if (isInteger(Vu) || isBytesOrRunes(Vu)) && isString(Tu) { return true } - // "x is a string and T is a slice of bytes or runes" - if isString(V) && isBytesOrRunes(Tu) { + // "V is a string and T is a slice of bytes or runes" + 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 } - // "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 { - if a := asArray(p.Elem()); a != nil { - if check.identical(s.Elem(), a.Elem()) { + 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) { 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 { + *cause = "conversion of slices to array pointers requires go1.17 or later" + if check.conf.CompilerErrorMessages { + *cause += fmt.Sprintf(" (-lang was set to %s; check go.mod)", check.conf.GoVersion) + } } - x.mode = invalid // avoid follow-up error + return false } } } } + // optimization: if we don't have type parameters, we're done + 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 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 + } + 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 } 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? - // (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/decl.go b/src/cmd/compile/internal/types2/decl.go index 1333e4c0eca323c2725b8c24ea733d7919258ff6..a4bc3969c0de1e2ffd44663c8d088c888252ed8f 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 { @@ -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(nil, 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 @@ -118,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 @@ -130,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 @@ -150,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 @@ -172,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, } @@ -204,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] @@ -222,13 +228,23 @@ func (check *Checker) cycle(obj Object) (isCycle 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 @@ -256,31 +272,36 @@ func (check *Checker) cycle(obj Object) (isCycle 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 isCycle { + if !valid { check.trace(obj.Pos(), "=> error: cycle is invalid") } }() } - // 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 false - } + 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 false // cycle is permitted + // 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) - - return true + return false } type typeInfo uint @@ -309,6 +330,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 { @@ -317,6 +345,17 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: + // 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 { @@ -338,20 +377,18 @@ 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:]) t.info = invalid - return t.info + t.underlying = Typ[Invalid] + return invalid } } - panic("internal error: cycle start not found") + panic("cycle start not found") } return t.info - - case *instance: - return check.validType(t.expand(), path) } return valid @@ -512,84 +549,30 @@ 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) } -// 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 == nil { - return Typ[Invalid] - } - - // If the underlying type of a defined type is not a defined - // type, then that is the desired underlying type. - n := asNamed(u) - if n == nil { - return u // common case - } - - // 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 - } - n1 := asNamed(u) - 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 - // 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:]) - } - 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 more (it's cheap). - if n0.check != nil && n.obj.pkg != n0.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 +// 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.IsMethodSet() } 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.versionErrorf(tdecl.Type, "go1.18", "using type constraint %s", rhs) + } + }).describef(obj, "validType(%s)", obj.Name()) alias := tdecl.Alias if alias && tdecl.TParamList != nil { @@ -599,123 +582,136 @@ 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") - } else { - check.error(tdecl, "type aliases requires go1.9 or later") - } + check.versionErrorf(tdecl, "go1.9", "type aliases") } obj.typ = Typ[Invalid] - obj.typ = check.anyType(tdecl.Type) - - } else { - // defined type declaration + rhs = check.varType(tdecl.Type) + obj.typ = rhs + return + } - 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() + check.collectTypeParams(&named.tparams, tdecl.TParamList) + } - // determine underlying type of named - named.fromRHS = check.definedType(tdecl.Type, named) + // determine underlying type of 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] } + // Disallow a lone type parameter as the RHS of a type declaration (issue #45639). + // 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] + } } -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(dst **TypeParamList, list []*syntax.Field) { + tparams := make([]*TypeParam, 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(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) + + // 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 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 + defer func() { + check.inTParamList = false + }() + // Keep track of bounds for later validation. 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 + 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 + } - // 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++ + 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") } - } else if bound != Typ[Invalid] { - check.errorf(f.Type, "%s is not an interface", bound) } - } - - return + for _, tpar := range tparams { + tpar.iface() // compute type set + } + }) } -func (check *Checker) declareTypeParam(tparams []*TypeName, 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.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position - tparams = append(tparams, tpar) - - if check.conf.Trace { - check.trace(name.Pos(), "type param = %v", tparams[len(tparams)-1]) +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) { + 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) +} - return 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, 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 } func (check *Checker) collectMethods(obj *TypeName) { @@ -735,9 +731,10 @@ 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 { - if t, _ := base.underlying.(*Struct); t != nil { + u := base.under() + if t, _ := u.(*Struct); t != nil { for _, fld := range t.fields { if fld.name != "_" { assert(mset.insert(fld) == nil) @@ -779,6 +776,7 @@ func (check *Checker) collectMethods(obj *TypeName) { } if base != nil { + base.resolve(nil) // TODO(mdempsky): Probably unnecessary. base.methods = append(base.methods, m) } } @@ -805,6 +803,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/errorcalls_test.go b/src/cmd/compile/internal/types2/errorcalls_test.go index 28bb33aaffd00443da31ca7086caa1e8cfba37f2..80b05f9f0f06883022a9333d84d93c233f4c7294 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/errors.go b/src/cmd/compile/internal/types2/errors.go index af4ecb2300a58cbfe5e8eeae32220fe72129ba2d..c39652fe5e4378bc254151060afedee4feec8cd9 100644 --- a/src/cmd/compile/internal/types2/errors.go +++ b/src/cmd/compile/internal/types2/errors.go @@ -61,9 +61,12 @@ 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...)) + buf.WriteString(sprintf(qf, false, p.format, p.args...)) } return buf.String() } @@ -82,13 +85,13 @@ 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: 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: @@ -98,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 } @@ -111,7 +114,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 { @@ -143,12 +146,12 @@ 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_) { if err.empty() { - panic("internal error: reporting no error") + panic("no error to report") } check.err(err.pos(), err.msg(check.qualifier), err.soft) } @@ -157,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) { @@ -227,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) { @@ -246,7 +259,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 e1f0e83fc97d16f43be86cf4eb169d78e1bba284..ac73ca4650dc4a54852ad20092a7b6df99a4e4ce 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) @@ -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/example_test.go b/src/cmd/compile/internal/types2/example_test.go index 714bf77821399683925a986183c984869edc93b2..4edaad580e5fce5869181b35495307a508cc3f8e 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(): diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 23b79656bb5fb0dabb7c769a27bcb86e10e68b7a..5961f32f37f58314b225d1809fdc2106c20806a9 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, } } @@ -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, under(x.typ).(*Basic)) return } @@ -127,9 +129,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 { @@ -157,6 +157,15 @@ 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 { + if tpar, _ := typ.(*TypeParam); tpar != nil { + return tpar.underIs(f) + } + return f(under(typ)) +} + func (check *Checker) unary(x *operand, e *syntax.Operation) { check.expr(x, e.X) if x.mode == invalid { @@ -177,19 +186,25 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { return case syntax.Recv: - typ := asChan(x.typ) - if typ == nil { + 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 typ.dir == SendOnly { + 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 = typ.elem + x.typ = ch.elem check.hasCallOrRecv = true return } @@ -597,7 +612,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 } @@ -610,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 } @@ -643,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, target.Underlying()) + t := target + if !isTypeParam(target) { + t = safeUnderlying(target) + } + check.invalidConversion(code, x, t) x.mode = invalid return } @@ -664,7 +683,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 } @@ -691,10 +709,10 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return nil, nil, _InvalidUntypedConversion } - switch t := optype(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 } @@ -723,20 +741,23 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const default: return nil, nil, _InvalidUntypedConversion } - case *Sum: - ok := t.is(func(t Type) bool { - target, _, _ := check.implicitTypeAndValue(x, t) - return target != nil - }) - if !ok { - return nil, nil, _InvalidUntypedConversion - } case *Interface: + if isTypeParam(target) { + if !u.typeSet().underIs(func(u Type) bool { + if u == nil { + return false + } + t, _, _ := check.implicitTypeAndValue(x, u) + return t != nil + }) { + 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. - check.completeInterface(nopos, t) - 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 @@ -760,7 +781,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() } @@ -814,7 +835,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 { @@ -845,12 +866,12 @@ 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) { - check.errorf(y, invalidOp+"signed shift count %s requires go1.13 or later", y) + } else if !allUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { + check.versionErrorf(y, "go1.13", invalidOp+"signed shift count %s", y) x.mode = invalid return } @@ -920,7 +941,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 @@ -934,19 +955,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.And: isInteger, - syntax.Or: isInteger, - syntax.Xor: isInteger, - syntax.AndNot: isInteger, - - syntax.AndAnd: isBoolean, - syntax.OrOr: isBoolean, + syntax.Add: allNumericOrString, + syntax.Sub: allNumeric, + syntax.Mul: allNumeric, + syntax.Div: allNumeric, + syntax.Rem: allInteger, + + syntax.And: allInteger, + syntax.Or: allInteger, + syntax.Xor: allInteger, + syntax.AndNot: allInteger, + + syntax.AndAnd: allBoolean, + syntax.OrOr: allBoolean, } } @@ -972,14 +993,35 @@ 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 + // TODO(gri) make canMix more efficient - called for each binary operation + canMix := func(x, y *operand) bool { + if IsInterface(x.typ) && !isTypeParam(x.typ) || IsInterface(y.typ) && !isTypeParam(y.typ) { + return true + } + if allBoolean(x.typ) != allBoolean(y.typ) { + return false + } + if allString(x.typ) != allString(y.typ) { + return false + } + if x.isNil() && !hasNil(y.typ) { + return false + } + if y.isNil() && !hasNil(x.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) { @@ -987,11 +1029,15 @@ 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] { - check.errorf(x, invalidOp+"mismatched types %s and %s", 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 @@ -1004,7 +1050,7 @@ 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 @@ -1057,8 +1103,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++ @@ -1069,11 +1117,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. // @@ -1176,7 +1253,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 @@ -1184,8 +1265,14 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin goto Error } - switch utyp := optype(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. + if utyp.fields == nil { + check.error(e, "illegal cycle in type declaration") + goto Error + } if len(e.ElemList) == 0 { break } @@ -1314,9 +1401,9 @@ 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 check.identical(vtyp, x.typ) { + if Identical(vtyp, x.typ) { duplicate = true break } @@ -1358,7 +1445,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 @@ -1384,12 +1471,16 @@ 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 } - check.ordinaryType(x.Pos(), xtyp) // x.(type) expressions are encoded via TypeSwitchGuards if e.Type == nil { check.error(e, invalidAST+"invalid use of AssertExpr") @@ -1399,7 +1490,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 @@ -1441,20 +1532,31 @@ 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 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 } @@ -1530,26 +1632,27 @@ 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 err error_ var msg string - if wrongType != nil { - if check.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) - } - } else { - msg = "missing method " + method.name - } - if check.conf.CompilerErrorMessages { - check.errorf(pos, "impossible type assertion: %s (%s)", x, msg) + if typeSwitch { + err.errorf(e.Pos(), "impossible type switch case: %s", e) + msg = check.sprintf("%s cannot have dynamic type %s %s", x, T, + check.missingMethodReason(T, x.typ, method, wrongType)) + } else { - check.errorf(pos, "%s cannot have dynamic type %s (%s)", x, T, msg) + err.errorf(e.Pos(), "impossible type assertion: %s", e) + 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) } // expr typechecks expression e and initializes x with the expression value. @@ -1557,14 +1660,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 { + if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } } + // x should not be generic at this point, but be safe and check + check.nonGeneric(x) + if x.mode == invalid { + return false + } + // 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 @@ -64,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 @@ -80,7 +88,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,101 +97,100 @@ 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 *Sum: - // A sum type can be indexed if all of the sum's types - // support indexing and have the same index and element - // type. Special rules apply for maps in the sum 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 { - var e Type - switch t := under(t).(type) { + case *Interface: + if !isTypeParam(x.typ) { + break + } + // 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 := asArray(t.base); t != nil { + if t, _ := under(t.base).(*Array); t != nil { + l = t.len e = t.elem } case *Slice: e = t.elem case *Map: - // If there are multiple maps in the sum 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) { - return false - } - tkey = t.key + k = 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: - panic("unimplemented") } - if e == nil || telem != nil && !Identical(e, telem) { + 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 } - telem = e + // track the minimal length for arrays, if any + if l >= 0 && l < length { + length = l + } 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 key != 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") + 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 - - // If there are only maps, we are done. - if nmaps == len(typ.types) { - 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 = elem + x.expr = e + return false } - x.typ = telem + + // no maps + valid = true + x.mode = mode + x.typ = elem } } 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) @@ -206,11 +213,20 @@ 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 := structuralString(x.typ).(type) { + case nil: + check.errorf(x, invalidOp+"cannot slice %s: %s has no structural type", x, x.typ) + x.mode = invalid + return + case *Basic: - if isString(typ) { + 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 } @@ -220,36 +236,31 @@ 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 isUntyped(x.typ) { 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, _ := under(u.base).(*Array); u != nil { valid = true - length = typ.len - x.typ = &Slice{elem: typ.elem} + length = u.len + x.typ = &Slice{elem: u.elem} } case *Slice: valid = true // x.typ doesn't change - - case *Sum, *TypeParam: - check.error(x, "generic slice expressions not yet implemented") - x.mode = invalid - return } if !valid { @@ -298,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 } } @@ -382,7 +396,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/infer.go b/src/cmd/compile/internal/types2/infer.go index f37d7f6477e96ab29bb8d0e6705cb65b0dd8cb37..b203985b8d129027d75a8b16c10c54e7bc0307b5 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 @@ -27,8 +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. -// -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) (result []Type) { if debug { defer func() { assert(result == nil || len(result) == len(tparams)) @@ -60,7 +60,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p // 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(pos, tparams, targs) if targs == nil || index < 0 { return targs } @@ -83,18 +83,18 @@ 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) - params = check.subst(nopos, params, smap).(*Tuple) + params = check.subst(nopos, params, smap, nil).(*Tuple) } // --- 2 --- // 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. @@ -105,9 +105,6 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p } 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 { @@ -122,12 +119,12 @@ 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 } } 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 { @@ -174,7 +171,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p // 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(pos, tparams, targs) if targs == nil || index < 0 { return targs } @@ -212,7 +209,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p // Again, follow up with constraint type inference. if useConstraintTypeInference { - targs, index = check.inferB(tparams, targs, report) + targs, index = check.inferB(pos, tparams, targs) if targs == nil || index < 0 { return targs } @@ -221,24 +218,22 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p // 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.name, tpar.pos, targs) - } + check.errorf(pos, "cannot infer %s (%s)", tpar.obj.name, tpar.obj.pos) 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 +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, @@ -266,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) { @@ -307,9 +302,6 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } } - case *Sum: - return w.isParameterizedList(t.types) - 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 @@ -321,24 +313,15 @@ 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.isParameterizedList(unpack(t.allTypes)) } - - return t.iterate(func(t *Interface) bool { - for _, m := range t.methods { - if w.isParameterized(m.typ) { - return true - } - } - return w.isParameterizedList(unpack(t.types)) - }, nil) + return tset.is(func(t *term) bool { + return t != nil && w.isParameterized(t.typ) + }) case *Map: return w.isParameterized(t.key) || w.isParameterized(t.elem) @@ -347,14 +330,11 @@ 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.list()) case *TypeParam: // 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) + return tparamIndex(w.tparams, t) >= 0 default: unreachable() @@ -363,7 +343,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 @@ -380,12 +360,12 @@ func (w *tpWalker) isParameterizedList(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(pos syntax.Pos, 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(check, false) + u := newUnifier(false) u.x.init(tparams) u.y = u.x // type parameters between LHS and RHS of unification are identical @@ -396,24 +376,28 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty } } - // 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.typ.(*TypeParam) - sbound := check.structuralType(typ.bound) + sbound := structuralType(tpar) if sbound != nil { - if !u.unify(typ, sbound) { - if report { - check.errorf(tpar, "%s does not match %s", tpar, sbound) - } + // 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(tpar, sbound) { + // TODO(gri) improve error message by providing the type arguments + // which we know already + check.errorf(pos, "%s does not match %s", tpar, sbound) return nil, 0 } } } // 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 + // 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 // remaining type parameters by substituting the type parameters in this type list // until nothing changes anymore. @@ -424,6 +408,34 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty } } + // 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. @@ -442,7 +454,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++ @@ -473,15 +485,97 @@ 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 { - check.completeInterface(nopos, iface) - types := unpack(iface.allTypes) - if len(types) == 1 { - return types[0] +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 + } } - return 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: + // 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) } - return constraint } diff --git a/src/cmd/compile/internal/types2/initorder.go b/src/cmd/compile/internal/types2/initorder.go index 40816276665117ba4bae14c040d515544df9654b..cf6110baa92c0f918b201af3bfe05f9e7f4d2586 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/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 0df52e851c9de4b6f02726325ad1698fb73c060e..cda6c7baf4e5c543f674903a05f01ca8a24d9a81 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -2,62 +2,265 @@ // 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 ( "cmd/compile/internal/syntax" + "errors" "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) { +// 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-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 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. +// +// 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 := 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 nil, &ArgumentError{i, err} + } + } + + inst := (*Checker)(nil).instance(nopos, orig, targs, ctxt) + return inst, nil +} + +// 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) (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: - 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 - }() + 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) + } + res = named + case *Signature: + tparams := orig.TypeParams() + if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { + return Typ[Invalid] + } + if tparams.Len() == 0 { + return orig // nothing to do (minor optimization) + } + 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 == orig { + copy := *sig + sig = © + } + // After instantiating a generic signature, it is not generic + // anymore; we need to set tparams to nil. + sig.tparams = nil + res = sig default: - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) + // only types and functions can be generic + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, orig)) } - // 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 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) } - if len(tparams) == 0 { - return typ // nothing to do (minor optimization) + return res +} + +// 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, 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", ntargs, ntparams) + return false + } + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams)) + } + return true +} + +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) - return (*Checker)(nil).subst(pos, typ, smap) + for i, tpar := range tparams { + // 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 +} + +// 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 + } + + errorf := func(format string, args ...interface{}) error { + return errors.New(sprintf(qf, false, format, args...)) + } + + Ti, _ := Tu.(*Interface) + if Ti == nil { + return errorf("%s is not an interface", T) + } + + // 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) + + // 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 + + // No type with non-empty type set satisfies the empty type set. + if Ti.typeSet().IsEmpty() { + return errorf("cannot implement %s (empty type set)", T) + } + + // If T is comparable, V must be comparable. + // TODO(gri) the error messages could be better, here + if Ti.IsComparable() && !Comparable(V) { + if Vi != nil && Vi.Empty() { + return errorf("empty interface %s does not implement %s", V, T) + } + return errorf("%s does not implement comparable", V) + } + + // V must implement T (methods) + // - check only if we have methods + if Ti.NumMethods() > 0 { + 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 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 implement %s: wrong method signature\n\tgot %s\n\twant %s", + V, T, wrong, m, + ) + } + return errorf("%s does not implement %s (missing method %s)", V, T, m.name) + } + } + + // V must also be in the set of types of T, if any. + // Constraints with empty type sets were already excluded above. + if !Ti.typeSet().hasTerms() { + return nil // nothing to do + } + + // 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 implement %s", V, T) + } + return nil + } + + // Otherwise, V's type must be included in the iface type set. + 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/instantiate_test.go b/src/cmd/compile/internal/types2/instantiate_test.go new file mode 100644 index 0000000000000000000000000000000000000000..591b467a2e382a8323f32367e915c73153d56ed4 --- /dev/null +++ b/src/cmd/compile/internal/types2/instantiate_test.go @@ -0,0 +1,247 @@ +// Copyright 2021 The Go Authors. 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" + "strings" + "testing" +) + +func TestInstantiateEquality(t *testing.T) { + emptySignature := NewSignatureType(nil, nil, nil, nil, nil, false) + 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, + }, + { + // 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]}, + "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, + }, + } + + 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) + 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 context. + T1 := pkg1.Scope().Lookup("T").Type().(*Named) + T2 := pkg2.Scope().Lookup("T").Type().(*Named) + ctxt := NewContext() + res1, err := Instantiate(ctxt, T1, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + res2, err := Instantiate(ctxt, 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) + } +} + +func TestMethodInstantiation(t *testing.T) { + const prefix = `package 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 = `package 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/interface.go b/src/cmd/compile/internal/types2/interface.go new file mode 100644 index 0000000000000000000000000000000000000000..b048fdd9e25ba70c6687f695f15767b7e25b17fe --- /dev/null +++ b/src/cmd/compile/internal/types2/interface.go @@ -0,0 +1,184 @@ +// Copyright 2021 The Go Authors. 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 + +// 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 + 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 +} + +// typeSet returns the type set for interface t. +func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(t.check, nopos, t) } + +// emptyInterface represents the empty interface +var emptyInterface = Interface{complete: true, tset: &topTypeSet} + +// 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 +} + +// 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) } + +// 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) } + +// 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().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().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) } + +// ---------------------------------------------------------------------------- +// Implementation + +func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) { + 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 { + addEmbedded(posFor(f.Type), parseUnion(check, f.Type)) + continue + } + // f.Name != nil + + // We have a method with name f.Name. + 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 + } + + 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) + } + + // 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 + + if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 { + // empty interface + ityp.tset = &topTypeSet + return + } + + // sort for API stability + // (don't sort embeddeds: they must correspond to *embedPos entries) + sortMethods(ityp.methods) + + // 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. + // + // 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 + }).describef(iface, "compute type set for %s", ityp) +} diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go index e716a48038510a2320c02524c4375d0bdaa9ef6f..9890b79323ac81dfe0347532b831b1cf2f635513 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 @@ -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 { diff --git a/src/cmd/compile/internal/types2/labels.go b/src/cmd/compile/internal/types2/labels.go index d3206988b54b69d41fd525e6ba9beec487b3e8ba..6f02e2fc969b084f4c86496ff8e9cc0999be2f6c 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 78299502e9c00d9ab176733912a31c60d2602a50..ee764c7d1407ef2fdc1a9c2da41fb00ef461e82e 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -6,6 +6,16 @@ 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 +// 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 +43,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 @@ -53,9 +50,9 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package // 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, _ := t.underlying.(*Pointer); p != nil { - obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name) + 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 } @@ -63,7 +60,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package } } - return check.rawLookupFieldOrMethod(T, addressable, pkg, name) + return lookupFieldOrMethod(T, addressable, false, pkg, name) } // TODO(gri) The named type consolidation and seen maps below must be @@ -71,10 +68,13 @@ 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. +// 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! - // This function and NewMethodSet should be kept in sync. if name == "_" { return // blank fields/methods are never found @@ -83,9 +83,10 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack 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 + if isPtr { + if _, ok := under(typ).(*Interface); ok { + return + } } // Start with typ as single entry at shallowest depth. @@ -111,7 +112,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack // 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 @@ -126,7 +127,8 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack seen[named] = true // look for a matching attached method - if i, m := lookupMethod(named.methods, pkg, name); m != nil { + 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 index = concat(e.index, i) @@ -138,12 +140,8 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack 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 @@ -181,9 +179,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 := lookupMethodFold(t.typeSet().methods, pkg, name, checkFold); m != nil { assert(m.typ != nil) index = concat(e.index, i) if obj != nil || e.multiples { @@ -194,7 +190,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 := lookupMethodFold(t.iface().typeSet().methods, pkg, name, checkFold); m != nil { assert(m.typ != nil) index = concat(e.index, i) if obj != nil || e.multiples { @@ -221,7 +217,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack // 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 } @@ -229,7 +225,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 @@ -246,7 +242,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 } @@ -254,7 +250,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 { @@ -266,14 +262,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 } } @@ -306,41 +302,41 @@ 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) + 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) if f == nil { - // if m is the magic method == we're ok (interfaces are comparable) - if m.name == "==" || !static { + if !static { continue } + // We don't do any case-fold check if V is an interface. 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) { + if ftyp.TypeParams().Len() != mtyp.TypeParams().Len() { return m, f } + if !acceptMethodTypeParams && ftyp.TypeParams().Len() > 0 { + panic("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 // 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.x.init(ftyp.tparams) + u := newUnifier(true) + u.x.init(ftyp.TypeParams().list()) if !u.unify(ftyp, mtyp) { return m, f } @@ -350,17 +346,25 @@ 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 { - // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)? - obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name) + for _, m := range T.typeSet().methods { + // 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, _, _ = check.rawLookupFieldOrMethod(ptr, false, m.pkg, m.name) + obj, _, _ = lookupFieldOrMethod(ptr, false, false, m.pkg, m.name) + 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 obj != nil { + // methods may not have a fully set up signature yet + if check != nil { + check.objDecl(obj, nil) + } return m, obj.(*Func) } } @@ -368,10 +372,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 } @@ -383,28 +383,11 @@ 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.TypeParams().Len() != mtyp.TypeParams().Len() { return m, f } - - // 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 && 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 - // 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) { - return - } - ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.rparams, Vn.targs)).(*Signature) + if !acceptMethodTypeParams && ftyp.TypeParams().Len() > 0 { + panic("method with type parameters") } // If the methods have type parameters we don't care whether they @@ -412,8 +395,21 @@ 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.x.init(ftyp.tparams) + u := newUnifier(true) + 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. + 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.RecvTypeParams().list(), ftyp.TypeParams().list()...)) + } else { + u.x.init(ftyp.RecvTypeParams().list()) + } if !u.unify(ftyp, mtyp) { return m, f } @@ -422,6 +418,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, 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 + 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) && !isTypeParam(T) { + if isInterfacePtr(V) { + r = fmt.Sprintf("(%s is pointer to interface, not interface)", V) + } + } else if isInterfacePtr(T) && !isTypeParam(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) && !isTypeParam(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. @@ -433,7 +482,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) @@ -443,6 +492,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 @@ -451,8 +507,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 } } @@ -491,21 +547,20 @@ 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 +// 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 + } + } } - - // 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 + return -1, nil } diff --git a/src/cmd/compile/internal/types2/map.go b/src/cmd/compile/internal/types2/map.go new file mode 100644 index 0000000000000000000000000000000000000000..0d3464caae728b7b0207365264170337666953ad --- /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/mono.go b/src/cmd/compile/internal/types2/mono.go new file mode 100644 index 0000000000000000000000000000000000000000..7bd79f4282efdcc1d196c4149428c07c3c459169 --- /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, xlist []syntax.Expr) { + for i, tpar := range tparams { + pos := pos + if i < len(xlist) { + pos = syntax.StartPos(xlist[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 0000000000000000000000000000000000000000..19d0e95637947191d268a776be9f7c4f54380c00 --- /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/named.go b/src/cmd/compile/internal/types2/named.go new file mode 100644 index 0000000000000000000000000000000000000000..51ea27a6dbd19dab05d799c8315bbb28d33e0102 --- /dev/null +++ b/src/cmd/compile/internal/types2/named.go @@ -0,0 +1,347 @@ +// 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" + "sync" +) + +// 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 + 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 + + // resolver may be provided to lazily resolve type parameters, underlying, and methods. + resolver func(*Context, *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. +// 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("underlying type must not be *Named") + } + return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) +} + +func (t *Named) resolve(ctxt *Context) *Named { + if t.resolver == nil { + return t + } + + t.once.Do(func() { + // 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 + // also make the API more future-proof towards further extensions + // (like SetTypeParams). + t.tparams, t.underlying, t.methods = t.resolver(ctxt, t) + t.fromRHS = t.underlying // for cycle detection + }) + 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 *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 + } + if obj.typ == nil { + obj.typ = typ + } + // Ensure that typ is always expanded and sanity-checked. + if check != nil { + check.defTypes = append(check.defTypes, typ) + } + return typ +} + +// 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 + +// 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. + +// 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.resolve(nil).tparams } + +// SetTypeParams sets the type parameters of the named type t. +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.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.resolve(nil).methods[i] } + +// SetUnderlying sets the underlying type and marks t as complete. +func (t *Named) SetUnderlying(underlying Type) { + if underlying == nil { + panic("underlying type must not be nil") + } + if _, ok := underlying.(*Named); ok { + panic("underlying type must not be *Named") + } + t.resolve(nil).underlying = underlying +} + +// AddMethod adds method m unless it is already in the method list. +func (t *Named) AddMethod(m *Func) { + 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.resolve(nil).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. +// +// 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() + + // If the underlying type of a defined type is not a defined + // (incl. instance) type, then that is the desired underlying + // type. + var n1 *Named + switch u1 := u.(type) { + case nil: + // After expansion via Underlying(), we should never encounter a nil + // underlying. + panic("nil underlying") + default: + // common case + return u + case *Named: + // handled below + n1 = u1 + } + + if n0.check == nil { + panic("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 + n := n0 + + seen := make(map[*Named]int) // types that need their underlying resolved + var path []Object // objects encountered, for cycle reporting + +loop: + for { + 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 { + // 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("imported type with unresolved underlying type") + } + n.underlying = u + } + + return u +} + +func (n *Named) setUnderlying(typ Type) { + if n != nil { + n.underlying = typ + } +} + +// bestContext returns the best available context. In order of preference: +// - the given ctxt, if 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 { + if check.ctxt == nil { + check.ctxt = NewContext() + } + return check.ctxt + } + 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(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 + + 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. + ctxt = check.bestContext(ctxt) + 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) + + smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) + underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt) + + 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(ctxt, m) + } + } + } + if check != nil { + check.later(completeMethods) + } else { + completeMethods() + } + + return n.orig.tparams, underlying, methods +} + +func (check *Checker) completeMethod(ctxt *Context, 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, ctxt).(*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 m.hasPtrRecv() { + rtyp = NewPointer(rbase) + } else { + rtyp = rbase + } + 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 +// 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.underlying + } + return typ.Underlying() +} diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 844bc34b6a3d1e7034880d667b48b1bedcef87f2..c7c64ca9d5dd209224e30d49ae80c1d077bfa09a 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 { @@ -237,6 +276,26 @@ 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, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { + obj := NewTypeName(pos, pkg, name, nil) + + resolve := func(_ *Context, 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 +} + // IsAlias reports whether obj is an alias name for a type. func (obj *TypeName) IsAlias() bool { switch t := obj.typ.(type) { @@ -256,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 } @@ -304,7 +365,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; use hasPtrRecv() to read } // NewFunc returns a new function with the given signature, representing @@ -315,7 +377,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 @@ -327,36 +389,27 @@ 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 } -// 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 +// 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 } - // 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 + // 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 @@ -407,6 +460,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 { @@ -452,19 +508,34 @@ 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 + 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) } } + // 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 7f63c793325721dca1512a4628d970e31f523892..8f0303d4b2457851ec9f1392cca40ee335219ca2 100644 --- a/src/cmd/compile/internal/types2/object_test.go +++ b/src/cmd/compile/internal/types2/object_test.go @@ -2,17 +2,16 @@ // 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" + "internal/testenv" "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) { @@ -25,7 +24,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") } } @@ -33,6 +32,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 @@ -40,12 +41,13 @@ 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) } @@ -86,3 +88,80 @@ 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 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}"}, + {"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 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) { + 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().LookupParent(names[0], nopos) + 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/operand.go b/src/cmd/compile/internal/types2/operand.go index 455d8b5dd1df22c40fb3b0bf12d8f8b914ed1ea9..f6bd0291ece212a7f6b261883a7bd61a6d1004e7 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)) } @@ -176,16 +176,17 @@ 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: + if isGeneric(x.typ) { + intro = " of parameterized type " + } else { intro = " of type " } buf.WriteString(intro) WriteType(&buf, x.typ, qf) + if tpar, _ := x.typ.(*TypeParam); tpar != nil { + buf.WriteString(" constrained by ") + WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here + } } else { buf.WriteString(" with invalid type") } @@ -249,46 +250,61 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er V := x.typ // x's type is identical to T - if check.identical(V, T) { + if Identical(V, T) { return true, 0 } - Vu := optype(V) - Tu := optype(T) + Vu := under(V) + Tu := under(T) + Vp, _ := V.(*TypeParam) + Tp, _ := T.(*TypeParam) // 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 { - // TODO(gri) this could probably be more efficient - ok, _ := x.assignableTo(check, t, reason) - return ok + 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 + } + // 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 check.identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { + // 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 - if Ti, ok := Tu.(*Interface); ok { - if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { + // T is an interface type and x implements T and T is not a type parameter + 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 wrongType != nil { - if check.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 @@ -296,15 +312,91 @@ 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) { + 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 { + 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 + // 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) { - return !isNamed(V) || !isNamed(T), _InvalidChanAssign + if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) { + return !hasName(V) || !hasName(T), _InvalidChanAssign } } + // optimization: if we don't have type parameters, we're done + if Vp == nil && Tp == nil { + return false, _IncompatibleAssign + } + + errorf := func(format string, args ...interface{}) { + if check != nil && reason != nil { + msg := check.sprintf(format, args...) + if *reason != "" { + msg += "\n\t" + *reason + } + *reason = msg + } + } + + // 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 to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true + }) + 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 := 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 (in %s) to %s", V.typ, Vp, T) + return false + } + return true + }) + return ok, code + } + return false, _IncompatibleAssign } diff --git a/src/cmd/compile/internal/types2/package.go b/src/cmd/compile/internal/types2/package.go index 31b1e7178771f5db37264b4886b8b3604e03b4b3..8044e7e6a76ce25254bcacab3599d547698e64a6 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,13 +39,22 @@ 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 } // 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. diff --git a/src/cmd/compile/internal/types2/pointer.go b/src/cmd/compile/internal/types2/pointer.go new file mode 100644 index 0000000000000000000000000000000000000000..63055fc6b056a76822d261a2913b502f9fab2476 --- /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/predicates.go b/src/cmd/compile/internal/types2/predicates.go index ae186a0b5d1efd402335101d6caa125ff277c3a2..cf2993f68b08b15e0258a8ff367a85a312b85a51 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -6,80 +6,98 @@ 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 { - switch typ.(type) { - case *Basic, *Named, *TypeParam, *instance: - return true - } - return false +// 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 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) } +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., +// 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 } -// 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.tparams != nil && named.targs == nil +// 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(structuralType(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) } +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(structuralType(t), info). +func allBasic(t Type, info BasicInfo) bool { + if tpar, _ := t.(*TypeParam); tpar != nil { + return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) + } + return isBasic(t, info) } -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) }) +// 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 } -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 list 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 +// 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 Basic()! - // 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 + // set up. Must not call under()! + 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 isOrdered(typ Type) bool { return is(typ, IsOrdered) } +// IsInterface reports whether t is an interface type. +func IsInterface(t Type) bool { + _, ok := under(t).(*Interface) + return ok +} -func isConstType(typ Type) bool { - // Type parameters are never const types. - t, _ := under(typ).(*Basic) - return t != nil && t.info&IsConstType != 0 +// isTypeParam reports whether t is a type parameter. +func isTypeParam(t Type) bool { + _, ok := t.(*TypeParam) + return ok } -// IsInterface reports whether typ is an interface type. -func IsInterface(typ Type) bool { - return asInterface(typ) != nil +// 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. @@ -96,24 +114,12 @@ 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), - // T is comparable if it has the == method. Otherwise, - // the underlying type "wins". For instance - // - // interface{ comparable; type []byte } - // - // is not comparable because []byte is not comparable. - 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 return t.kind != UntypedNil - case *Pointer, *Interface, *Chan: + case *Pointer, *Chan: return true case *Struct: for _, f := range t.fields { @@ -124,42 +130,27 @@ 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 { - return comparable(t, seen) - } - return t.is(pred) - case *TypeParam: - return t.Bound().IsComparable() + case *Interface: + return !isTypeParam(T) || t.IsComparable() } return false } -// hasNil reports whether a type includes the nil value. -func hasNil(typ Type) bool { - switch t := optype(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 - case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: + return u.kind == UnsafePointer + case *Slice, *Pointer, *Signature, *Map, *Chan: return true - case *Sum: - return t.is(hasNil) + case *Interface: + return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool { + return u != nil && hasNil(u) + }) } 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 @@ -171,11 +162,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 { - // types must be expanded for comparison - x = expandf(x) - y = expandf(y) - +func identical(x, y Type, cmpTags bool, p *ifacePair) bool { if x == y { return true } @@ -195,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: @@ -216,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 } } @@ -227,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: @@ -238,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 } } @@ -248,57 +235,79 @@ func (check *Checker) identical0(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 && - check.identicalTParams(x.tparams, y.tparams, cmpTags, p) && - check.identical0(x.params, y.params, cmpTags, p) && - check.identical0(x.results, y.results, cmpTags, p) + y, _ := y.(*Signature) + if y == nil { + return false } - 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 - // 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) { - // 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) { - continue L // x is in y.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, 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 } - return false // x is not in y.types } - return true + + 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) + 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: + // // 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 { - // 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) + xset := x.typeSet() + yset := y.typeSet() + if !xset.terms.equal(yset.terms) { + return false } - a := x.allMethods - b := y.allMethods + 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 @@ -335,7 +344,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 } } @@ -346,20 +355,41 @@ 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: // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { + xargs := x.TypeArgs().list() + yargs := y.TypeArgs().list() + + 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. @@ -369,14 +399,6 @@ func (check *Checker) identical0(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 *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 nil: // avoid a crash in case of nil type @@ -387,25 +409,28 @@ 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 { - if len(x) != len(y) { +// 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, x := range x { - y := y[i] - if !check.identical0(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) { + + for i, xa := range xargs { + if !Identical(xa, yargs[i]) { return false } } - return true + + return Identical(xorig, yorig) } // 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] @@ -421,5 +446,5 @@ func Default(typ Type) Type { return Typ[String] } } - return typ + return t } diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go index fa30650bd444f3d995b1939e897783e6ef50b768..a8cb244c55e6095c31bbb68d5dee0d427e35a789 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 { @@ -265,7 +275,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 } @@ -298,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 } } } @@ -398,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 @@ -459,8 +481,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()) @@ -486,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) } } diff --git a/src/cmd/compile/internal/types2/resolver_test.go b/src/cmd/compile/internal/types2/resolver_test.go index aee435ff5fb6cd7e0aa6d0d34028290197e71968..a02abce081b8334e3bb57bb0444ff6bced209e79 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 { diff --git a/src/cmd/compile/internal/types2/return.go b/src/cmd/compile/internal/types2/return.go index 204e456a916fb127e02b3fa9aee0f6c41cd5971b..6c3e1842ce7d715b93d350ff58cc1e3738e4cf0d 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/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go deleted file mode 100644 index 64a2dedc7d83d9972af155599757891b41e8a549..0000000000000000000000000000000000000000 --- a/src/cmd/compile/internal/types2/sanitize.go +++ /dev/null @@ -1,202 +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, *bottom, *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 *Sum: - s.typeList(t.types) - - 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 { - t.allTypes = allTypes - } - - 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 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/cmd/compile/internal/types2/scope.go b/src/cmd/compile/internal/types2/scope.go index ade0a79b31d11daf4fab28c7094d15b8175f22b7..095875d94b0d9ecec9d318d6456a0420abbd7442 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 @@ -22,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 @@ -31,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 } @@ -66,7 +69,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 +84,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 +98,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 +139,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 +219,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 +237,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/self_test.go b/src/cmd/compile/internal/types2/self_test.go index 4722fec9889f0f53670daef90d75f537962f378e..9a01ccdf7a28bbce7903885bf51e36feaa4ab374 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) } } @@ -38,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) { diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go new file mode 100644 index 0000000000000000000000000000000000000000..06dcd9131a42566763e9784190802b37913150ed --- /dev/null +++ b/src/cmd/compile/internal/types2/signature.go @@ -0,0 +1,339 @@ +// Copyright 2021 The Go Authors. 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 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 *TypeParamList // receiver type parameters from left to right, or nil + tparams *TypeParamList // type parameters from left to right, or nil + 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 + variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) +} + +// 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 { + panic("variadic function must have at least one parameter") + } + if _, ok := params.At(n - 1).typ.(*Slice); !ok { + panic("variadic parameter must be of unnamed slice type") + } + } + 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 +// 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 } + +// 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 } + +// 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 + +// 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() + + 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 { + 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 == "_" { + tpar := sig.rparams.At(i) + if check.recvTParamMap == nil { + check.recvTParamMap = make(map[*syntax.Name]*TypeParam) + } + check.recvTParamMap[p] = tpar + } + } + // determine receiver type to get its type parameters + // and the respective type parameter bounds + 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 + // 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.TypeParams().list() + } + } + // provide type parameter bounds + // - only do this if we have the right number (otherwise an error is reported elsewhere) + if sig.RecvTypeParams().Len() == len(recvTParams) { + // We have a list of *TypeNames but we need a list of Types. + 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() { + bound := recvTParams[i].bound + // bound is (possibly) parameterized in the context of the + // receiver type declaration. Substitute parameters for the + // current context. + tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil) + } + } + } + } + + if tparams != nil { + 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.) + 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}, false) // use rewritten receiver type, if any + } + 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()) + 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) + + // 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 rtyp != Typ[Invalid] { + var err string + switch T := rtyp.(type) { + case *Named: + 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 { + 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." + 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 { + // 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 + } + return true + }) + } + 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 = "" + } + default: + 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. +func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, 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 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 +} diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 236feb0404ebbd84d894690d7227a352a29ba896..99b846b80b91c1f355777331ca012ce54ee7f405 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -26,30 +26,29 @@ func TestSizeof(t *testing.T) { {Struct{}, 24, 48}, {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, - {Signature{}, 44, 88}, - {Sum{}, 12, 24}, - {Interface{}, 60, 120}, + {Signature{}, 28, 56}, + {Union{}, 16, 32}, + {Interface{}, 44, 88}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 68, 136}, + {Named{}, 68, 128}, {TypeParam{}, 28, 48}, - {instance{}, 52, 96}, - {bottom{}, 0, 0}, - {top{}, 0, 0}, + {term{}, 12, 24}, // Objects {PkgName{}, 64, 104}, {Const{}, 64, 104}, {TypeName{}, 56, 88}, {Var{}, 60, 96}, - {Func{}, 60, 96}, + {Func{}, 64, 104}, {Label{}, 60, 96}, {Builtin{}, 60, 96}, {Nil{}, 56, 88}, // Misc - {Scope{}, 56, 96}, + {Scope{}, 60, 104}, {Package{}, 40, 80}, + {_TypeSet{}, 28, 56}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index aa0fbf40fced43115bd43e899920214bd11e5b47..6f981964be1afdfdaf9ac2d64918cbdbb4a73bb7 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." @@ -67,12 +67,17 @@ func (s *StdSizes) Alignof(T Type) int64 { case *Slice, *Interface: // Multiword data structures are effectively structs // in which each element has size WordSize. + // 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. 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 +123,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 +153,13 @@ 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 *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() } return s.WordSize // catch-all } @@ -241,7 +249,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/slice.go b/src/cmd/compile/internal/types2/slice.go new file mode 100644 index 0000000000000000000000000000000000000000..9c22a6fb1b6853f06a03fa0c0f7967aeed1b1aeb --- /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/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index cde35c17b6f717f97dd3781f914ee0fcfe0afc99..551611da552454ecf10757d9618d7da389976980 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 ) } @@ -192,6 +194,10 @@ 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 + "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 ) } @@ -215,7 +221,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 } diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index c3e646c80c142d91434991bc5f37d57ab20d4225..ab64882c0273a2c197f4c38fa46ab1810f8d244e 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 { @@ -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, @@ -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) @@ -64,7 +59,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) } @@ -174,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: @@ -255,7 +251,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") @@ -268,24 +264,38 @@ 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) 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 { - Ts = T.String() + Ts = TypeString(T, check.qualifier) } var err error_ err.errorf(e, "duplicate case %s in type switch", Ts) @@ -296,12 +306,53 @@ L: } seen[T] = e if T != nil { - check.typeAssertion(e.Pos(), x, xtyp, T) + check.typeAssertion(e, x, xtyp, T, true) } } 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, x, xtyp, T, true) +// } +// } +// 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 @@ -335,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: @@ -351,25 +402,27 @@ 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) + u := structuralType(ch.typ) + if u == nil { + check.errorf(s, invalidOp+"cannot send to %s: no structural type", &ch) return } - - if tch.dir == RecvOnly { - check.errorf(s, invalidOp+"cannot send to receive-only type %s", tch) + uch, _ := u.(*Chan) + if uch == nil { + check.errorf(s, invalidOp+"cannot send to non-channel %s", &ch) return } - - check.assignment(&x, tch.elem, "send") + 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) @@ -384,7 +437,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 } @@ -413,7 +466,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" @@ -441,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") @@ -498,7 +550,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) @@ -587,7 +639,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") } } @@ -596,9 +648,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) @@ -684,16 +733,16 @@ 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 } - check.ordinaryType(x.Pos(), xtyp) check.multipleSwitchDefaults(s.Body) @@ -780,19 +829,28 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s // determine key/value types var key, val Type if x.mode != invalid { - 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 + // 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 = 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) + // 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 } } @@ -873,71 +931,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) { - switch typ := typ.(type) { +// 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, "" - case *Pointer: - if typ := asArray(typ.base); typ != nil { - 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 *Sum: - first := true - var key, val Type - var msg string - typ.is(func(t Type) bool { - k, v, m := rangeKeyVal(under(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 - } - return nil, nil, "" + return typ.elem, Typ[Invalid] + } + return } diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go new file mode 100644 index 0000000000000000000000000000000000000000..31a3b1af5bc338bbbf015cd53fefe17bea8d47e6 --- /dev/null +++ b/src/cmd/compile/internal/types2/struct.go @@ -0,0 +1,225 @@ +// Copyright 2021 The Go Authors. 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" +) + +// ---------------------------------------------------------------------------- +// API + +// A Struct represents a struct type. +type Struct struct { + 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 +} + +// 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") + } + s := &Struct{fields: fields, tags: tags} + s.markComplete() + return s +} + +// 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 (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 + } + + // 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 u := under(t).(type) { + case *Basic: + if t == Typ[Invalid] { + // error was reported before + return + } + // unsafe.Pointer is treated like a regular pointer + 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 *Interface: + if 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") + } + } + }).describef(embeddedPos, "check embedded type %s", embeddedTyp) + } + } + + styp.fields = fields + styp.tags = tags + styp.markComplete() +} + +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/subst.go b/src/cmd/compile/internal/types2/subst.go index c8e428c1832311bed33fa8abf7965a01c3dce2a4..516f2481279597af6dd9137b169097b21f7ce603 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -2,215 +2,43 @@ // 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 -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 -} +import "cmd/compile/internal/syntax" + +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(map[*TypeParam]Type, len(tpars)) + proj := make(substMap, 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] = targs[i] } - return &substMap{targs, proj} + return proj } -func (m *substMap) String() string { - return fmt.Sprintf("%s", m.proj) +func (m substMap) empty() bool { + return len(m) == 0 } -func (m *substMap) empty() bool { - return len(m.proj) == 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 } -func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslist []syntax.Pos) (res Type) { - if 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: - check.dump("%v: cannot instantiate %v", pos, typ) - unreachable() // only defined types and (defined) functions can be generic - - } - - // 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 len(tparams) == 0 { - return typ // nothing to do (minor optimization) - } - - smap := makeSubstMap(tparams, targs) - - // 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(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 - } - } - - // targ's underlying type must also be one of the interface types listed, if any - if iface.allTypes == nil { - continue // 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 - } - } - 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) - break - } - } - - return check.subst(pos, typ, smap) -} - -// 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 +// 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 the incoming type. -func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap) 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 } @@ -224,15 +52,20 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap) Type { } // general case - subst := subster{check, pos, make(map[Type]Type), smap} + subst := subster{ + pos: pos, + smap: smap, + check: check, + ctxt: check.bestContext(ctxt), + } return subst.typ(typ) } type subster struct { - check *Checker pos syntax.Pos - cache map[Type]Type - smap *substMap + smap substMap + check *Checker // nil if called via Instantiate + ctxt *Context } func (subst *subster) typ(typ Type) Type { @@ -241,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, *bottom, *top: + case *Basic: // nothing to do case *Array: @@ -258,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: @@ -279,10 +114,9 @@ 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? - tparams: t.tparams, - scope: t.scope, + // TODO(gri) why can't we nil out tparams here, rather than in instantiate? + tparams: t.tparams, + // instantiated signatures have a nil scope recv: recv, params: params, results: results, @@ -290,29 +124,20 @@ func (subst *subster) typ(typ Type) Type { } } - case *Sum: - types, copied := subst.typeList(t.types) + case *Union: + terms, copied := subst.termlist(t.terms) 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) + // 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: 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 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) + if mcopied || ecopied { + iface := &Interface{methods: methods, embeddeds: embeddeds, implicit: t.implicit, complete: t.complete} return iface } @@ -342,77 +167,69 @@ func (subst *subster) typ(typ Type) Type { } } - if t.tparams == nil { + // 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 new_targs []Type - - if len(t.targs) > 0 { - // already instantiated - dump(">>> %s already instantiated", t) - 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. - 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, len(t.tparams)) - copy(new_targs, t.targs) - } - new_targs[i] = new_targ + var newTArgs []Type + if t.targs.Len() != t.orig.TypeParams().Len() { + return Typ[Invalid] // error reported elsewhere + } + + // 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.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.orig.TypeParams().Len()) + copy(newTArgs, t.targs.list()) } + 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 := subst.ctxt.instanceHash(t.orig, 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 := subst.ctxt.lookup(h, t.orig, newTArgs); named != nil { + dump(">>> found %s", named) + return named } - // 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.targs = new_targs - if subst.check != nil { - subst.check.typMap[h] = named - } - subst.cache[t] = named - - // do the substitution - dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, new_targs) - named.underlying = subst.typOrNil(t.underlying) - named.fromRHS = named.underlying // for cycle detection (Checker.validType) + // 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.ctxt) + return subst.check.instance(subst.pos, t.orig, newTArgs, subst.ctxt) - return named + // 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. 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() } @@ -420,37 +237,6 @@ func (subst *subster) typ(typ Type) Type { return typ } -// TODO(gri) Eventually, this should be more sophisticated. -// It won't work correctly for locally declared types. -func instantiatedHash(typ *Named, targs []Type) string { - var buf bytes.Buffer - writeTypeName(&buf, typ.obj, nil) - buf.WriteByte('[') - writeTypeList(&buf, targs, nil, nil) - buf.WriteByte(']') - - // 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++ - } - } - - 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. @@ -545,3 +331,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] = NewTerm(t.tilde, u) + } + } + return +} diff --git a/src/cmd/compile/internal/types2/termlist.go b/src/cmd/compile/internal/types2/termlist.go new file mode 100644 index 0000000000000000000000000000000000000000..844e39e3bf4ae275c76cb98eef96fbff35cb17c1 --- /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 + +// 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, +// 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 + } + 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 0000000000000000000000000000000000000000..1bdf9e13860abc413aa7af9961449b4abe2e1643 --- /dev/null +++ b/src/cmd/compile/internal/types2/termlist_test.go @@ -0,0 +1,313 @@ +// Copyright 2021 The Go Authors. 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.ReplaceAll(s, " ", "") + names := strings.Split(s, "∪") + r := make(termlist, len(names)) + for i, n := range names { + r[i] = testTerm(n) + } + return r +} + +func TestTermlistAll(t *testing.T) { + if !allTermlist.isAll() { + t.Errorf("allTermlist is not the set of all types") + } +} + +func TestTermlistString(t *testing.T) { + for _, want := range []string{ + "∅", + "𝓤", + "int", + "~int", + "myInt", + "∅ ∪ ∅", + "𝓤 ∪ 𝓤", + "∅ ∪ 𝓤 ∪ int", + "∅ ∪ 𝓤 ∪ int ∪ myInt", + } { + 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, + "∅ ∪ ∅ ∪ myInt": false, + "𝓤": false, + "𝓤 ∪ int": false, + "𝓤 ∪ myInt ∪ ∅": false, + } { + xl := maketl(test) + got := xl.isEmpty() + if got != want { + t.Errorf("(%v).isEmpty() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistIsAll(t *testing.T) { + for test, want := range map[string]bool{ + "∅": false, + "∅ ∪ ∅": false, + "int ∪ ~string": false, + "~int ∪ myInt": false, + "∅ ∪ ∅ ∪ 𝓤": true, + "𝓤": true, + "𝓤 ∪ int": true, + "myInt ∪ 𝓤": true, + } { + xl := maketl(test) + got := xl.isAll() + if got != want { + t.Errorf("(%v).isAll() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistNorm(t *testing.T) { + for _, test := range []struct { + xl, want string + }{ + {"∅", "∅"}, + {"∅ ∪ ∅", "∅"}, + {"∅ ∪ 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() + if got.String() != test.want { + t.Errorf("(%v).norm() = %v; want %v", xl, got, test.want) + } + } +} + +func TestTermlistSingleType(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", + "myInt": "myInt", + "~int": "int", + "~int ∪ string": "nil", + "~int ∪ myInt": "int", + "∅ ∪ int": "int", + "∅ ∪ ~int": "int", + "∅ ∪ ~int ∪ string": "nil", + } { + xl := maketl(test) + got := tstring(xl.singleType()) + if got != want { + t.Errorf("(%v).singleType() == %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", "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) + 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", "∅"}, + {"∅", "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) + 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}, + {"𝓤 ∪ myInt", "string ∪ 𝓤", true}, + {"int ∪ ~string", "string ∪ int", false}, + {"~int ∪ string", "string ∪ myInt", 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", "myInt", true}, + {"int ∪ string", "string", true}, + {"~int ∪ string", "int", true}, + {"~int ∪ string", "myInt", true}, + {"~int ∪ myInt ∪ ∅", "myInt", true}, + {"myInt ∪ ∅ ∪ 𝓤", "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}, + {"𝓤", "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 ∪ ∅ ∪ 𝓤", "myInt", 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", "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}, + {"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) + got := xl.subsetOf(yl) + if got != test.want { + t.Errorf("(%v).subsetOf(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index 3918d836b5277a8a71d46380b441b1a29d409bd7..48a39891bf85874821e6b77fc24504b8a9c6d9ff 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -6,48 +6,269 @@ package builtins -type Bmc interface { - type map[rune]string, chan int +import "unsafe" + +// 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) } -type Bms interface { - type map[string]int, []int +func _[T C5[X], X any](ch T) { + close(ch) } -type Bcs interface { - type chan bool, []float64 +// copy + +func _[T any](x, y T) { + copy(x /* ERROR copy expects slice arguments */ , y) } -type Bss interface { - type []int, []string +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 any] () { - _ = make(T /* ERROR invalid argument */ ) - _ = make(T /* ERROR invalid argument */ , 10) - _ = make(T /* ERROR invalid argument */ , 10, 20) +func _[T ~[]E, E any](x T, y []E) { + copy(x, y) + copy(x /* ERROR different element types */ , "foo") } -func _[T Bmc] () { - _ = make(T) - _ = make(T, 10) - _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20) +func _[T ~string](x []byte, y T) { + copy(x, y) + copy(y /* ERROR expects slice arguments */ , x) } -func _[T Bms] () { - _ = make /* ERROR expects 2 arguments */ (T) - _ = make(T, 10) - _ = make /* ERROR expects 2 arguments */ (T, 10, 20) +func _[T ~[]byte|~string](x T, y []byte) { + copy(x /* ERROR expects slice arguments */ , y) + copy(y, x) } -func _[T Bcs] () { - _ = make /* ERROR expects 2 arguments */ (T) - _ = make(T, 10) - _ = make /* ERROR expects 2 arguments */ (T, 10, 20) +type L0 []int +type L1 []int + +func _[T L0 | L1](x, y T) { + copy(x, y) } -func _[T Bss] () { - _ = make /* ERROR expects 2 or 3 arguments */ (T) - _ = make(T, 10) - _ = make(T, 10, 20) +// 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 myChan chan int + +func _[ + S1 ~[]int, + S2 ~[]int | ~chan int, + + M1 ~map[string]int, + M2 ~map[string]int | ~chan int, + + C1 ~chan int, + C2 ~chan int | ~chan string, + C3 chan int | myChan, // single underlying type +]() { + 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 S2: 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 M2: 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 C2: no structural type */ ) + _ = make(C3) +} + +// 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/check/builtins.src b/src/cmd/compile/internal/types2/testdata/check/builtins.src index 6d1f47129b9c16d2935a66c6eb97a740550041ae..de27f5c6322132acbddfd8dc7d84b3fa44e923e7 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) @@ -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/testdata/check/compliterals.go2 b/src/cmd/compile/internal/types2/testdata/check/compliterals.go2 new file mode 100644 index 0000000000000000000000000000000000000000..60eac97a3f2084ef2e58302f79ecd25bc7c19211 --- /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}} +} diff --git a/src/cmd/compile/internal/types2/testdata/check/const0.src b/src/cmd/compile/internal/types2/testdata/check/const0.src index 5608b1549ba8d7774c2463fa9faab3702673f061..3cffdf904c87feb265ee5b1293d07be185e17372 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/cycles.src b/src/cmd/compile/internal/types2/testdata/check/cycles.src index b2ee8ecd5f6001076e336779a9b5150c1e524162..998f9f7da980116ccbae32f6fb796766fe4c19fa 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/testdata/check/cycles4.src b/src/cmd/compile/internal/types2/testdata/check/cycles4.src index 445babca68bc3db73a1cc192f366480171fbc659..924aabf475f9640cdfa6da8834fa9a8db6aa0a2b 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/testdata/check/decls0.src b/src/cmd/compile/internal/types2/testdata/check/decls0.src index e78d8867e0995b38ae8d2d936143937839a5a808..09e5d5c5ad84355af0bdea8552b1de283b5cf256 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" @@ -146,7 +146,7 @@ type ( m1(I5) } I6 interface { - S0 /* ERROR "not an interface" */ + S0 /* ERROR "non-interface type S0" */ } I7 interface { I1 @@ -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 { diff --git a/src/cmd/compile/internal/types2/testdata/check/decls1.src b/src/cmd/compile/internal/types2/testdata/check/decls1.src index e6beb7835897bc12ae90eed4c1007b956ac33a21..1167ced366e2bff73453c5bf09559c54c8f0ece4 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/errors.src b/src/cmd/compile/internal/types2/testdata/check/errors.src index ff929217c4c865ae18f8b918ee720762f15cf3cc..5f09197bde0f27d56ec3abb0543facc3261d1417 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/expr1.src b/src/cmd/compile/internal/types2/testdata/check/expr1.src index 4ead815158f61e2dbbb91dec8e7feabef4a3923c..85ad234bbbf46833d33c6328b38192c5a9bd88d4 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 0c959e8011944f0ce42b89bc193e448628bc762f..8e5862319e650b9dc3afbae66435516471bfaef1 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 @@ -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/src/cmd/compile/internal/types2/testdata/check/expr3.src b/src/cmd/compile/internal/types2/testdata/check/expr3.src index eab3f72c4d5ff0d323151f3c3b9feff11cf29de3..646319e4c470713b760ca5068cc54f7c313e07a8 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 @@ -104,14 +104,14 @@ 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] _ = 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 @@ -459,7 +459,7 @@ func type_asserts() { var t I _ = t /* ERROR "use of .* outside type switch" */ .(type) - _ = t /* ERROR "missing method m" */ .(T) + _ = t /* ERROR "method m has pointer receiver" */ .(T) _ = t.(*T) _ = t /* ERROR "missing method m" */ .(T1) _ = t /* ERROR "wrong type for method m" */ .(T2) @@ -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/tinference.go2 b/src/cmd/compile/internal/types2/testdata/check/funcinference.go2 similarity index 58% rename from src/cmd/compile/internal/types2/testdata/check/tinference.go2 rename to src/cmd/compile/internal/types2/testdata/check/funcinference.go2 index a53fde0a2a944decd986e8a1046e2be71865a376..7160e18b19c51cc717c287efbc98ed88cabf1df6 100644 --- a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/funcinference.go2 @@ -2,42 +2,43 @@ // 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{} -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") + f("a", nil, nil, nil) + f0("a", nil, nil, nil) } -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)) + f(int(0), new(int)) + f1(int(0), new(int)) } -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 _() { - 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{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,26 +46,24 @@ 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 { panic(0) } 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 { panic(0) } func _() { x := f6(struct{f []string}{}) 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{type A}]() +func f7[A interface{*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 +79,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/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index 1c73b5da9219c04c1b2a479f594fc7d315ab3948..76f9cc5010af6d1879faeb843641edd01c674c17 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -24,25 +24,23 @@ 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() }]() +func f2[_ interface{ m1(); m2() }]() {} type T struct{} func (T) m1() @@ -57,15 +55,15 @@ 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 */ ]{} + _ = T1[P /* ERROR empty interface P does not implement interface{~uint} */ ]{} } // This is the original (simplified) program causing the same issue. type Unsigned interface { - type uint + ~uint } type T2[U Unsigned] struct { @@ -76,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 empty interface U does not implement Unsigned */ ] { + return T2[U /* ERROR empty interface U does not implement Unsigned */ ]{} } func _() { @@ -147,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 @@ -156,7 +154,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 +166,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 +180,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 +201,31 @@ 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() +} + +type F1 func() +type F2 func() +func _[T interface{ func()|F1|F2 }](f T) { f() go f() } @@ -232,9 +237,9 @@ 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{ type T }](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 @@ -242,7 +247,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/issues.src b/src/cmd/compile/internal/types2/testdata/check/issues.src index 21aa208cc769d2b872dbf1c46cacf1e7ae9d2382..f4b6199b82e53ed556b4daac2b6ee97cc9ff9ea8 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.src +++ b/src/cmd/compile/internal/types2/testdata/check/issues.src @@ -2,11 +2,11 @@ // 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" - syn "cmd/compile/internal/syntax" + syn "regexp/syntax" t1 "text/template" t2 "html/template" ) @@ -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 */ @@ -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 \(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\)" */ () - _ = 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 */ @@ -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{} @@ -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,11 +357,11 @@ 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. - 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/src/cmd/compile/internal/types2/testdata/check/linalg.go2 b/src/cmd/compile/internal/types2/testdata/check/linalg.go2 index 0d27603a5837a2747922d9c1e52802b840ca8c4e..f02e773dbeeeebbafde08ab38ac4cef93f11897a 100644 --- a/src/cmd/compile/internal/types2/testdata/check/linalg.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/linalg.go2 @@ -4,15 +4,13 @@ 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 { - 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,42 +40,43 @@ 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 -} - -// 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 + ~complex64 | ~complex128 } -// 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/main.go2 b/src/cmd/compile/internal/types2/testdata/check/main.go2 index b7ddeaa1a881b0ec79ac318ff474819fd61ecf3e..395e3bfec8076e3eeaf09c7ddebb475d9b69dcc2 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/map2.go2 b/src/cmd/compile/internal/types2/testdata/check/map2.go2 index 2833445662de813d6d3eeed95978c8342316b29f..be2c49f621efeff4b22a42ca683a5084224a210a 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 c2f282bae11a9817620365e445a9bc8b3f3b310f..1b406593f888a47fc8eb7682c142c9725402a9bc 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/stmt0.src b/src/cmd/compile/internal/types2/testdata/check/stmt0.src index bedcbe5fce3573f8aea5c8c8b2fb73786c0a9b17..8b18d676ac258513eb68f2a7a254219c3b7ff606 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() { @@ -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< 0 { x0 = x[0] @@ -118,9 +118,9 @@ func max[T interface{ type 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 b47ce75805480539dcdf5fbef2ff350f6fc9cafe..0732f06a39ab1c6afb9862771052cc610fcecf97 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/inference.go2 @@ -7,10 +7,10 @@ package p type Ordered interface { - type int, float64, string + ~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{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. @@ -97,5 +97,28 @@ 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 + +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/testdata/examples/methods.go2 b/src/cmd/compile/internal/types2/testdata/examples/methods.go2 index 76c6539e1b7e7de019b7031025274eee082be8d7..1d76d553dcc44a1b57f2f983edefa404c39ab534 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/methods.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/methods.go2 @@ -94,3 +94,19 @@ func (_ T2[_, _, _]) _() int { return 42 } type T0 struct{} func (T0) _() {} func (T1[A]) _() {} + +// 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/operations.go2 b/src/cmd/compile/internal/types2/testdata/examples/operations.go2 new file mode 100644 index 0000000000000000000000000000000000000000..18e4d6080c59f0307c55e94bf389e4109eb88a7f --- /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 +} diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index a7825ed2d9bf7c421c23c9fb78549ce889d2fe91..077fcfdbb76119caf45f104d6751e648347512b7 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. @@ -113,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 { @@ -155,31 +156,42 @@ 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(); type 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 +// } + +// 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 @@ -202,19 +214,19 @@ 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]]() -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 @@ -232,11 +244,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 */ ) @@ -264,10 +276,10 @@ 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 { type int, float64 }]() { +func _[T interface{~int|~float64}]() { // not valid const _ = T /* ERROR not constant */ (0) const _ T /* ERROR invalid constant type T */ = 1 @@ -277,3 +289,27 @@ func _[T interface { type 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}, {}} +} + +// 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/testdata/examples/typesets.go2 b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 new file mode 100644 index 0000000000000000000000000000000000000000..e19dcf8da378f3e1f4b1748d5a46ec092c057c0e --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/examples/typesets.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. + +// 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 */ ]() {} +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.) +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/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 index 2c1299feb09519d7499d09d937abf4abfb3f00bd..9a98f7f955e8c24e3e2eaf4d0ead54099a96c51c 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 @@ -31,13 +31,14 @@ type x7[A any] struct{ foo7 } func main7() { var _ foo7 = x7[int]{} } // crash 8 -type foo8[A any] interface { type 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 { type foo9 /* ERROR interface contains type constraints */ [A] } -func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [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 */ @@ -49,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() } @@ -57,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 _ */ ]) @@ -73,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 @@ -84,8 +86,8 @@ 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 */ } +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/issue39680.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 index 9bc26f35461345eb2f0d5728ba39fe793774723d..e56bc3547582d190f110b6f70a231e9e38012572 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 @@ -4,16 +4,19 @@ package p +// Embedding stand-alone type parameters is not permitted for now. Disabled. + +/* 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) { @@ -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/issue39693.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39693.go2 index 316ab1982e89cf3635b1b1b16b3356f70a4d2b4f..301c13be41cce2b5fce7cec228cac0d9f1504f63 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/issue39699.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39699.go2 index 75491e7e26f00cd5b1d0ce771d471724ae7cdf9e..72f83997c2460a5496556cb1d294b9e260550c5d 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/issue39711.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 index df621a4c1730db66648dd23c898a1238bdfce332..8f3101235410c091910641c928113718e66d2bc4 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 @@ -4,8 +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 { - 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 term 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 55464e6b7759f09016050e541868a72b50e1dca1..00885238e69c9a26ce5ef6f44539c0cba86152b1 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{ ~int }, B A /* ERROR cannot use a type parameter as constraint */ ]() {} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39725.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39725.go2 index e19b6770bfe4bd21462434f97ace29659a02c4ed..62dc45a59601eecc43e0b23fd09123cf00fbf57d 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/issue39754.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 index f70b8d0ce0388757004f3797bac5cae749429177..9edd239d7d97c2e3e00bd6031327f180939494b0 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 @@ -16,8 +16,6 @@ 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]] - // 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 /* ERROR does not implement Box */ [string]] + _ = f[int, Optional[int], Optional /* ERROR Optional.* does not implement Box.* */ [string]] } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39755.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39755.go2 index b7ab68818e9587897e7f916730644a3dc1f0af8b..257b73a2fbeff15a934f4daf4798952578bad9d5 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/issue39768.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 index abac141d7f08dd359a26ba18c36b696d7970d40a..696d9d9beef9d2f9961456e1ddf3ed6f31c51889 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 @@ -4,17 +4,18 @@ package p -type T[P any] P -type A = T -var x A[int] -var _ A /* ERROR cannot use generic type */ - -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 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/issue39938.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 index 76e7e369ca12bb6718272a2de41dfc7f6617d848..114646786d5b74324413b74cbbca0c211f3c6cb2 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 @@ -3,19 +3,21 @@ // 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 -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 } +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/issue39948.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 index c2b460902cc643b5537834e489f3213f551fe6f7..e38e57268d63d1fd00012274bd8ea23bc2a7c7df 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 @@ -5,5 +5,5 @@ 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/issue39976.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39976.go2 index 3db4eae0123930db81b5ff193e58ff802678878a..d703da90a2176a3e975f5a62cad5cf5b3f665faf 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 8948d61caa477fff40ac7f773946d0377df734e4..0981a335da3aa91cc12538ddc976f1e34e428e6d 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 747aab49dd1639b79bbf7eb0efcf84787b337c4c..a3f3eecca098c6dbbace1dbc19eee13069484b6c 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/issue40301.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40301.go2 index 5d97855f8a172ff414ae86c5112b500059a3142b..c78f9a1fa040892e7ebec27753100db2867752b2 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) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40684.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40684.go2 index 0269c3a62ce6d0d10d92f0f2cb4e0ce8e82129cf..58d0f69f6503164328feb8990baa1d4bbf201c52 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/issue40789.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40789.go2 new file mode 100644 index 0000000000000000000000000000000000000000..9eea4ad60a6647380606f70fd998febab618db8c --- /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/testdata/fixedbugs/issue41124.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 index 61f766bcbd7891ef16f8ca6396349e1ff43159f6..7f55ba85a6b42d4580a030337e5bba3e1da71713 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 @@ -6,13 +6,13 @@ package p // Test case from issue. -type Nat interface { - type Zero, Succ +type Nat /* ERROR cycle */ interface { + Zero|Succ } 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. @@ -22,7 +22,7 @@ type I1 interface { } type I2 interface { - type int + ~int } type I3 interface { @@ -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{} @@ -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/issue42758.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue42758.go2 index 698cb8a16bad26194a40f5893e7a1d493b30083c..dd66e9648b56326f364b4ade15b459a506a5bb9d 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{}){ @@ -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/testdata/fixedbugs/issue43527.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2 new file mode 100644 index 0000000000000000000000000000000000000000..e4bcee51fe5f90420af7c385a53e748f485a4edc --- /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/testdata/fixedbugs/issue43671.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 new file mode 100644 index 0000000000000000000000000000000000000000..46ac51ebdd2df27b2007ce66c953b460e693c4e8 --- /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 ch .* no structural type +} + +func _[T C0](ch T) { + <-ch // ERROR cannot receive from non-channel ch +} + +func _[T C1](ch T) { + <-ch +} + +func _[T C2](ch T) { + <-ch +} + +func _[T C3](ch T) { + <-ch // ERROR cannot receive from ch .* no structural 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 +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2 index b1e42497e8586c500d11985f0df6c70249927949..b8ba0ad4a70915b4edaca42bb24ca60f1088a2bd 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/issue45550.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45550.go2 new file mode 100644 index 0000000000000000000000000000000000000000..3eeaca0957a9bd54ee9dfcdd253e68d6a37f3fd9 --- /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 /* ERROR illegal cycle */ [T interface{ struct{ Builder[T] } }] struct{} +type myBuilder struct { + Builder[myBuilder] +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 index 65662cdc7662938f72e41f4770149277cbdaedda..29379591057a6148a38cc0ff6ede246c527ee79e 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 + ~[]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/testdata/fixedbugs/issue45639.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.go2 new file mode 100644 index 0000000000000000000000000000000000000000..80148fe4819862f4761eb439da062e735204aa20 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.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 + +// 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/issue45920.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 new file mode 100644 index 0000000000000000000000000000000000000000..b113e104bc8e5ee5f84608aa287101965a6671ae --- /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 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 implement chan int\|chan<- int */ ch) } +func _(ch chan<- int) { f2(ch) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 index 7678e348ef99ce2733eaa741fcd3e3b1d13e0e46..cea8c1498321c7182c490d262cd9b4f58a03190f 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 "type S = S does not match" */ interface{ type []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/cmd/compile/internal/types2/testdata/fixedbugs/issue46090.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46090.go2 new file mode 100644 index 0000000000000000000000000000000000000000..81b31974c8dc0207e0833d51c845b978ce26cef4 --- /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/testdata/fixedbugs/issue46275.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46275.go2 new file mode 100644 index 0000000000000000000000000000000000000000..f41ae26e4bdda6fd5815434d0c96887006154a9b --- /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 +} 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 0000000000000000000000000000000000000000..4432402a300e9a4cec961fa762d81d0b6317c6d0 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.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 + +// test case 1 +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 /* ERROR illegal cycle */ [T interface{ A[T] }] interface{} + +// test case 3 +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/issue46583.src b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46583.src new file mode 100644 index 0000000000000000000000000000000000000000..da1f1ffbbaf6c2d29054d9d65f9226199e426363 --- /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 +} 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 0000000000000000000000000000000000000000..b184f9b5b7dfbf7255d9bd6587fb78acce371fb6 --- /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/testdata/fixedbugs/issue47115.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 new file mode 100644 index 0000000000000000000000000000000000000000..83a8f3a5da64356cf10b747692018c379e712939 --- /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 ch .* no structural type */ <- 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 cannot send to ch .* no structural type */ <- 0 +} + +func _[T C4](ch T) { + ch <- 0 +} + +func _[T C5[X], X any](ch T, x X) { + ch <- x +} 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 0000000000000000000000000000000000000000..108d600a38a6c9ce9075ca792ab7abf4077f1d8e --- /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/testdata/fixedbugs/issue47411.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 new file mode 100644 index 0000000000000000000000000000000000000000..ce5db0a615ff0622d783efc8d95b28aa8f4110ef --- /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 implement comparable */ )] + _ = f[R /* ERROR empty interface R does not implement comparable */ ] + + _ = g[int] + _ = g[P /* ERROR P does not implement interface{interface{comparable; ~int\|~string} */ ] + _ = g[Q] + _ = 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/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 new file mode 100644 index 0000000000000000000000000000000000000000..6a2e787bf99848bc662654db7b6dd97b55bcec93 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 @@ -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 p + +// 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) { + 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) +} + +// 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 + +// 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/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 new file mode 100644 index 0000000000000000000000000000000000000000..6667ba4fec08551412c380b4cc0a34d413625ca6 --- /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 /* 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 /* 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 /* ERROR illegal cycle */ [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 /* ERROR illegal cycle */ [a Eq[a]] interface { + Equal(that a) bool +} 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 0000000000000000000000000000000000000000..2631118baed94a7f8163693a3f928c95c080a778 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 @@ -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. + +// Parser accepts type parameters but the type checker +// needs to report any operations that are not permitted +// before Go 1.18. + +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 +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 /* 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]{} + _ = 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 +) + +type Ordered constraints /* ERROR using type constraint constraints\.Ordered requires go1\.18 or later */ .Ordered 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 0000000000000000000000000000000000000000..4c4fc2fda8f8a3140ae9f9b540eb5b7a0781f2e2 --- /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/testdata/fixedbugs/issue47968.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go2 new file mode 100644 index 0000000000000000000000000000000000000000..711e50a55a1d5eeb9661ff259a03ea78618dd82e --- /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 // ERROR cannot use generic type + +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 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 0000000000000000000000000000000000000000..2c4b6610fecb69b9f3be3de784631648fa34caf6 --- /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 missing */ m /* ERROR unexpected */ () /* ERROR \) */ { /* ERROR { */ } /* ERROR } */ 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 0000000000000000000000000000000000000000..6c14c78e4c9cfc3a56bf285c8af9a1f929f8fa27 --- /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 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 */ }: + 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/testdata/fixedbugs/issue48018.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48018.go2 new file mode 100644 index 0000000000000000000000000000000000000000..e6ccc6b9be703584177333b01e0d9afc780e7a9d --- /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/cmd/compile/internal/types2/testdata/fixedbugs/issue48048.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48048.go2 new file mode 100644 index 0000000000000000000000000000000000000000..f4013306215ec3aaeb69ff6855132784178e72bd --- /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/cmd/compile/internal/types2/testdata/fixedbugs/issue48082.src b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48082.src new file mode 100644 index 0000000000000000000000000000000000000000..5395154978ebe1864ab02ced4fe56b57110da8db --- /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/cmd/compile/internal/types2/testdata/fixedbugs/issue48083.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48083.go2 new file mode 100644 index 0000000000000000000000000000000000000000..3dae51415df0a2178ca9c2b2206c2dc58f0cda27 --- /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/testdata/fixedbugs/issue48136.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48136.go2 new file mode 100644 index 0000000000000000000000000000000000000000..0ab92df40fabc07b89d7e1ff0f6de1623392bb9e --- /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 */ ) +} 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 0000000000000000000000000000000000000000..e069930c42d99c3caa36a9acff90d60cf6031fa4 --- /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/testdata/fixedbugs/issue48472.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.go2 new file mode 100644 index 0000000000000000000000000000000000000000..2d908f4c8b56c7c6ab799080a5c863bfd5a234d5 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.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 + +func g() { + var s string + 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 +} 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 0000000000000000000000000000000000000000..a3653fa19c09618b6565c51df29555b756549d17 --- /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 /* ERROR illegal cycle */ [U interface{ M() T[U, int] }] int + +type X int + +func (X) M() T[X] { return 0 } 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 0000000000000000000000000000000000000000..c12091be7902f460ee8e3022a94e151f69faeab5 --- /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/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 new file mode 100644 index 0000000000000000000000000000000000000000..870bacd0bd25ab2d368906d091c66e3db1235e39 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.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. + +// 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 */) +} + +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 0000000000000000000000000000000000000000..652f8ce37a3c98ac5bf322135bc9b878467f9728 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.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. + +// This issue is still open. + +package 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 0000000000000000000000000000000000000000..9f4a76851d5dad0ec983630cbb97abf263011f88 --- /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/testdata/fixedbugs/issue48703.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48703.go2 new file mode 100644 index 0000000000000000000000000000000000000000..8a32c1ecf22a3c375abc3ae1f9b5ddf3f85abcb4 --- /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/issue48819.src b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48819.src new file mode 100644 index 0000000000000000000000000000000000000000..9262110ea09e71e96c3494186beaba6c6c5f4db5 --- /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/testdata/fixedbugs/issue48951.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48951.go2 new file mode 100644 index 0000000000000000000000000000000000000000..cf02cc130aa6cb44089d3abedf05734ea6fd0d42 --- /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] } +) 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 0000000000000000000000000000000000000000..d8ff7c8cf46d1b957f72bd8c1a856f693a30c9c3 --- /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 /* ERROR instantiation cycle */ 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() {} 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 0000000000000000000000000000000000000000..ece1a27bb927f4bdf9b14a8674bca0e3488b6dff --- /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/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go new file mode 100644 index 0000000000000000000000000000000000000000..f152e7f55ce27547ded9b31d157f0d0f7fa0e537 --- /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 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 method M\) */ X2: + } +} 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 0000000000000000000000000000000000000000..c37b0f126783f6f0e3fc8ab5d0c088e9d96e0ecf --- /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] +) 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 0000000000000000000000000000000000000000..75bea1807226079867458b918a6b88d69630f290 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49179.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 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 +} + +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\] \(possibly missing ~ for \[\]int in constraint SliceConstraint\[int\]\) */, int](s, nil) +} 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 0000000000000000000000000000000000000000..524a0cbae364ad110ace20437441a1c39e7f6575 --- /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/fixedbugs/issue49247.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49247.go2 new file mode 100644 index 0000000000000000000000000000000000000000..3f25e0ee35526adb7fa4d3edf398e1e6006f3daa --- /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/fixedbugs/issue49276.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49276.go new file mode 100644 index 0000000000000000000000000000000000000000..8839087b50671221dd56a6b05dad3bfa199ef33a --- /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 +} 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 0000000000000000000000000000000000000000..eaa8e4dc7d8ad6d33c582f79c89d903da03b8721 --- /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 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 */ ) +} 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 0000000000000000000000000000000000000000..6cc838b3b30104c299e86b74ad604282dbb9b8c4 --- /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/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 new file mode 100644 index 0000000000000000000000000000000000000000..9e20ae5468db76e8604dcd93cea7c74f05480c8d --- /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/cmd/compile/internal/types2/testdata/fixedbugs/issue49592.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49592.go2 new file mode 100644 index 0000000000000000000000000000000000000000..846deaa89aac62bf1d7b404ca8e78d01965587f9 --- /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/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2 new file mode 100644 index 0000000000000000000000000000000000000000..2b991b872211af0466e433ae7aecd699d78ff52d --- /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/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 new file mode 100644 index 0000000000000000000000000000000000000000..46b1e71a3b95cfb43cfd760524c89d4054738b9c --- /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/testdata/fixedbugs/issue49864.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49864.go2 new file mode 100644 index 0000000000000000000000000000000000000000..0437e74a643fab57fdd6bd1c26bbd295c3e4764c --- /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/cmd/compile/internal/types2/testdata/spec/assignability.go2 b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 new file mode 100644 index 0000000000000000000000000000000000000000..507fe6d021f7ad37cae9cb33202fcc4be57787e9 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 @@ -0,0 +1,264 @@ +// Copyright 2021 The Go Authors. 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 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 + 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 named type" +// (here a named type is a type with a name) +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 // 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 /* 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 // 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 nil + a = nil // ERROR cannot use nil + l = nil + s = nil // ERROR cannot use nil + p = nil + f = nil + i = nil + m = nil + c = nil + d = nil // ERROR cannot use nil + + B = nil // ERROR cannot use nil + A = nil // ERROR cannot use nil + L = nil + S = nil // ERROR cannot use nil + P = nil + F = nil + I = nil + M = nil + C = 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" +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/spec/conversions.go2 b/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 new file mode 100644 index 0000000000000000000000000000000000000000..fde332f34bd13e091ecffc7831da54c6db900dc8 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 @@ -0,0 +1,178 @@ +// Copyright 2021 The Go Authors. 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" + +// 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 +} + +// 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 + +// "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\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" + +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\n\tcannot 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\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 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" + +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\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 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 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 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" + +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\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 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 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 +// 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 +} diff --git a/src/cmd/compile/internal/types2/tuple.go b/src/cmd/compile/internal/types2/tuple.go new file mode 100644 index 0000000000000000000000000000000000000000..1356aae0b018a464ef6c9deed88138e5d7115d7c --- /dev/null +++ b/src/cmd/compile/internal/types2/tuple.go @@ -0,0 +1,34 @@ +// 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} + } + 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 e6c260ff6790c6663438ad62ce3e21b232712a1a..9487ac5a84482ae5edcbc586802cc87cf05f0cf5 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -4,990 +4,123 @@ package types2 -import ( - "cmd/compile/internal/syntax" - "fmt" - "sync/atomic" -) - // A Type represents a type of Go. // All types implement the Type interface. 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 } -// 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 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 -} - -// 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 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 } - -// 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 } - -// 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] +// 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 { + if t, _ := t.(*Named); t != nil { + return t.under() } - return &Sum{types: types} + return t.Underlying() } -// is reports whether all types in t satisfy pred. -func (s *Sum) is(pred func(Type) bool) bool { - if s == nil { - return false +// 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) } - 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 - 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) - 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) -} - -// 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 sum := asSum(typ); sum != nil { - return sum.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 { - return false // we must have at least one type! (was bug) - } - for _, t := range unpack(t.allTypes) { - if !pred(t) { + var su Type + if tpar.underIs(func(u Type) bool { + if u == nil { return false } - } - return true -} - -// 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) - -// 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. -// -// 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. -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 (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 { - 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) - sortTypes(embeddeds) - - typ.methods = methods - typ.embeddeds = embeddeds - 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. -// 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") - } -} - -// 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] } - -// 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) -} - -// 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) -} - -// 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) -} - -// 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) -} - -// 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. -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 + if su != nil { + u = match(su, u) + if u == nil { + return false } } - } - return false -} - -// 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() - if t.allTypes == nil { + // su == nil || match(su, u) != nil + su = u return true + }) { + return su } - types := unpack(t.allTypes) - return includes(types, typ) || includes(types, under(typ)) + return nil } -// Complete computes the interface's method 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. -func (t *Interface) Complete() *Interface { - // TODO(gri) consolidate this method with Checker.completeInterface - if t.allMethods != nil { - return t +// 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 } - 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 + var su Type + hasString := false + if tpar.underIs(func(u Type) bool { + if u == nil { + return false } - etyp.Complete() - for _, m := range etyp.allMethods { - addMethod(m, false) + if isString(u) { + u = NewSlice(universeByte) + hasString = true } - 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 su != nil { + u = match(su, u) + if u == nil { + return false + } } - } - - if methods != nil { - sortMethods(methods) - t.allMethods = methods - } - t.allTypes = allTypes - - return t -} - -// 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 - 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 -} - -// 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) -} - -// 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 - } - 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.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 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.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] } - -// 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.underlying = underlying -} - -// AddMethod adds method m unless it is already in the method list. -func (t *Named) AddMethod(m *Func) { - 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. -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} - if obj.typ == nil { - obj.typ = typ - } - return typ -} - -func (t *TypeParam) Bound() *Interface { - iface := asInterface(t.bound) - // 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. - t.check.completeInterface(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 -// 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 - // 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.Bound().allTypes; u != nil && u != typ { - // u != typ and u is a type parameter => under(u) != typ, so this is ok - return under(u) + // su == nil || match(su, u) != nil + su = u + return true + }) { + if hasString { + return Typ[String] } - return theTop + return su } - 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 + return nil } -// 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] +// 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 + } } - 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 } - -// 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. -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 *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 } -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. -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 *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) } -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. -// 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 *Sum? - if n := asNamed(t); n != nil { - return n.under() } - return t -} - -// 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 asArray(t Type) *Array { - op, _ := optype(t).(*Array) - return op -} - -func asSlice(t Type) *Slice { - op, _ := optype(t).(*Slice) - return op -} - -func asStruct(t Type) *Struct { - op, _ := optype(t).(*Struct) - return op -} - -func asPointer(t Type) *Pointer { - op, _ := optype(t).(*Pointer) - return op -} - -// asTuple is not needed - not provided -func asSignature(t Type) *Signature { - op, _ := optype(t).(*Signature) - return op -} - -func asSum(t Type) *Sum { - op, _ := optype(t).(*Sum) - return op -} - -func asInterface(t Type) *Interface { - op, _ := optype(t).(*Interface) - return op -} - -func asMap(t Type) *Map { - op, _ := optype(t).(*Map) - return op -} - -func asChan(t Type) *Chan { - op, _ := optype(t).(*Chan) - return op -} - -// If the argument to asNamed and asTypeParam is of the respective types -// (possibly after expanding an instance type), these methods return that type. -// Otherwise the result is nil. - -func asNamed(t Type) *Named { - e, _ := expand(t).(*Named) - return e -} - -func asTypeParam(t Type) *TypeParam { - u, _ := under(t).(*TypeParam) - return u + // types are different + return nil } - -// Exported for the compiler. - -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) } diff --git a/src/cmd/compile/internal/types2/typelists.go b/src/cmd/compile/internal/types2/typelists.go new file mode 100644 index 0000000000000000000000000000000000000000..0b77edbde251afaa5bc5094a1c0e1d32b0793e38 --- /dev/null +++ b/src/cmd/compile/internal/types2/typelists.go @@ -0,0 +1,80 @@ +// Copyright 2021 The Go Authors. 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" + +// 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 *TypeParamList) Len() int { return len(l.list()) } + +// At returns the i'th type parameter in the list. +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 +// TypeParamList instead. +func (l *TypeParamList) 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 +} + +func (l *TypeList) String() string { + if l == nil || len(l.types) == 0 { + return "[]" + } + var buf bytes.Buffer + newTypeWriter(&buf, nil).typeList(l.types) + return buf.String() +} + +// ---------------------------------------------------------------------------- +// Implementation + +func bindTParams(list []*TypeParam) *TypeParamList { + 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 &TypeParamList{tparams: list} +} diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go new file mode 100644 index 0000000000000000000000000000000000000000..e32063a0af1dc85dbd9d00ffc53bacbfa6109e50 --- /dev/null +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -0,0 +1,160 @@ +// 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 // any type, but underlying is eventually *Interface for correct programs (see TypeParam.iface) +} + +// Obj returns the type name for the type parameter t. +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 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. +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: constraint} + 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 +} + +// 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 +} + +// Constraint returns the type constraint specified for t. +func (t *TypeParam) Constraint() Type { + return t.bound +} + +// 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 { + return t.iface() +} + +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 + + // 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: + if isTypeParam(bound) { + // error is reported in Checker.collectTypeParams + return &emptyInterface + } + ityp = u + } + + // If we don't have an interface, wrap constraint into an implicit interface. + if ityp == nil { + ityp = NewInterfaceType(nil, []Type{bound}) + ityp.implicit = true + t.bound = ityp // update t.bound for next time (optimization) + } + + // 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 +} + +// 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. +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/types_test.go b/src/cmd/compile/internal/types2/types_test.go index 096402148d38ad481815ad916e00664dfd0419c2..11dca0b53de86421a3a34f5ae505d90dca61d3f2 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) } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go new file mode 100644 index 0000000000000000000000000000000000000000..eaf614da6410a5cd1381a28ff1bd5bf412162ffe --- /dev/null +++ b/src/cmd/compile/internal/types2/typeset.go @@ -0,0 +1,401 @@ +// Copyright 2021 The Go Authors. 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" + "cmd/compile/internal/syntax" + "fmt" + "sort" +) + +// ---------------------------------------------------------------------------- +// API + +// 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 + terms termlist // type terms of the type set +} + +// IsEmpty reports whether type set s is the empty set. +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() +} + +// 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 { + if s.terms.isAll() { + return s.comparable + } + return s.is(func(t *term) bool { + return t != nil && Comparable(t.typ) + }) +} + +// 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 { + return !s.comparable && len(s.methods) == 0 +} + +// 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 { + switch { + case s.IsEmpty(): + return "∅" + case s.IsAll(): + return "𝓤" + } + + hasMethods := len(s.methods) > 0 + hasTerms := s.hasTerms() + + var buf bytes.Buffer + buf.WriteByte('{') + if s.comparable { + buf.WriteString("comparable") + if hasMethods || hasTerms { + buf.WriteString("; ") + } + } + for i, m := range s.methods { + if i > 0 { + buf.WriteString("; ") + } + buf.WriteString(m.String()) + } + if hasMethods && hasTerms { + buf.WriteString("; ") + } + if hasTerms { + buf.WriteString(s.terms.String()) + } + buf.WriteString("}") + return buf.String() +} + +// ---------------------------------------------------------------------------- +// Implementation + +// hasTerms reports whether the type set has specific type terms. +func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } + +// 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. +// 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. +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 + +// 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 !s.hasTerms() { + return f(nil) + } + for _, t := range s.terms { + assert(t.typ != nil) + if !f(t) { + return false + } + } + 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 !s.hasTerms() { + return f(nil) + } + for _, t := range s.terms { + assert(t.typ != nil) + // x == under(x) for ~x terms + u := t.typ + 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{terms: allTermlist} + +// computeInterfaceTypeSet may be called with check == nil. +func computeInterfaceTypeSet(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. + 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 = &_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 + // 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 allTerms = allTermlist + 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 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) { + check.versionErrorf(pos, "go1.18", "embedding constraint interface %s", typ) + continue + } + if tset.comparable { + ityp.tset.comparable = true + } + for _, m := range tset.methods { + addMethod(pos, m, false) // use embedding position pos rather than m.pos + } + terms = tset.terms + case *Union: + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.versionErrorf(pos, "go1.18", "embedding interface element %s", u) + continue + } + tset := computeUnionTypeSet(check, pos, u) + if tset == &invalidTypeSet { + continue // ignore invalid unions + } + terms = tset.terms + default: + if u == Typ[Invalid] { + continue + } + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.versionErrorf(pos, "go1.18", "embedding non-interface type %s", typ) + continue + } + terms = termlist{{false, typ}} + } + // 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) + + // 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.terms = allTerms + + return ityp.tset +} + +func sortMethods(list []*Func) { + sort.Sort(byUniqueMethodName(list)) +} + +func assertSortedMethods(list []*Func) { + if !debug { + panic("assertSortedMethods called outside debug mode") + } + if !sort.IsSorted(byUniqueMethodName(list)) { + panic("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] } + +// 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 + } + + // avoid infinite recursion (see also computeInterfaceTypeSet) + utyp.tset = new(_TypeSet) + + var allTerms termlist + for _, t := range utyp.terms { + var terms termlist + 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, 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)} + } + // 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 + + return utyp.tset +} 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 0000000000000000000000000000000000000000..7f7cc06db9773c7f09cef849888de81c5bd18499 --- /dev/null +++ b/src/cmd/compile/internal/types2/typeset_test.go @@ -0,0 +1,80 @@ +// Copyright 2021 The Go Authors. 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" + "strings" + "testing" +) + +func TestInvalidTypeSet(t *testing.T) { + if !invalidTypeSet.IsEmpty() { + t.Error("invalidTypeSet is not empty") + } +} + +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 diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 40016697b7c90f99c6319f0dae6c9079f3db0767..4d03eba65757c0ceaac89f2f358754102d88f67c 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -9,6 +9,9 @@ package types2 import ( "bytes" "fmt" + "sort" + "strconv" + "strings" "unicode/utf8" ) @@ -39,33 +42,18 @@ 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. 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() } @@ -73,172 +61,190 @@ 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) +} + +// 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) +} + +type typeWriter struct { + 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, nil, false} +} + +func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter { + assert(ctxt != nil) + return &typeWriter{buf, make(map[Type]bool), nil, ctxt, nil, false} } -// instanceMarker is the prefix for an instantiated type -// in "non-evaluated" instance 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 +func (w *typeWriter) byte(b byte) { + if w.ctxt != 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.ctxt != nil { + panic(msg) + } + w.buf.WriteString("<" + msg + ">") +} + +func (w *typeWriter) typ(typ Type) { + if w.seen[typ] { + w.error("cycle to " + goTypeName(typ)) + return } - visited = append(visited, typ) + w.seen[typ] = true + defer delete(w.seen, typ) switch t := typ.(type) { case nil: - buf.WriteString("") + w.error("nil") 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 } } - - if gcCompatibilityMode { - // forget the alias names - switch t.kind { - case Byte: - t = Typ[Uint8] - case Rune: - t = Typ[Int32] - } - } - buf.WriteString(t.name) + w.string(t.name) case *Array: - fmt.Fprintf(buf, "[%d]", t.len) - writeType(buf, t.elem, qf, visited) + w.byte('[') + w.string(strconv.FormatInt(t.len, 10)) + w.byte(']') + 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.byte(';') } // 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.byte(' ') + // TODO(gri) If tag contains blanks, replacing them with '#' + // in Context.TypeHash may produce another tag + // accidentally. + w.string(strconv.Quote(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) - - case *Sum: - for i, t := range t.types { + w.string("func") + w.signature(t) + + case *Union: + // Unions only appear as (syntactic) embedded elements + // in interfaces and syntactically cannot be empty. + if t.Len() == 0 { + w.error("empty union") + break + } + for i, t := range t.terms { if i > 0 { - buf.WriteString(", ") + w.byte('|') + } + if t.tilde { + w.byte('~') } - writeType(buf, t, qf, visited) + w.typ(t.typ) } 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) - for i, m := range t.allMethods { - if i > 0 { - buf.WriteString("; ") - } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - if !empty && t.allTypes != nil { - buf.WriteString("; ") - } - if t.allTypes != nil { - buf.WriteString("type ") - writeType(buf, t.allTypes, qf, visited) + 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]) + break } + // Something's wrong with the implicit interface. + // Print it as such and continue. + w.string("/* implicit */ ") + } + w.string("interface{") + first := true + if w.ctxt != nil { + w.typeSet(t.typeSet()) } else { - // print explicit interface methods and embedded types - for i, m := range t.methods { - if i > 0 { - buf.WriteString("; ") + for _, m := range t.methods { + if !first { + w.byte(';') } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false + first = false + w.string(m.name) + w.signature(m.typ.(*Signature)) } - 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("; ") - } - for i, typ := range t.embeddeds { - if i > 0 { - buf.WriteString("; ") + for _, typ := range t.embeddeds { + if !first { + w.byte(';') } - writeType(buf, typ, qf, visited) - empty = false - } - } - if t.allMethods == nil || len(t.methods) > len(t.allMethods) { - if !empty { - buf.WriteByte(' ') + first = false + w.typ(typ) } - buf.WriteString("/* incomplete */") } - 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 @@ -255,157 +261,187 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case RecvOnly: s = "<-chan " default: - panic("unreachable") + w.error("unknown channel direction") } - 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: - writeTypeName(buf, t.obj, qf) + // 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 - buf.WriteByte('[') - writeTypeList(buf, t.targs, qf, visited) - buf.WriteByte(']') - } else if t.tparams != nil { + w.typeList(t.targs.list()) + } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TypeParams // parameterized type - writeTParamList(buf, t.tparams, qf, visited) + w.tParamList(t.TypeParams().list()) } case *TypeParam: - s := "?" - if t.obj != nil { - s = t.obj.name + if t.obj == nil { + w.error("unnamed type parameter") + break + } + 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)) + } } - 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 *bottom: - buf.WriteString("⊥") - - case *top: - buf.WriteString("⊤") default: // For externally defined implementations of Type. - buf.WriteString(t.String()) + // Note: In this case cycles won't be caught. + w.string(t.String()) } } -func writeTypeList(buf *bytes.Buffer, list []Type, qf Qualifier, visited []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 { if i > 0 { - buf.WriteString(", ") + w.byte(',') } - writeType(buf, typ, qf, visited) + w.typ(typ) } + w.byte(']') } -func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited []Type) { - buf.WriteString("[") +func (w *typeWriter) tParamList(list []*TypeParam) { + w.byte('[') 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 + 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. + if tpar == nil { + w.error("nil type parameter") + continue } if i > 0 { - if b != prev { - // type bound changed - write previous one before advancing - buf.WriteByte(' ') - writeType(buf, prev, qf, visited) + if tpar.bound != prev { + // bound changed - write previous one before advancing + w.byte(' ') + w.typ(prev) } - buf.WriteString(", ") - } - prev = b - - if t, _ := p.typ.(*TypeParam); t != nil { - writeType(buf, t, qf, visited) - } else { - buf.WriteString(p.name) + w.byte(',') } + prev = tpar.bound + w.typ(tpar) } 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) { - s := "" - if obj != nil { - if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) - } - // TODO(gri): function-local named types should be displayed - // differently from named types at package level to avoid - // ambiguity. - s = obj.name +func (w *typeWriter) typeName(obj *TypeName) { + if obj.pkg != nil { + writePackage(w.buf, obj.pkg, w.qf) } - buf.WriteString(s) + w.string(obj.name) } -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.byte(',') } - if v.name != "" { - buf.WriteString(v.name) - buf.WriteByte(' ') + // parameter names are ignored for type identity and thus type hashes + if w.ctxt == nil && v.name != "" { + 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: // append(s, "foo"...) leads to signature func([]byte, string...) - if t := asBasic(typ); t == nil || t.kind != String { - panic("internal error: string type expected") + if t, _ := under(typ).(*Basic); t == nil || t.kind != String { + w.error("expected string type") + continue } - 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, -// 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) { - writeSignature(buf, sig, qf, make([]Type, 0, 8)) -} - -func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { - if sig.tparams != nil { - writeTParamList(buf, sig.tparams, qf, visited) +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()) } - writeTuple(buf, sig.params, sig.variadic, qf, visited) + w.tuple(sig.params, sig.variadic) n := sig.results.Len() if n == 0 { @@ -413,15 +449,15 @@ func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []T return } - buf.WriteByte(' ') - if n == 1 && sig.results.vars[0].name == "" { - // single unnamed result - writeType(buf, sig.results.vars[0].typ, qf, visited) + w.byte(' ') + 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 } // 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/typestring_test.go b/src/cmd/compile/internal/types2/typestring_test.go index d98e9a5ade6e9bbe0a3c60b03d9dd472425c35a9..eda68355884ceeaa5ed4d61c51b3badca56d3419 100644 --- a/src/cmd/compile/internal/types2/typestring_test.go +++ b/src/cmd/compile/internal/types2/typestring_test.go @@ -91,7 +91,8 @@ var independentTestTypes = []testEntry{ dup("interface{}"), dup("interface{m()}"), dup(`interface{String() string; m(int) float32}`), - dup(`interface{type int, float32, complex128}`), + dup("interface{int|float32|complex128}"), + dup("interface{int|~float32|~complex128}"), // maps dup("map[string]int"), @@ -128,67 +129,18 @@ 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) } } } -var nopos syntax.Pos - -func TestIncompleteInterfaces(t *testing.T) { - 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) diff --git a/src/cmd/compile/internal/types2/typeterm.go b/src/cmd/compile/internal/types2/typeterm.go new file mode 100644 index 0000000000000000000000000000000000000000..1d7223f13c42c013e06c8d8f1fb9cf4b423a7fb2 --- /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 + +// 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 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 { + 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 !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 0000000000000000000000000000000000000000..5a5c1fa4477d9e0da4a5a4d72a4505bce65856e1 --- /dev/null +++ b/src/cmd/compile/internal/types2/typeterm_test.go @@ -0,0 +1,239 @@ +// Copyright 2021 The Go Authors. 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 myInt = func() Type { + tname := NewTypeName(nopos, nil, "myInt", nil) + return NewNamed(tname, Typ[Int], nil) +}() + +var testTerms = map[string]*term{ + "∅": nil, + "𝓤": {}, + "int": {false, Typ[Int]}, + "~int": {true, Typ[Int]}, + "string": {false, Typ[String]}, + "~string": {true, Typ[String]}, + "myInt": {false, myInt}, +} + +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", + "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]) + 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 ∅", + "∅ 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]) + 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 ∅", + "∅ 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]) + 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", + "~int myInt T", + "string int F", + "~string int F", + "myInt 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", + "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]) + 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 myInt T", + "~int ~string T", + "~int myInt F", + "string myInt T", + "~string myInt 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) + } + } +} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index e64d804c30b8ccc59a9c5532d714a624109c0cca..9121c2c1f64414bd0d45b205d39d3fa4bf44868a 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -10,14 +10,9 @@ import ( "cmd/compile/internal/syntax" "fmt" "go/constant" - "sort" - "strconv" "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. @@ -30,9 +25,18 @@ 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 { + 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) @@ -41,6 +45,11 @@ 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 // avoid follow-on errors + } } check.recordUse(e, obj) @@ -63,7 +72,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 } @@ -130,40 +139,33 @@ 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 Interface) 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 := 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) - return - } - if t.IsComparable() { - check.softErrorf(pos, "interface is (or embeds) comparable") + 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() { + if tset.comparable { + check.softErrorf(pos, "interface is (or embeds) comparable") + } else { + check.softErrorf(pos, "interface contains type constraints") + } } } }) -} -// 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 } @@ -198,238 +200,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 { @@ -449,9 +219,7 @@ 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 = T.Underlying() + under = safeUnderlying(T) } if T == under { check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T)) @@ -500,6 +268,9 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { } case *syntax.IndexExpr: + if !check.allowVersion(check.pkg, 1, 18) { + check.versionErrorf(e.Pos(), "go1.18", "type instantiation") + } return check.instantiatedType(e.X, unpackExpr(e.Index), def) case *syntax.ParenExpr: @@ -544,8 +315,16 @@ 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 + // 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 } @@ -583,7 +362,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) @@ -623,77 +402,109 @@ 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) +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, xlist) + check.indent++ + defer func() { + check.indent-- + // Don't format the underlying here. It will always be nil. + check.trace(x.Pos(), "=> %s", res) + }() } - 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 - } - base := asNamed(b) - if base == nil { - unreachable() // should have been caught by genericType + gtyp := check.genericType(x, true) + if gtyp == Typ[Invalid] { + return gtyp // error already reported } - // create a new type instance rather than instantiate the type - // TODO(gri) should do argument number check here rather than - // when instantiating the type? - typ := new(instance) - def.setUnderlying(typ) - - typ.check = check - typ.pos = x.Pos() - typ.base = base + orig, _ := gtyp.(*Named) + if orig == nil { + panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp)) + } - // evaluate arguments (always) - typ.targs = check.typeList(targs) - if typ.targs == nil { + // evaluate arguments + targs := check.typeList(xlist) + 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) + // create the instance + ctxt := check.bestContext(nil) + h := ctxt.instanceHash(orig, targs) + // targs may be incomplete, and require inference. In any case we should de-duplicate. + 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 + // for each instantiated type in the source. + 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 = ctxt.update(h, orig, targs, inst).(*Named) + } + def.setUnderlying(inst) + + inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { + tparams := orig.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) + } + } + + check.recordInstance(x, inferred, inst) + return expandNamed(ctxt, n, x.Pos()) } - // make sure we check instantiation works at least once - // and that the resulting type is valid + // orig.tparams may not be set up, so we need to do expansion later. check.later(func() { - t := typ.expand() - check.validType(t, 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(ctxt) + // 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(xlist) { + pos = syntax.StartPos(xlist[i]) + } + check.softErrorf(pos, "%s", err) + } else { + check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), xlist) + } + } + + check.validType(inst, nil) }) - return typ + return inst } // arrayLength type-checks the array length expression e // 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_ { @@ -702,6 +513,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) { @@ -713,6 +525,7 @@ func (check *Checker) arrayLength(e syntax.Expr) int64 { } } } + check.errorf(&x, "array length %s must be integer", &x) return -1 } @@ -732,537 +545,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(ftype.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 -} - -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) 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 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].less(a[j]) } -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 { - 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 (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 - } - return nil -} diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index e1832bbb2a36232cd00a04e2e195ae51711938fe..f663beec38bbcca373a5ef51d52715ba6e9a737a 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 @@ -60,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 @@ -74,29 +76,30 @@ type tparamsList struct { // String returns a string representation for a tparamsList. For debugging. func (d *tparamsList) String() string { var buf bytes.Buffer - buf.WriteByte('[') - for i, tname := range d.tparams { + w := newTypeWriter(&buf, nil) + w.byte('[') + for i, tpar := range d.tparams { if i > 0 { - buf.WriteString(", ") + w.string(", ") } - writeType(&buf, tname.typ, 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() } // 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 @@ -105,7 +108,7 @@ func (d *tparamsList) init(tparams []*TypeName) { // 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] @@ -129,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. @@ -148,10 +152,23 @@ 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 []*TypeParam, tpar *TypeParam) int { + // 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 } @@ -216,26 +233,20 @@ 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 { - // 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 // 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 - // want *Named types.) - switch { - case !isNamed(x) && y != nil && asNamed(y) != nil: - return u.nify(x, under(y), p) - case x != nil && asNamed(x) != nil && !isNamed(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) } } @@ -352,25 +363,18 @@ 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 *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 { - // 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) + xset := x.typeSet() + yset := y.typeSet() + if !xset.terms.equal(yset.terms) { + return false } - a := x.allMethods - b := y.allMethods + 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 @@ -428,19 +432,18 @@ 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 - // } + // 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() + // 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 } } @@ -454,15 +457,11 @@ 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 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 diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go new file mode 100644 index 0000000000000000000000000000000000000000..97581fe863083ef21449b08db081bd6ac1eb3705 --- /dev/null +++ b/src/cmd/compile/internal/types2/union.go @@ -0,0 +1,157 @@ +// Copyright 2021 The Go Authors. 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 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 +} + +// 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) 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 + +// Avoid excessive type-checking times due to quadratic termlist operations. +const maxTermCount = 100 + +// 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) + if len(tlist) == 1 && !tilde { + // 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 // 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)) + } + + // 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 terms { + if t.typ == Typ[Invalid] { + continue + } + + u := under(t.typ) + f, _ := u.(*Interface) + if t.tilde { + if f != nil { + 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(tlist[i], "invalid use of ~ (underlying type of %s is %s)", t.typ, u) + continue // don't report another error for 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(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(tlist[i], "overlapping terms %s and %s", t, terms[j]) + } + } + }) + + u := &Union{terms, nil} + check.recordTypeAndValue(uexpr, typexpr, u, nil) + return u +} + +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 + } + typ = check.typ(x) + // Embedding stand-alone type parameters is not permitted (issue #47127). + // 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 +} + +// 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("empty or top union term") + } + } + if !(*term)(x).disjoint((*term)(y)) { + return i + } + } + 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/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index 76d4e55e84b59127dd4d3b5d9335a37c8369d0a8..c16ae3f63eafd0cc90ec46b6e3a6b94b1ff52cec 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 Object + universeByte Type // uint8 alias, but has name "byte" + universeRune Type // int32 alias, but has name "rune" + universeAny Object + universeError Type + universeComparable Object ) // Typ contains the predeclared *Basic types indexed by their @@ -77,20 +78,33 @@ 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.) - def(NewTypeName(nopos, nil, "any", &emptyInterface)) + // type any = interface{} + // 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})) - // Error has a nil package in its qualified name since it is in no package + // type error interface{ Error() string } { + obj := NewTypeName(nopos, nil, "error", nil) + obj.setColor(black) res := NewVar(nopos, nil, "", Typ[String]) - sig := &Signature{results: NewTuple(res)} + sig := NewSignatureType(nil, nil, nil, nil, NewTuple(res), false) err := NewFunc(nopos, nil, "Error", sig) - typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()} + 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) - def(NewTypeName(nopos, nil, "error", typ)) + def(obj) + } + + // type comparable interface{ /* type set marked comparable */ } + { + obj := NewTypeName(nopos, nil, "comparable", nil) + obj.setColor(black) + ityp := &Interface{nil, obj, nil, nil, nil, false, true, &_TypeSet{true, nil, allTermlist}} + NewNamed(obj, ityp, nil) + def(obj) } } @@ -200,33 +214,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).Complete() - - // 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,16 +223,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) - // "any" is only visible as constraint in a type parameter list - delete(Universe.elems, "any") + 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") } // Objects with names containing blanks are internal and not entered into @@ -259,7 +243,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 @@ -277,6 +261,6 @@ func def(obj Object) { } } if scope.Insert(obj) != nil { - panic("internal error: double declaration") + panic("double declaration of predeclared identifier") } } diff --git a/src/cmd/compile/internal/types2/version.go b/src/cmd/compile/internal/types2/version.go index d9d18b6f7a7f487e88320324fd7f457b5704b023..b649f09c3aa95ad333e1dcad2e4988ea0d549ff1 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/compile/internal/walk/assign.go b/src/cmd/compile/internal/walk/assign.go index 6d697a53ae3aaa14442a21f9f4e15880bbfe75c2..9350c389c162d6f3bbccee60d84014c9e4442b83 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 { @@ -429,6 +429,7 @@ func readsMemory(n ir.Node) bool { ir.OBITNOT, ir.OCONV, ir.OCONVIFACE, + ir.OCONVIDATA, ir.OCONVNOP, ir.ODIV, ir.ODOT, @@ -532,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)) @@ -542,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") @@ -689,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 14efc05e32753727502e42f4e805ebe134522125..d0aaee03d59d07b4bd39ef861f1ea62ccc5fae30 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") @@ -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) @@ -641,16 +638,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/closure.go b/src/cmd/compile/internal/walk/closure.go index 2194e1c5b0c7a3fd9f5ed01a57bb1e8aeb613238..4d1c5621fec857fe3a9487bf9da3c422367e08d5 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 @@ -115,13 +107,25 @@ 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) 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()) @@ -161,7 +165,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: // @@ -175,18 +179,16 @@ 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) + typ := typecheck.MethodValueType(n) 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)), n.X} addr := typecheck.NodAddr(clos) addr.SetEsc(n.Esc()) @@ -205,3 +207,78 @@ func walkCallPart(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { return walkExpr(cfn, init) } + +// 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.Name { + 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.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 + + // 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.SetWrapper(true) + + // Declare and initialize variable holding receiver. + 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()) + 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.Nname + typecheck.Target.Decls = append(typecheck.Target.Decls, fn) + ir.CurFunc = savecurfn + base.Pos = saveLineNo + + return fn.Nname +} diff --git a/src/cmd/compile/internal/walk/compare.go b/src/cmd/compile/internal/walk/compare.go index b18615f61a3e3b4d0ca988193c1114d3b6d1fb86..625e2160503754b6c2beb0452e0ecddf0b2b280d 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) @@ -138,7 +136,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 +162,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 +200,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 +225,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 +240,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() } } } @@ -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/compile/internal/walk/complit.go b/src/cmd/compile/internal/walk/complit.go index abd920d64612ff720dbfc27e6b37d6ce32f64e7f..b985b4caeb8597ec7387cb7ca24eb4cde01e5c0d 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()) @@ -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) { @@ -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) @@ -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 @@ -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 26e17a126f22151a542fecf9026002846baa82ca..ffc5fd19e801dcfbc2bdd046bc43eb3fda9104c7 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" ) @@ -24,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) } @@ -41,46 +39,98 @@ func walkConv(n *ir.ConvExpr, init *ir.Nodes) ir.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 !fromType.IsInterface() && !ir.IsBlank(ir.CurFunc.Nname) { // skip unnamed functions (func _()) + 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.Pos(), 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(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) + + 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(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. + 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)) } @@ -90,118 +140,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.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.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(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(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) + addr = ir.NewConvExpr(pos, ir.OCONVNOP, argType.PtrTo(), addr) + arg = ir.NewStarExpr(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.Pos(), n.X, init, n.Esc() != ir.EscNone) } // walkBytesRunesToString walks an OBYTES2STR or ORUNES2STR node. @@ -312,50 +315,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 && uint8(from.Alignment()) == 2: + return "convT16", types.Types[types.TUINT16], false + case from.Size() == 4 && uint8(from.Alignment()) == 4 && !from.HasPointers(): + return "convT32", types.Types[types.TUINT32], false + 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 { 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 @@ -379,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() } } @@ -395,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 } @@ -423,32 +411,6 @@ func byteindex(n ir.Node) ir.Node { return n } -func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, count ir.Node) ir.Node { - if !n.Type().IsPtr() { - base.Fatalf("expected pointer type: %v", n.Type()) - } - elem := n.Type().Elem() - 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) - init.Append(mkcall("checkptrAlignment", nil, init, typecheck.ConvNop(n.X, types.Types[types.TUNSAFEPTR]), reflectdata.TypePtr(elem), typecheck.Conv(count, types.Types[types.TUINTPTR]))) - 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 @@ -462,7 +424,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 } @@ -499,7 +463,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/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 2fb907710bbbda09f6cdae70ba6a2fd734d84175..e5bf6cf0b5e3670a8df0c827f1385ff40251f54d 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: @@ -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) @@ -161,13 +165,13 @@ 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 - case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH: + case ir.OCALLINTER, ir.OCALLFUNC: n := n.(*ir.CallExpr) return walkCall(n, init) @@ -206,6 +210,10 @@ 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) + return walkConvIData(n, init) + case ir.OCONV, ir.OCONVNOP: n := n.(*ir.ConvExpr) return walkConv(n, init) @@ -308,8 +316,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), @@ -487,9 +495,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 { + 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) @@ -549,20 +560,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) + base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") } args := n.Args @@ -671,6 +670,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) @@ -761,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) @@ -801,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]. @@ -817,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.Max) - } if n.Op().IsSlice3() { if n.Max != nil && n.Max.Op() == ir.OCAP && ir.SameSafeExpr(n.X, n.Max.(*ir.UnaryExpr).X) { @@ -867,7 +862,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) @@ -931,56 +926,55 @@ 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() + // 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. + if base.Ctxt.Pkgpath == "reflect" { + switch ir.CurFunc.Nname.Sym().Name { // TODO: is there a better way than hardcoding the names? + case "(*rtype).Method", "(*rtype).MethodByName", "(*interfaceType).Method", "(*interfaceType).MethodByName": + return + } + } - // 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 { + dot, ok := n.X.(*ir.SelectorExpr) + if !ok { return } - if n := t.NumResults(); n != 1 && n != 2 { + + // 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 } - 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 - } + t := dot.Selection.Type + if t.NumParams() != 1 || t.Params().Field(0).Type.Kind() != pKind { + 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. - if base.Ctxt.Pkgpath == "reflect" { - switch ir.CurFunc.Nname.Sym().Name { // TODO: is there a better way than hardcoding the names? - case "(*rtype).Method", "(*rtype).MethodByName", "(*interfaceType).Method", "(*interfaceType).MethodByName": + switch t.NumResults() { + case 1: + // ok + case 2: + if t.Results().Field(1).Type.Kind() != types.TBOOL { return } + default: + return } - // Note: Don't rely on res0.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) { + // 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. ir.CurFunc.LSym.Set(obj.AttrReflectMethod, true) diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index b733d3a29f67cc18a924462a0a4c8983a8e8bf7b..861c122456d7648f2fc319beecb77f23004e2ae1 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -7,15 +7,14 @@ package walk import ( "fmt" "go/constant" - "internal/buildcfg" "cmd/compile/internal/base" - "cmd/compile/internal/escape" "cmd/compile/internal/ir" "cmd/compile/internal/reflectdata" "cmd/compile/internal/staticinit" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" + "cmd/internal/objabi" "cmd/internal/src" ) @@ -53,7 +52,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 } @@ -78,20 +77,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.LongString() - 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 { @@ -305,7 +298,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) @@ -372,7 +365,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().LinkString() o.free[key] = append(o.free[key], n) } o.temp = o.temp[:mark] @@ -451,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)) @@ -514,15 +514,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) @@ -554,39 +557,6 @@ func (o *orderState) call(nn ir.Node) { n.X = o.expr(n.X, nil) o.exprList(n.Args) - - if n.Op() == ir.OCALLINTER { - return - } - keepAlive := func(arg 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) - } - } - } - - // 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) - } - } - } } // mapAssign appends n to o.out. @@ -693,9 +663,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, @@ -713,6 +694,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) @@ -748,14 +733,25 @@ 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) o.out = append(o.out, n) o.cleanTemp(t) - case ir.OCLOSE, ir.ORECV: + 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() n.X = o.expr(n.X, nil) @@ -770,10 +766,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) @@ -783,16 +779,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) - } - if buildcfg.Experiment.RegabiDefer { - o.wrapGoDefer(n) - } o.out = append(o.out, n) o.cleanTemp(t) @@ -830,16 +816,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. @@ -973,6 +949,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) @@ -1192,23 +1174,26 @@ 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) { + 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 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 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 @@ -1261,9 +1246,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, @@ -1275,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: @@ -1293,6 +1281,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) @@ -1327,11 +1320,11 @@ 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() { - t := typecheck.PartialCallType(n) + t := typecheck.MethodValueType(n) n.Prealloc = o.newTemp(t, false) } return n @@ -1498,313 +1491,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 c, ok := call.(*ir.CallExpr); ok && callX != nil && callX.Op() == ir.OCLOSURE { - cloFunc := callX.(*ir.ClosureExpr).Func - cloFunc.SetClosureCalled(false) - c.PreserveClosure = 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) - 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) - } - } - } - - // 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.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)) - } - ir.FinishCaptureNames(n.Pos(), outerfn, fn) - - // 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) - - // 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) - - // Create closure expr - clo := ir.NewClosureExpr(n.Pos(), fn) - fn.OClosure = clo - clo.SetType(fn.Type()) - - // 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) - } - } 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, []ir.Node{}) - 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. - 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/range.go b/src/cmd/compile/internal/walk/range.go index b1169fdae8a1aba973a7e3023d56b882634e721b..aa8c5489630829ec8781cd56cd2e694a259e37fe 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/select.go b/src/cmd/compile/internal/walk/select.go index d2b67ddf55a7abc8d5ccba5dc9d991aa7cd7fd2e..fde8f5089590fbc2984a6fb2c98d2d1e0e0412f0 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: diff --git a/src/cmd/compile/internal/walk/stmt.go b/src/cmd/compile/internal/walk/stmt.go index 0bf76680c4626546f00fee0890a4418a157c77b5..f09e9165464bcf9e31979752111a881c5091c84c 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. @@ -41,7 +40,6 @@ func walkStmt(n ir.Node) ir.Node { ir.OAS2MAPR, ir.OCLOSE, ir.OCOPY, - ir.OCALLMETH, ir.OCALLINTER, ir.OCALL, ir.OCALLFUNC, @@ -50,7 +48,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) @@ -138,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: @@ -187,33 +193,28 @@ 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 { + if !validGoDeferCall(n.Call) { + base.FatalfAt(n.Pos(), "invalid %v call: %v", n.Op(), n.Call) + } + 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) - - 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) - } - default: - n.Call = walkExpr(call, &init) - } + call := n.Call.(*ir.CallExpr) + call.X = walkExpr(call.X, &init) + if len(init) > 0 { init.Append(n) return ir.NewBlockStmt(n.Pos(), init) @@ -228,110 +229,3 @@ func walkIf(n *ir.IfStmt) ir.Node { walkStmtList(n.Else) 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}...) -// -// 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/src/cmd/compile/internal/walk/switch.go b/src/cmd/compile/internal/walk/switch.go index 162de018f637ef5a329d8a31cab1f64cc7906b54..3705c5b19265d9a4f5a4c5cf9d36cfba3cf94ac5 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/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go index 26da6e314574431ef88187128097d4c644f00c1d..78cc2e69da091b1acf00109c036980bd69dd665f 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) } @@ -206,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()) { @@ -308,12 +307,12 @@ 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 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 @@ -343,7 +342,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. } diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go index 31b09016eb98296a3838bc39125dbb3f4f73a101..765051c9445b293e84f372fcd890598c048f3ba3 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 @@ -89,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) @@ -123,10 +116,14 @@ 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 { - // 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 { @@ -138,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/galign.go b/src/cmd/compile/internal/x86/galign.go index 00a20e429f1d6112cbf985e0b3c8706b187b0356..5565bd32c765b36debf7cde83eab4f3d2d8a71dd 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/compile/internal/x86/ssa.go b/src/cmd/compile/internal/x86/ssa.go index a06fdbcb71770ebce782dcbba69fdc673b236ac7..32e29f347b9c7f675414ee46c037aa62ea682b00 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/src/cmd/cover/cover.go b/src/cmd/cover/cover.go index 7ee000861bcc2ad073e68a38c227a6a401343ea8..9c8529f7eb600ab5e0457595343a3464aae44004 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) diff --git a/src/cmd/cover/testdata/test.go b/src/cmd/cover/testdata/test.go index b794962205d3da7f8cdf9c37c43fecdc0473e81e..0e1dbc61943112cda78141572962d9434d7f7618 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" @@ -150,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: @@ -214,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/build.go b/src/cmd/dist/build.go index bec17696f3040acd6f78750f3306c1d3bbeba102..d37c3f83efb4d474175a46062956222c450ad906 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 @@ -48,8 +49,6 @@ var ( exe string defaultcc map[string]string defaultcxx map[string]string - defaultcflags string - defaultldflags string defaultpkgconfig string defaultldso string @@ -147,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" @@ -209,9 +214,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" @@ -222,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) @@ -809,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) } } @@ -819,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 { @@ -967,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") || @@ -1029,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 == "" { @@ -1049,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 @@ -1186,6 +1168,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 54e935ad3bec1d35c5bf37732ed1bb659965792c..fdc1d257744fcdba092d5db466acdcf4e321ac13 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/dist/buildtag.go b/src/cmd/dist/buildtag.go new file mode 100644 index 0000000000000000000000000000000000000000..24776a0aaf735f14fe79caf53510248f09112742 --- /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 == '_' +} diff --git a/src/cmd/dist/buildtag_test.go b/src/cmd/dist/buildtag_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f64abfd1f18c252ed1b8a8a9cbbbea5a286abc03 --- /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/dist/buildtool.go b/src/cmd/dist/buildtool.go index 26b33e389fe9283aabd5c0c8f44fba88fa44ea8c..036f8c52fa3918f66d05b27611cf5c349c941ef2 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" ) @@ -46,6 +47,7 @@ var bootstrapDirs = []string{ "cmd/internal/obj/...", "cmd/internal/objabi", "cmd/internal/pkgpath", + "cmd/internal/quoted", "cmd/internal/src", "cmd/internal/sys", "cmd/link", @@ -92,10 +94,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) @@ -276,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/dist/exec.go b/src/cmd/dist/exec.go new file mode 100644 index 0000000000000000000000000000000000000000..67305530ae83fcbc6a30e1956ad25094d1935d30 --- /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 f40fa926dfd398b2c8adf239122358ef49e358cc..50a2e5936c639846d8d9f78f78756552fcf10390 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 @@ -491,30 +499,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", - 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{ @@ -522,7 +506,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 }, }) @@ -542,7 +527,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 }, }) @@ -563,7 +548,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() @@ -600,16 +585,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 { @@ -736,11 +718,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 }, }, @@ -892,9 +872,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 } @@ -997,11 +977,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 } @@ -1027,7 +1002,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 @@ -1045,7 +1020,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 @@ -1053,7 +1028,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", @@ -1068,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 @@ -1132,7 +1105,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 } @@ -1141,7 +1115,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. @@ -1149,7 +1123,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 @@ -1161,9 +1135,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") @@ -1181,10 +1155,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") @@ -1217,7 +1191,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") } } @@ -1456,7 +1430,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. @@ -1486,7 +1460,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 { @@ -1650,7 +1625,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 df60145d1e21e8f2a9a4fc421e56c2f20d305c6b..8856f467d5ba8e66ed4ad851ed3ea4abc9efdf8a 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 @@ -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 {} } } diff --git a/src/cmd/doc/dirs.go b/src/cmd/doc/dirs.go index 661624cfe4c168c793d582203de163f3169634e6..f27af1d27befbe10f4fcf61fc21eed960f6e9867 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/main.go b/src/cmd/doc/main.go index 0499c403695247035687054c0700fe28500a0b57..dee5d7bbcd7142d07c822387d2b42d6ce65fa522 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() diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index 587f0bdc1468f2fd23a2f15d8a097a89137f4fef..f51efe08af5c1ab35055f92aff6b466484ba52c1 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{ @@ -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: @@ -325,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 @@ -344,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 { @@ -421,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/cmd/doc/testdata/nested/ignore.go b/src/cmd/doc/testdata/nested/ignore.go index c497f1b5bc410017f84927737153148254e8447a..5fa811d0a859c192c3a34713e970e604b2f93da3 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/buildtag.go b/src/cmd/fix/buildtag.go new file mode 100644 index 0000000000000000000000000000000000000000..5f4fbfef16f15b99d78ff34d2f2c0a02334760db --- /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 0000000000000000000000000000000000000000..1c6efbe9e0326232a59a9548e2cde10fb73e2bc0 --- /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/cftype.go b/src/cmd/fix/cftype.go index b47b06682add8040c98fa9480e73bf3788d6e062..27e4088aa9fa7f28bf98870758689eb2d42d9f32 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,12 +58,12 @@ 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 } v := reflect.ValueOf(n) - if v.Type().Kind() != reflect.Ptr { + if v.Type().Kind() != reflect.Pointer { return } if v.IsNil() { @@ -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 b49db375710c3c511ca26a3fa55fa406b19d19ff..7abdab28a8df21095aebc8ea009919406dd03128 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) { @@ -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: @@ -381,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 031f85c9cc5c18ebf3ea1779ebeddfcbcc86b789..6085816ada45c0d9b7f706574b07298aacad3155 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 d055929aac0767bcd6b0be7ff6550b239c55af34..3229b71ec488ea3614afe6f1ee4134ff2c2eac49 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 != "" { @@ -219,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/main_test.go b/src/cmd/fix/main_test.go index af16bcaa31ed94ca6e1f611c847cbae3e0f41786..1baa95c5456bcc85d7158902f9c2afa382363fdf 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/fix/netipv6zone.go b/src/cmd/fix/netipv6zone.go index 3e502bda07cb964ab77a7aaccf13b656a9b93a6b..199fcf5bf5976520857e7c194341e5443f60684a 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 6d9399687281134b22fd791ea54bfc4cc2588d40..bad6953196421408fbf905f169342dffc51f1313 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 39a53785b724d4105ccfd6d7bdd320a7f3428005..8a18d61bf2748e5c080cb4811a2782b01de428c4 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,11 +379,11 @@ 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 } - 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()) @@ -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/go.mod b/src/cmd/go.mod index cd03968eedcf618d0ecef8da89ce790646dba399..f46c770c199b4f865b4cf0431b1b442df150d7eb 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -1,15 +1,19 @@ module cmd -go 1.17 +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/crypto v0.0.0-20210503195802-e9a32991a82e // indirect - 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 + 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.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.9-0.20211207220608-fd2bfb79a16a +) + +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-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 d728acaec9925e702dac5a61edeaebac48d878c6..941011fe09fc9e512030fe85b221adac28251d7e 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -1,45 +1,24 @@ 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/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= +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-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +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.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-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/sys v0.0.0-20211007075335-d3039528d8ac/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.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= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 7f88d3216cf080a9573026997231cc608a801589..6703792054d70d055bec469db2a35b0cf2509b21 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 @@ -114,13 +115,16 @@ // 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. // 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 @@ -131,8 +135,19 @@ // // -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 +// 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. See also -buildinfo. // -compiler name // name of compiler to use, as in runtime.Compiler (gccgo or gc). // -gccgoflags '[pattern=]arg list' @@ -144,8 +159,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 @@ -167,6 +182,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 @@ -284,6 +307,13 @@ // 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. 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'. // // For more about specifying packages, see 'go help packages'. @@ -338,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 [.] // @@ -438,14 +467,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. // @@ -483,7 +516,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 @@ -598,11 +631,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: // @@ -618,17 +651,18 @@ // // 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 // // 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. @@ -643,15 +677,9 @@ // 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. +// 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. // @@ -694,14 +722,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 @@ -1041,8 +1072,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 @@ -1260,7 +1294,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. @@ -1272,6 +1306,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'. // // @@ -1329,6 +1368,148 @@ // See https://golang.org/ref/mod#go-mod-why for more about 'go mod why'. // // +// Workspace maintenance +// +// 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 modules. +// +// 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] +// +// The commands are: +// +// 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. +// +// Edit go.work from tools or scripts +// +// Usage: +// +// go work edit [editing flags] [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, Edit 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 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. +// +// 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 -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. +// +// 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 Use 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] +// +// Init initializes and writes a new go.work file in the current +// directory, in effect creating a new workspace at the current directory. +// +// 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 +// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for +// more information. +// +// +// Sync workspace build list to modules +// +// Usage: +// +// go work sync [moddirs] +// +// 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: @@ -1387,8 +1568,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 +// 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. // @@ -1405,7 +1586,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 @@ -1446,16 +1628,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: // @@ -1746,6 +1928,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: // @@ -1885,6 +2074,10 @@ // GO386 // For GOARCH=386, how to implement floating point instructions. // Valid values are sse2 (default), softfloat. +// GOAMD64 +// 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 // For GOARCH=mips{,le}, whether to use floating point instructions. // Valid values are hardfloat (default), softfloat. @@ -2622,9 +2815,10 @@ // (for example, -benchtime 100x). // // -count n -// Run each test and benchmark 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 tests matched by -fuzz. // // -cover // Enable coverage analysis. @@ -2651,32 +2845,67 @@ // 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 -// of GOMAXPROCS. +// Specify a list of GOMAXPROCS values for which the tests, benchmarks or +// 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 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 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 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 +// 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 -// list top-level tests. No subtest or subbenchmarks will be shown. +// 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. +// Allow parallel execution of test functions that call t.Parallel, and +// 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; 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 // (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 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 // 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, @@ -2689,11 +2918,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. @@ -2789,7 +3018,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, @@ -2843,6 +3076,10 @@ // // func BenchmarkXxx(b *testing.B) { ... } // +// A fuzz test 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 @@ -2882,7 +3119,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 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/go11.go b/src/cmd/go/go11.go index a1f2727825ede1f1ead32d3e240311206a186ed5..9faa7cba42e097b094ca17d41c47dbbb5f54ba62 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_test.go b/src/cmd/go/go_test.go index 6ce276537babd88765937e1f7ec0f3c98cc5ac68..170c882df9e77158b9591370411bc6f728018825 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" @@ -31,7 +32,6 @@ import ( "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/robustio" - "cmd/go/internal/work" "cmd/internal/sys" ) @@ -44,9 +44,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 + 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 { @@ -198,6 +201,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 @@ -205,6 +209,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") @@ -806,7 +812,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), @@ -1120,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") @@ -1376,10 +1384,10 @@ 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")) + 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") } @@ -2274,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) @@ -2297,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") } @@ -2329,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) @@ -2358,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) @@ -2388,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/cmd/go/go_unix_test.go b/src/cmd/go/go_unix_test.go index 7d5ff9bbb748391dac7cc2f2be0c7fc032977bac..bab94944014afa330431c328ca22edce9d80ba31 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/base.go b/src/cmd/go/internal/base/base.go index 954ce47a9899325014b4e99b5b6a1875a4120f30..c2d4e6b258887118b8d0822f6a3c246951b7bb77 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/base/flag.go b/src/cmd/go/internal/base/flag.go index 677f8196827f4c8fa18e49964ba2abc75a5861fa..2c72c7e562b7333be43813553321469a555b44a0 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/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{} } @@ -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/base/signal_notunix.go b/src/cmd/go/internal/base/signal_notunix.go index 5cc0b0f1011e5a1a0c2ff3a0eb256960d90deb7c..682705f9b2cb41e3a6fc81fd74536a3aa4e42104 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 cdc2658372e429930170b5a25b6a8ee7948e0c9f..657ff38584104201de727e67d74f50ce798df8b1 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/base/tool.go b/src/cmd/go/internal/base/tool.go index d0da65e03ced64a930867913843e534dd5701bd9..f927016965051e7d2d8f46c4d2af9b5123c92fe7 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 307527c695cbededab0ae1dfa4447e2fc3161c4b..702dc2a14acdaad63f13bcd802541dd3141f3362 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) @@ -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) { diff --git a/src/cmd/go/internal/cache/cache.go b/src/cmd/go/internal/cache/cache.go index d592d7049786ce9d3fd5d15a67f2884327f149a0..93d7c25658fa07eef33d282ff3e61e90cf63d616 100644 --- a/src/cmd/go/internal/cache/cache.go +++ b/src/cmd/go/internal/cache/cache.go @@ -533,3 +533,15 @@ 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'. +// +// 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/cache/default.go b/src/cmd/go/internal/cache/default.go index 0b1c1e0c203511ca619e8f0a409e088af9c35b0b..426dddfb978624a1843bdc6df66fdd7e96eb2ca6 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. ` diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 57a3c1ff6fbdc1f9f29a10a4580e8d40e4f8c908..5b84d8be92117993e32047ae0dc97c3747ad6c3d 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -25,7 +25,9 @@ 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() BuildMod string // -mod flag BuildModExplicit bool // whether -mod was set explicitly @@ -33,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 @@ -47,17 +50,26 @@ 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. 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 + + GOEXPERIMENT = envOr("GOEXPERIMENT", buildcfg.DefaultGOEXPERIMENT) ) func defaultContext() build.Context { ctxt := build.Default + ctxt.JoinPath = filepath.Join // back door to say "do not use go command" ctxt.GOROOT = findGOROOT() @@ -70,7 +82,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. @@ -79,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) @@ -261,6 +273,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)) @@ -287,6 +300,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": @@ -396,3 +411,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/clean/clean.go b/src/cmd/go/internal/clean/clean.go index fd4cb205591105d0ad527e25e811cd62dfadf5a8..dc93cdf5983126c42adeddb2504276a8a41f834f 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -75,6 +75,13 @@ 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 files stored in the Go build +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'. For more about specifying packages, see 'go help packages'. @@ -85,6 +92,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 +104,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, "") @@ -112,7 +121,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 } @@ -144,7 +153,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 +166,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 +196,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 +204,26 @@ 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) + } + } + } + + 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: %v", err) } } } @@ -245,7 +266,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 +355,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 +407,5 @@ func removeFile(f string) { return } } - base.Errorf("go clean: %v", err) + base.Errorf("go: %v", err) } diff --git a/src/cmd/go/internal/cmdflag/flag.go b/src/cmd/go/internal/cmdflag/flag.go index 8abb7e559f5ab5564f48a972bd084d2eb023a70f..a634bc1ab8d7ea1a256b386c2c6720009613284c 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/doc/doc.go b/src/cmd/go/internal/doc/doc.go index 8580a5dc4d2482a7e2f88640abe9a76a245adb18..7741a9022c910a0bee6c4084e55503bc6aea9c09 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 [.] diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 1553d263914541f05a639e03b8041969ba244301..e56dd8223f0519e90e9c89cd8e576d5f227becc5 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/quoted" ) 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}) @@ -145,13 +146,17 @@ 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") + gomod = modload.ModFilePath() } else if modload.Enabled() { gomod = os.DevNull } + modload.InitWorkfile() + gowork := modload.WorkFilePath() return []cfg.EnvVar{ {Name: "GOMOD", Value: gomod}, + {Name: "GOWORK", Value: gowork}, } } @@ -191,13 +196,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, @@ -275,7 +280,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 { @@ -287,14 +292,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 { @@ -303,13 +308,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") } } @@ -319,18 +324,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) @@ -414,7 +419,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) } } @@ -429,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) @@ -457,10 +462,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 := quoted.Split(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]) } } @@ -479,11 +497,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") @@ -541,7 +559,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/fix/fix.go b/src/cmd/go/internal/fix/fix.go index 988d45e71ccfe2ccf571e409962bdd3ade4e3430..d8ba353de6595091f10b693bcb3aed1fde9d2e0d 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)) } } diff --git a/src/cmd/go/internal/fmtcmd/fmt.go b/src/cmd/go/internal/fmtcmd/fmt.go index 8a040087539e8f9195c61a88d89883a379a963b2..19656eab7fc661c4cea1fabf55630f38ab2b3c98 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/go/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/fsys/fsys.go b/src/cmd/go/internal/fsys/fsys.go index 0b806027e6469a3cac3b19e2e5e162b7ead8e92d..9a1bbf890e1191ebb68b19673f7ea647bae9a899 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/fsys/fsys_test.go b/src/cmd/go/internal/fsys/fsys_test.go index 7f175c7031169dded7b720e9899f7d38909f8d74..c080c14987c37cad5928771d49bb0a4b1b602953 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/generate/generate.go b/src/cmd/go/internal/generate/generate.go index 80ea32b4284011712eb82b2bd671e4f5f9a35b2e..54ccfe78f24b66d526bc4b386b8ebc282603a140 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 @@ -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/get/get.go b/src/cmd/go/internal/get/get.go index 3c16dc3040facba13a7a59416268ae7944250599..8cf8fe6645f369d47d84de3321e195e0b727cf22 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,18 +214,19 @@ 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) } } } 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() @@ -415,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 @@ -444,10 +446,19 @@ 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) + const allowNesting = false + repoDir, vcsCmd, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot, allowNesting) 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/help/help.go b/src/cmd/go/internal/help/help.go index 7a730fc8eb8c5e5255c6121b8b26d81ba9b6ba99..2a07d2423bdd9e46eb397228214cde2b13226695 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/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 490ff1fb7cf05bd5a7e107c1ea40bb44174cc0db..035235fe1b5a1d39a3e8228daa20362fee8af86c 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=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 For GOARCH=mips{,le}, whether to use floating point instructions. Valid values are hardfloat (default), softfloat. @@ -771,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/imports/build.go b/src/cmd/go/internal/imports/build.go index 50aeabc578c93094ce776e99d25d0612e7397bbc..ff6bea6777dce89c81385f1e38182e43de12f821 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/internal/imports/scan_test.go b/src/cmd/go/internal/imports/scan_test.go index 2d245ee7872e73c706b15dcf6b2e1f9559248412..7e69c56513ac01a2acf0d5cd5d4372597abd96f0 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 { diff --git a/src/cmd/go/internal/imports/testdata/android/e.go b/src/cmd/go/internal/imports/testdata/android/e.go index d9b2db769b5f0c7c529cfeb9e437689dab8821f7..f1b9c888c2cafdd83ab651a52f75b31bb1f83516 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 281e4dd6b9898ed971ba7b8d19d20d2004c92ae2..bb0ff7b73f67c15fffeb5ea95f0628047a794cdf 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 66a789c0ada4b58abccdfac60c056417847cb058..ee19424890a963fa1618310d2875de3438df2a0e 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 5e1ed3cb9decae06303aa7ecbdc8f8410baa2bff..fddf2c429909b7776cd4cdddce2ed70f0cd35542 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 f3e3f728bce5d837453f3f88ed6c2de34c6c49d7..4b6d528e4c2225f29ed67e382a3561586b4f2170 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 b30f1eb4037322ce7501948f9f8deceddeb605cf..1bf826b81510b42fafb4a11a0e9e92c7ad8d0860 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 6a9594aed035e6570d51457d8428cd0fc0a0f73f..eaaea979e9dc82285ab0f830cbc676295d0732d1 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 7cb9ec6d9492428aa0c9afe111fde89bf35fa536..d9a7078ccf29f7aa16d1a9d10e3bf24d486f4495 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") } @@ -355,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() @@ -383,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) @@ -424,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") @@ -468,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() } @@ -708,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/load/flag.go b/src/cmd/go/internal/load/flag.go index 440cb86134489a7e023ce516629fe9bccc00fe0c..de079decdf2541c6f7ac312e002aec761427bfbc 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/quoted" "fmt" "strings" ) @@ -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. @@ -61,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 } @@ -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 a83cc9a812b674fe863b19c16273f2f6626042f8..a891d601b1d4fdf62faebaa6eb5f6cd3b492ee79 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -21,9 +21,11 @@ import ( pathpkg "path" "path/filepath" "runtime" + "runtime/debug" "sort" "strconv" "strings" + "time" "unicode" "unicode/utf8" @@ -38,6 +40,7 @@ import ( "cmd/go/internal/search" "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/go/internal/vcs" "cmd/internal/sys" "golang.org/x/mod/modfile" @@ -203,6 +206,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 @@ -494,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)) @@ -585,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)] }) } @@ -601,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) @@ -813,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) @@ -840,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 != "" { @@ -1059,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) @@ -1187,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 "" @@ -1450,9 +1454,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) { @@ -1622,6 +1626,7 @@ var cgoSyscallExclude = map[string]bool{ "runtime/cgo": true, "runtime/race": true, "runtime/msan": true, + "runtime/asan": true, } var foldPath = make(map[string]string) @@ -1677,9 +1682,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) } @@ -1919,9 +1925,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. @@ -2012,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 } @@ -2081,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. @@ -2193,6 +2203,229 @@ 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. +// +// 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() { + // 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 ...any) { + 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, + } + 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 { + if cfg.BuildASan { + appendSetting("-asan", "true") + } + if BuildAsmflags.present { + appendSetting("-asmflags", BuildAsmflags.String()) + } + appendSetting("-compiler", cfg.BuildContext.Compiler) + if BuildGccgoflags.present && cfg.BuildContext.Compiler == "gccgo" { + appendSetting("-gccgoflags", BuildGccgoflags.String()) + } + if BuildGcflags.present && cfg.BuildContext.Compiler == "gc" { + appendSetting("-gcflags", BuildGcflags.String()) + } + if BuildLdflags.present { + appendSetting("-ldflags", BuildLdflags.String()) + } + if cfg.BuildMSan { + appendSetting("-msan", "true") + } + 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_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: + // + // - -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 + const allowNesting = true + if cfg.BuildBuildvcs && p.Module != nil && p.Module.Version == "" && !p.Standard { + repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting) + 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, "", allowNesting) + 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, "", allowNesting) + 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 + } + + type vcsStatusError struct { + Status vcs.Status + Err error + } + cached := vcsStatusCache.Do(repoDir, func() any { + st, err := vcsCmd.Status(vcsCmd, repoDir) + return vcsStatusError{st, err} + }).(vcsStatusError) + if err := cached.Err; err != nil { + setVCSError(err) + return + } + st := cached.Status + + appendSetting("vcs", vcsCmd.Cmd) + if st.Revision != "" { + appendSetting("vcs.revision", st.Revision) + } + if !st.CommitTime.IsZero() { + stamp := st.CommitTime.UTC().Format(time.RFC3339Nano) + appendSetting("vcs.time", stamp) + } + appendSetting("vcs.modified", strconv.FormatBool(st.Uncommitted)) + } + + 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. @@ -2231,6 +2464,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 } @@ -2447,7 +2684,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 ( @@ -2673,10 +2911,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 { @@ -2704,7 +2939,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/load/test.go b/src/cmd/go/internal/load/test.go index c8282965669c56d330c68a2390ba51d8c39452b8..6122428c9cf0a2f066535fa025153ab0185da82e 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -555,6 +555,7 @@ func formatTestmain(t *testFuncs) ([]byte, error) { type testFuncs struct { Tests []testFunc Benchmarks []testFunc + FuzzTargets []testFunc Examples []testFunc TestMain *testFunc Package *Package @@ -653,6 +654,13 @@ 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}) + *doImport, *seen = true, true } } ex := doc.Examples(f) @@ -670,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 } @@ -716,6 +730,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}}}, @@ -774,7 +794,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/lockedfile/internal/filelock/filelock_fcntl.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go index a37b2ad6d184b0f89169e4e0e1d8ff5e396b8370..09354d23061ec78452c36398c6775bbfbfec7c9f 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 70f5d7a688a070e5381c7da252fcd153cda80fb6..491bec39af935468b0fb7541e5faeb3c1c4dcfae 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 908afb6c8cb7687d4d34545038b831e27434c2d8..54b2c946e0d6b2272e5758ac638e0bef49aa3e8e 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 640d4406f4200cd1e44c426421955678feb66f91..7bd7bd28f55ab7830fe9bb0e86327272877de5d5 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 878a1e770d4d42a754950bc86f21221446c20262..d7778d05de1884f88bcbdbbc13e30a26c86d43ba 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 dd27ce92bd8d617449952f0c792f7966d10d2b84..e2ca5383046bbe13bd3dd5bb7d3c43bcab190d22 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 e4923f68764dad89a06539bbffccbe112e645996..1a677a7fe4a60d3a98866a846bbd6e39b057cbe9 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 979118b10ae83d13d01064ca3eb896f5b6a38d48..35669388e0531318a8d3cdb65f2c992bccbe9e7d 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 3acc6695a748003e6f0fc7107bc49ffcf5995162..c9907db46cecb36e043a1ff8105ac386bcec9e95 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 b753346e7da50bccbb6d904a3f59c30648093153..3c1caa334eb4df6bbaec7f1dae4228286df11067 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/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index 0e5af852376e76c5363d595d15c55f18d4acd8f6..6b8a010fd9d71ca248b91a2ccd7375e3305f432a 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 @@ -66,6 +70,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,27 +86,68 @@ 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 { - base.Fatalf("go mod download: no modules specified (see 'go help mod download')") - } + modload.ExplicitWriteGoMod = true haveExplicitArgs := len(args) > 0 - if !haveExplicitArgs { - args = []string{"all"} - } - if modload.HasModRoot() { - modload.LoadModFile(ctx) // to fill Target - targetAtUpgrade := modload.Target.Path + "@upgrade" - targetAtPatch := modload.Target.Path + "@patch" - for _, arg := range args { - switch arg { - case modload.Target.Path, targetAtUpgrade, targetAtPatch: - os.Stderr.WriteString("go mod download: skipping argument " + arg + " that resolves to the main module\n") + + if modload.HasModRoot() || modload.WorkFilePath() != "" { + modload.LoadModFile(ctx) // to fill MainModules + + if haveExplicitArgs { + 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 { + 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) { var err error m.Info, err = modfetch.InfoFile(m.Path, m.Version) @@ -140,13 +186,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 { @@ -183,7 +232,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 != "" { @@ -193,7 +242,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() @@ -206,13 +255,15 @@ 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 // (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 bb3d5210926aef7993e93a8beb0fbd189859e399..e5182a9590adc866532d0dfde80130808706faad 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/graph.go b/src/cmd/go/internal/modcmd/graph.go index ac81f26dadea69dd3f58d7491caaa39aba7cfcad..9b6aa1fb14dddc5ade58f888a5bf01f2ba7ed140 100644 --- a/src/cmd/go/internal/modcmd/graph.go +++ b/src/cmd/go/internal/modcmd/graph.go @@ -42,11 +42,14 @@ 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") + 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 958c3066ac11082dee31fe8b0cc4f3f049124e5e..bc4620a2a8d3f2121145ee64038ba0329fda599d 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 fe25507e94f4fe365ec17d48b09e91be1109d702..d35476eb5393d3e92c6e61f384c99f5bf04463a7 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 != "" { @@ -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 713d5f9f3faa6ac9fb58dffc561c96d2dd5b1b70..ef123700aa3ca5ae8600f5b09bd84c4f4bc09a6d 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,22 +44,29 @@ 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) } 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 @@ -74,15 +81,23 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { } _, pkgs := modload.LoadPackages(ctx, loadOpts, "all") - vdir := filepath.Join(modload.ModRoot(), "vendor") + 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 mod vendor: %v", err) + base.Fatalf("go: %v", err) } 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) @@ -128,7 +143,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 := "" @@ -177,11 +193,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) } } @@ -242,14 +258,14 @@ 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) } } 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) @@ -260,21 +276,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) } } } @@ -353,7 +369,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() @@ -375,10 +391,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) { @@ -387,20 +403,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 5a6eca32cfb706bfcd50906937d9eec70e4fc4c4..3f0c005d5d91482c87d764f155168ed3a579151c 100644 --- a/src/cmd/go/internal/modcmd/verify.go +++ b/src/cmd/go/internal/modcmd/verify.go @@ -39,12 +39,15 @@ 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") + 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 3b14b27c8c780d954a133cd46dc4bee2f875e442..d8355cca957a460788b1f7f146679c79bdfe169c 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{ @@ -61,11 +59,14 @@ 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 + modload.ExplicitWriteGoMod = true // don't write go.mod in ListModules loadOpts := modload.PackageOpts{ Tags: imports.AnyTags(), @@ -78,28 +79,28 @@ 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) + 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/internal/modfetch/bootstrap.go b/src/cmd/go/internal/modfetch/bootstrap.go index ed694581a7c6af47ba12c789ece904fb15c1099c..e23669fb00c76b7bb5d6a1f20523051354f2f3f5 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/cache.go b/src/cmd/go/internal/modfetch/cache.go index b01b4674131e7af76436c5b5513b6dbc1c155cbe..c682447900fbc39a1d1ab8c21c1146c940c2f7f6 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. @@ -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/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go index 378fbae34f9530378ced67a8298f797891af9e72..4a0e2241e50ac828a92c5add57d174faa70ba6a9 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. @@ -243,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...) } @@ -251,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 4d4964edf447ebb7e963acd2c0defb74bb5957f6..34f453c855ef8d6b3dd7f6edbab34f30430b7c08 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) @@ -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} } @@ -496,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) @@ -516,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 - r.refsOnce.Do(r.loadRefs) - if r.refsErr != nil { - return nil, r.refsErr - } - for _, tag := range need { - if r.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/shell.go b/src/cmd/go/internal/modfetch/codehost/shell.go index 0e9f38196676b108a28c77e9c2d5b591ecb0ae02..eaa01950b95ef395e57ac6f8d85036c44b6ff911 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/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index c2cca084e3077a8b3f9627e8b212491c1baf06dd..de62265efc5a722abae770da0486ef04c2e5a205 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} @@ -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 diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go index dfef9f73c27aefa1bd3073706280a62f5cd8173e..79da010809b7407b12e2a1a823abb7ee3c022cce 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{ @@ -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) } } @@ -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 d3d30d970b3b979b14741ce2a2da38c8812a422c..12b7431570930c1e97f16734e309d6112473d951 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} @@ -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. @@ -693,19 +737,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 @@ -723,10 +769,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 } if _, ok := fsys.OverlayPath(GoSumFile); ok { base.Fatalf("go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay") @@ -747,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) } } @@ -765,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) } } @@ -774,11 +820,21 @@ 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 +} + +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 diff --git a/src/cmd/go/internal/modfetch/repo.go b/src/cmd/go/internal/modfetch/repo.go index 0bffa55af6f2ed6c4b12ec8363a8bb4f7f434bc6..1b42ecb6edb45c0ce6dcf8ee88fdcb047e061b61 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/modfetch/sumdb.go b/src/cmd/go/internal/modfetch/sumdb.go index f233cba6df1bb7e996735147834e9c40960158f4..492b03bd84ac8b6e0d3758accb79e614dd567fe2 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 @@ -201,7 +200,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 +220,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) diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 9672e5598e0d3a980570899a4770925effaee087..3d8463e892c69ad5fdd5cb7885a7d4b65d6e0893 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,17 +72,18 @@ 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 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. @@ -98,15 +98,9 @@ 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. +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. @@ -218,7 +212,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, "") @@ -263,30 +257,50 @@ 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) + } + // 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 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") } 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") } + 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. - 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. 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) @@ -356,74 +370,12 @@ 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 && pkg.Module.Path != modload.Target.Path { - haveExternalExe = true - break - } - } - if haveExternalExe { - fmt.Fprint(os.Stderr, "go get: 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 - } - // 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) @@ -440,7 +392,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 } @@ -455,11 +407,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 } } @@ -649,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]} @@ -675,7 +627,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 +640,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.QueryMatchesMainModulesError{MainModules: []module.Version{v}, Pattern: q.pattern, Query: q.version}) } return pathSet{mod: module.Version{Path: q.pattern, Version: "none"}} @@ -698,8 +652,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.QueryMatchesMainModulesError{MainModules: []module.Version{curM}, Pattern: q.pattern, Query: q.version}) } return pathSet{mod: module.Version{Path: curM.Path, Version: "none"}} }) @@ -718,28 +672,38 @@ 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())) + 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, modload.Target, imports.AnyTags()) + match := modload.MatchInModule(ctx, pkgPattern, mainModule, imports.AnyTags()) if len(match.Errs) > 0 { return pathSet{err: match.Errs[0]} } 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() { - 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{} } - return pathSet{pkgMods: []module.Version{modload.Target}} + return pathSet{pkgMods: []module.Version{mainModule}} }) } } @@ -789,11 +753,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, + return errSet(&modload.QueryMatchesMainModulesError{ + MainModules: []module.Version{curM}, + Pattern: q.pattern, + Query: q.version, }) } @@ -928,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) } @@ -1159,8 +1124,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 == "" { + // Packages in the standard library and main modules are already at their // latest (and only) available versions. return nil } @@ -1327,7 +1292,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 } @@ -1370,11 +1335,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 } @@ -1720,13 +1685,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) } } @@ -1744,10 +1709,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 { - reportError(q, &modload.QueryMatchesMainModuleError{ - Pattern: q.pattern, - Query: q.version, + if modload.MainModules.Contains(m.Path) && m.Version != "" { + reportError(q, &modload.QueryMatchesMainModulesError{ + MainModules: []module.Version{{Path: m.Path}}, + Pattern: q.pattern, + Query: q.version, }) return } @@ -1775,7 +1741,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}) } } @@ -1784,7 +1750,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 } @@ -1796,7 +1762,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 1a5a60f7eb98fb97454ded379eeff593e8df97da..887cb51b317f7f3c46db33192452197571467a09 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, } } } @@ -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/build.go b/src/cmd/go/internal/modload/build.go index 76e1ad589f43c1c6c12fed6faa038186a19453d7..bfc73cc2f9ab59238da44f0aefd58382295d04ea 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" @@ -80,7 +79,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 { @@ -212,20 +211,20 @@ 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 { + 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 } @@ -322,7 +321,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(replaceRelativeTo(), r.Path) } info.Replace.GoMod = filepath.Join(info.Replace.Dir, "go.mod") } @@ -336,115 +335,33 @@ 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 isStandardImportPath(path) || !Enabled() { - return "" - } - - target := mustFindModule(loaded, path, path) - mdeps := make(map[module.Version]bool) - for _, dep := range deps { - if !isStandardImportPath(dep) { - mdeps[mustFindModule(loaded, path, dep)] = 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)) - } - } - - writeEntry("mod", target) - for _, mod := range mods { - writeEntry("dep", mod) - } - - 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" { - return Target - } - - 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 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 - } return module.Version{}, false } 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/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index bf6956731676d39e66e74642f6a43b40607d619a..45be51f1c649cce2b8541d68b8d64300c9042db1 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -30,18 +30,25 @@ 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 - - // rootModules is the set of module versions explicitly required by the main - // module, sorted and capped to length. It may contain duplicates, and may - // contain multiple versions for a given module path. + // 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 []module.Version maxRootVersion map[string]string @@ -97,10 +104,23 @@ 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 { + 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 == 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)) @@ -114,7 +134,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, @@ -135,13 +155,18 @@ 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 module 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 - // 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 @@ -156,9 +181,9 @@ 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) + // 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 // from the vendor directory, and we don't actually know how we got from @@ -170,7 +195,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 +207,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 @@ -197,7 +222,7 @@ func (rs *Requirements) rootSelected(path string) (version string, ok bool) { // selection. func (rs *Requirements) hasRedundantRoot() bool { for i, m := range rs.rootModules { - if m.Path == Target.Path || (i > 0 && m.Path == rs.rootModules[i-1].Path) { + if MainModules.Contains(m.Path) || (i > 0 && m.Path == rs.rootModules[i-1].Path) { return true } } @@ -214,7 +239,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) @@ -230,7 +255,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 @@ -254,8 +279,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 { @@ -274,21 +307,26 @@ 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) + if pruning != workspace { + if inWorkspaceMode() { + panic("pruning is not workspace in workspace mode") + } + mg.g.Require(MainModules.mustGetSingleMainModule(), roots) + } 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{} { + cached := mg.loadCache.Do(m, func() any { summary, err := goModSummary(m) mu.Lock() @@ -305,15 +343,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 @@ -326,21 +364,25 @@ 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 != pruned || summary.pruning == unpruned { + nextPruning := summary.pruning + if pruning == unpruned { + nextPruning = unpruned + } for _, r := range summary.require { - enqueue(r, eager) + enqueue(r, nextPruning) } } }) } for _, m := range roots { - enqueue(m, depth) + enqueue(m, pruning) } <-loadQueue.Idle() @@ -351,8 +393,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. @@ -404,7 +445,12 @@ func (mg *ModuleGraph) findError() error { } func (mg *ModuleGraph) allRootsSelected() bool { - roots, _ := mg.g.RequiredBy(Target) + 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 @@ -427,12 +473,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) @@ -447,7 +493,8 @@ func LoadModGraph(ctx context.Context, goVersion string) *ModuleGraph { base.Fatalf("go: %v", err) } - commitRequirements(ctx, modFileGoVersion(), rs) + requirements = rs + return mg } @@ -455,9 +502,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. @@ -473,9 +519,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) @@ -513,7 +559,7 @@ func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (chang if err != nil { return false, err } - commitRequirements(ctx, modFileGoVersion(), rs) + requirements = rs return changed, err } @@ -544,23 +590,45 @@ 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) { - if rs.depth == eager { - return tidyEagerRoots(ctx, rs.direct, pkgs) + mainModule := MainModules.mustGetSingleMainModule() + if rs.pruning == unpruned { + return tidyUnprunedRoots(ctx, mainModule, rs.direct, pkgs) } - return tidyLazyRoots(ctx, 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) + 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 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 updateLazyRoots(ctx, direct, rs, pkgs, add, rootsImported) + return rs, nil } -// 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. @@ -568,16 +636,16 @@ 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 // 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 tidyPrunedRoots(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". // @@ -605,7 +673,7 @@ func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) queued[pkg] = true } module.Sort(roots) - tidy := newRequirements(lazy, roots, direct) + tidy := newRequirements(pruned, roots, direct) for len(queue) > 0 { roots = tidy.rootModules @@ -641,7 +709,7 @@ func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) if len(roots) > len(tidy.rootModules) { module.Sort(roots) - tidy = newRequirements(lazy, roots, tidy.direct) + tidy = newRequirements(pruned, roots, tidy.direct) } } @@ -652,8 +720,8 @@ func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) 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. @@ -670,7 +738,7 @@ func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) // 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 @@ -690,13 +758,13 @@ func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) // 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 @@ -717,11 +785,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 @@ -732,17 +800,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: @@ -807,16 +876,15 @@ 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 - // 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 { @@ -831,7 +899,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 @@ -855,7 +923,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 @@ -908,12 +978,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 @@ -955,17 +1025,37 @@ func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Versi return true } -// 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) { +// 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() { @@ -979,16 +1069,48 @@ func tidyEagerRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg inRootPaths[m.Path] = true } } + for _, m := range pkg.altMods { + altMods[m.Path] = m.Version + } } - min, err := mvs.Req(Target, 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 } - return newRequirements(eager, min, direct), nil + 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 } -// 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. // @@ -1002,7 +1124,7 @@ func tidyEagerRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg // 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 @@ -1011,7 +1133,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 { @@ -1067,10 +1189,10 @@ 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()[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) @@ -1078,44 +1200,53 @@ 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 + 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) { - // The root set is unchanged and rs was already eager, so keep rs to + if MainModules.Len() > 1 { + module.Sort(roots) + } + 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, min, 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 + } else if rs.pruning == workspace || pruning == workspace { + panic("attempthing to convert to/from workspace pruning and another pruning type") } - 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()[1:], 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 c350b9d1b5c571ed0e0754a07ad58fa3c9b26fe9..0f37e3b2e94773e983fc70f161ea2c768d759833 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,13 +69,14 @@ 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 m.Version != "none" && m.Path != Target.Path { + if m.Version != "none" && !MainModules.Contains(m.Path) { rootPaths = append(rootPaths, m.Path) } } @@ -97,13 +98,13 @@ 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 } } 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,22 +187,22 @@ 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 // 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 -// 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,51 +215,88 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d } } - var eagerUpgrades []module.Version - if depth == eager { - eagerUpgrades = tryUpgrade + 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 { - if m.Path == Target.Path { - // Target is 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 + 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 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 } - 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) - continue + unprunedUpgrades = append(unprunedUpgrades, m) + return nil } - 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) } } - 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 { - 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 } @@ -268,16 +307,41 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d } } - if len(mustSelect) > 0 { - mustGraph, err := readModGraph(ctx, depth, 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) + } } } @@ -301,12 +365,12 @@ 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 } - initial = mg.BuildList()[1:] + initial = mg.BuildList()[MainModules.Len():] } else { initial = rs.rootModules } @@ -318,7 +382,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}) } } @@ -328,13 +392,13 @@ 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 } 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}) } @@ -350,16 +414,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 @@ -411,14 +475,18 @@ 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: map[string]string{Target.Path: Target.Version}, + selected: selected, dqReason: map[module.Version]dqState{}, requiring: map[module.Version][]module.Version{}, } @@ -427,8 +495,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 { @@ -440,7 +508,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, @@ -457,7 +525,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. @@ -474,7 +542,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 } @@ -484,15 +552,15 @@ 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 m.Version == "none" || m == Target { +// 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. return dqState{} @@ -522,20 +590,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.go b/src/cmd/go/internal/modload/import.go index d2bbe5cbe0b1eae58ac5a041792d0b4d0e8a3c85..812e48a1568f16e62ac33f07a90f8e4d9d8595e7 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 + 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 // directives can cause us to treat the replaced paths as also being in @@ -71,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) } @@ -238,55 +243,63 @@ 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? 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, nil, err + } else if ok { + 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. // 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}} + 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 Target, mainDir, nil + return mainModule, mainDir, nil, nil } if mainErr != nil { - return module.Version{}, "", mainErr + return module.Version{}, "", nil, mainErr } - readVendorList() - return vendorPkgModule[path], vendorDir, nil + readVendorList(mainModule) + return vendorPkgModule[path], vendorDir, nil, nil } // Check each module on the build list. @@ -307,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 @@ -341,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) } } @@ -360,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 { @@ -368,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, @@ -376,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 { @@ -386,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. @@ -397,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 } } } @@ -410,9 +425,9 @@ 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 { + var mods []module.Version + 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 } @@ -439,40 +454,41 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver } 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. + replacement := Replacement(mods[0]) + return module.Version{}, &PackageNotInModuleError{ + Mod: mods[0], + Query: "latest", + Pattern: path, + Replacement: replacement, } } @@ -596,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) @@ -619,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) @@ -638,14 +654,14 @@ 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 == "" { dir = r.Path if !filepath.IsAbs(dir) { - dir = filepath.Join(ModRoot(), dir) + dir = filepath.Join(replaceRelativeTo(), dir) } // Ensure that the replacement directory actually exists: // dirInModule does not report errors for missing modules, @@ -667,7 +683,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/import_test.go b/src/cmd/go/internal/modload/import_test.go index 98145887e9dcc5c6b18aa071f08c27ce7c4681ca..65a889ec52f11c8355085050833b82ccfee56ddd 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 := 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 45f724d5e3658f5d21d757d7a955b24af6b89be9..df083e7fcca05475be6b676a767022f1aeca5b86 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -12,11 +12,13 @@ import ( "fmt" "go/build" "internal/lazyregexp" + "io/ioutil" "os" "path" "path/filepath" "strconv" "strings" + "sync" "cmd/go/internal/base" "cmd/go/internal/cfg" @@ -43,28 +45,197 @@ 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 ) // Variables set in Init. var ( initialized bool - modRoot string - gopath 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). +// 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 ( - Target module.Version + // 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 + // fields are empty strings. + versions []module.Version + + // modRoot maps each module in versions to its absolute filesystem path. + modRoot map[module.Version]string - // targetPrefix is the path prefix for packages in Target, without a trailing - // slash. For most modules, targetPrefix is just Target.Path, but the + // 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 + + modFiles map[module.Version]*modfile.File + + modContainingCWD module.Version + + 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 +} + +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 { + 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 { + 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] +} + +func (mms *MainModuleSet) GetSingleIndexOrNil() *modFileIndex { + if mms == nil { + return nil + } + if len(mms.versions) == 0 { + return nil + } + return mms.indices[mms.mustGetSingleMainModule()] +} + +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 + } + 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 +} + +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 { + 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 +} + +func (mms *MainModuleSet) WorkFileReplaceMap() map[module.Version]module.Version { + return mms.workFileReplaceMap +} + +var MainModules *MainModuleSet type Root int @@ -94,6 +265,7 @@ const ( // in go.mod, edit it before loading. func ModFile() *modfile.File { Init() + modFile := MainModules.ModFile(MainModules.mustGetSingleMainModule()) if modFile == nil { die() } @@ -102,9 +274,38 @@ func ModFile() *modfile.File { func BinDir() string { Init() + if cfg.GOBIN != "" { + return cfg.GOBIN + } + if gopath == "" { + return "" + } 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: + if !filepath.IsAbs(cfg.WorkFile) { + base.Fatalf("the path provided to -workfile must be an absolute path") + } + workFilePath = cfg.WorkFile + } +} + +// 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 @@ -169,18 +370,18 @@ 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 if inWorkspaceMode() { + // We're in workspace mode. } else { - modRoot = findModuleRoot(base.Cwd()) - if modRoot == "" { + 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.") } @@ -198,11 +399,12 @@ func Init() { // 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 = "" 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") { @@ -213,35 +415,11 @@ func Init() { cfg.ModulesEnabled = true setDefaultBuildMod() 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 modRoot == "" { - // 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(), ".mod") + ".sum" - search.SetModRoot(modRoot) + 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") + } } } @@ -255,7 +433,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 } @@ -297,16 +475,18 @@ 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. -// It calls base.Fatalf if there is no main module. -func ModRoot() string { - if !HasModRoot() { - die() +func VendorDir() string { + return filepath.Join(MainModules.ModRoot(MainModules.mustGetSingleMainModule()), "vendor") +} + +func inWorkspaceMode() bool { + if !initialized { + panic("inWorkspaceMode called before modload.Init called") } - return modRoot + return workFilePath != "" } // HasModRoot reports whether a main module is present. @@ -314,17 +494,27 @@ 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 -// "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 -// module, even if -modfile is set. -func ModFilePath() string { +// 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 { + MustHaveModRoot() + return modFilePath(findModuleRoot(base.Cwd())) +} + +func modFilePath(modRoot string) string { if cfg.ModFile != "" { return cfg.ModFile } @@ -335,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 { @@ -365,12 +558,81 @@ func (goModDirtyError) Error() string { var errGoModDirty error = goModDirtyError{} +func loadWorkFile(path string) (goVersion string, modRoots []string, replaces []*modfile.Replace, err error) { + workDir := filepath.Dir(path) + wf, err := ReadWorkFile(path) + if err != nil { + return "", nil, nil, err + } + if wf.Go != nil { + goVersion = wf.Go.Version + } + seen := map[string]bool{} + for _, d := range wf.Use { + modRoot := d.Path + 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 + } + + return modfile.ParseWork(path, workData, 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.Use { + 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.AddUse(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. // // 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. @@ -383,111 +645,142 @@ var errGoModDirty error = goModDirtyError{} // 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, modFileGoVersion(), 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() - if modRoot == "" { - Target = module.Version{Path: "command-line-arguments"} - targetPrefix = "command-line-arguments" - goVersion := LatestGoVersion() - rawGoVersion.Store(Target, goVersion) - requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil) - return requirements, false - } - - gomod := ModFilePath() - 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) + 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) + } + 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. + // + // 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 { - data, err = lockedfile.Read(gomodActual) - } - if err != nil { - base.Fatalf("go: %v", err) + modfetch.GoSumFile = strings.TrimSuffix(modFilePath(modRoots[0]), ".mod") + ".sum" + } + if len(modRoots) == 0 { + // 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() + rawGoVersion.Store(mainModule, goVersion) + pruning := pruningForGoVersion(goVersion) + if inWorkspaceMode() { + pruning = workspace + } + requirements = newRequirements(pruning, nil, nil) + return requirements } - 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 modFiles []*modfile.File + var mainModules []module.Version + var indices []*modFileIndex + for _, modroot := range modRoots { + gomod := modFilePath(modroot) + var fixed bool + data, f, err := ReadModFile(gomod, fixVersion(ctx, &fixed)) + if err != nil { + base.Fatalf("go: %v", err) + } - modFile = f - initTarget(f.Module.Mod) - index = indexModFile(data, f, fixed) + modFiles = append(modFiles, f) + mainModule := f.Module.Mod + mainModules = append(mainModules, mainModule) + 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 { - 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, modFiles, indices, workFileGoVersion, workFileReplaces) setDefaultBuildMod() // possibly enable automatic vendoring - rs = requirementsFromModFile() + rs := requirementsFromModFiles(ctx, modFiles) + + if inWorkspaceMode() { + // We don't need to do anything for vendor or update the mod file so + // return early. + requirements = rs + return rs + } + + mainModule := MainModules.mustGetSingleMainModule() + if cfg.BuildMod == "vendor" { - readVendorList() - checkVendorConsistency() + readVendorList(mainModule) + index := MainModules.Index(mainModule) + modFile := MainModules.ModFile(mainModule) + checkVendorConsistency(index, modFile) rs.initVendor(vendorList) } + if rs.hasRedundantRoot() { // If any module path appears more than once in the roots, we know that the // go.mod file needs to be updated even though we have not yet loaded any // transitive dependencies. + var err error rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false) if err != nil { base.Fatalf("go: %v", err) } } - if index.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" { - addGoStmt(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. - rs, err = convertDepth(ctx, rs, lazy) - if err != nil { - base.Fatalf("go: %v", err) - } + addGoStmt(MainModules.ModFile(mainModule), mainModule, LatestGoVersion()) + + // 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 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 = convertPruning(ctx, rs, pruned) + if err != nil { + base.Fatalf("go: %v", err) } } else { - rawGoVersion.Store(Target, modFileGoVersion()) + rawGoVersion.Store(mainModule, modFileGoVersion(MainModules.ModFile(mainModule))) } } requirements = rs - return requirements, true + return requirements } // CreateModFile initializes a new module by creating a go.mod file. @@ -500,9 +793,10 @@ 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() + modFilePath := modFilePath(modRoot) if _, err := fsys.Stat(modFilePath); err == nil { base.Fatalf("go: %s already exists", modFilePath) } @@ -523,15 +817,22 @@ 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) - modFile = new(modfile.File) + 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}, []*modfile.File{modFile}, []*modFileIndex{nil}, "", nil) + addGoStmt(modFile, modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements. - convertedFrom, err := convertLegacyConfig(modPath) + convertedFrom, err := convertLegacyConfig(modFile, modRoot) if convertedFrom != "" { fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(convertedFrom)) } @@ -539,12 +840,15 @@ func CreateModFile(ctx context.Context, modPath string) { base.Fatalf("go: %v", err) } - rs := requirementsFromModFile() + rs := requirementsFromModFiles(ctx, []*modfile.File{modFile}) rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false) if err != nil { base.Fatalf("go: %v", err) } - commitRequirements(ctx, modFileGoVersion(), 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 @@ -570,6 +874,32 @@ 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) { + 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) + workF.Syntax = new(modfile.FileSyntax) + workF.AddGoStmt(goV) + + for _, dir := range modDirs { + _, 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.AddUse(ToDirectoryPath(dir), f.Module.Mod.Path) + } + + UpdateWorkFile(workF) + WriteWorkFile(workFile, workF) +} + // fixVersion returns a modfile.VersionFixer implemented using the Query function. // // It resolves commit hashes and branch names to versions, @@ -632,49 +962,118 @@ 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, 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)) + } + } + 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, + 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 + mainModules.modRoot[m] = rootDirs[i] + 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" { + // 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] = "" + } + } + + 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] && prev != r.New { + 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 + + 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 } -// requirementsFromModFile returns the set of non-excluded requirements from +// requirementsFromModFiles returns the set of non-excluded requirements from // the global modFile. -func requirementsFromModFile() *Requirements { - roots := make([]module.Version, 0, len(modFile.Require)) +func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Requirements { + var roots []module.Version 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) - } - continue + 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 { + 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) - if !r.Indirect { - direct[r.Mod.Path] = true + roots = append(roots, r.Mod) + if !r.Indirect { + direct[r.Mod.Path] = true + } } } module.Sort(roots) - rs := newRequirements(modDepthFromGoVersion(modFileGoVersion()), roots, direct) + rs := newRequirements(pruning, roots, direct) return rs } @@ -682,18 +1081,35 @@ func requirementsFromModFile() *Requirements { // wasn't provided. setDefaultBuildMod may be called multiple times. func setDefaultBuildMod() { if cfg.BuildModExplicit { + if inWorkspaceMode() && cfg.BuildMod != "readonly" { + 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 } - 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", "work sync": + // 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" return + case "mod vendor": + cfg.BuildMod = "readonly" + return } - if modRoot == "" { + if modRoots == nil { if allowMissingModuleImports { cfg.BuildMod = "mod" } else { @@ -702,31 +1118,38 @@ 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 { + index := MainModules.GetSingleIndexOrNil() + 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" } +func mustHaveCompleteRequirements() bool { + return cfg.BuildMod != "mod" && !inWorkspaceMode() +} + // 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, 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) @@ -757,14 +1180,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(modFile *modfile.File, 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 @@ -815,7 +1238,7 @@ var altConfigs = []string{ ".git/config", } -func findModuleRoot(dir string) (root string) { +func findModuleRoot(dir string) (roots string) { if dir == "" { panic("dir not set") } @@ -835,6 +1258,33 @@ func findModuleRoot(dir string) (root string) { return "" } +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 { + // 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 + } + return "" +} + func findAltConfig(dir string) (root, name string) { if dir == "" { panic("dir not set") @@ -960,66 +1410,62 @@ 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, modFileGoVersion(), 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. -func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) { - requirements = rs - - if !allowWriteGoMod { - // Some package outside of modload promised to update the go.mod file later. - return - } - - if modRoot == "" { +// 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. + 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() + 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 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) } modFile.Cleanup() + index := MainModules.GetSingleIndexOrNil() dirty := index.modFileIsDirty(modFile) 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" { @@ -1028,30 +1474,33 @@ 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, requirements, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { + return err + } } - return + return nil } - 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") + 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. - index = indexModFile(new, modFile, 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. if cfg.CmdName != "mod init" { - modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums)) + if err == nil { + err = modfetch.WriteGoSum(keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()) + } } }() @@ -1063,7 +1512,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. @@ -1084,8 +1533,9 @@ func commitRequirements(ctx context.Context, goVersion string, 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 @@ -1113,16 +1563,18 @@ 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} - keep[resolveReplacement(m)] = true + r := resolveReplacement(m) + keep[r] = true } } continue @@ -1133,15 +1585,15 @@ 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 } } } } 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 { @@ -1158,13 +1610,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 } } } @@ -1184,3 +1638,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/internal/modload/list.go b/src/cmd/go/internal/modload/list.go index ccdeb9b1d11e8650ec420169723ba7d1aae4c2ba..f782cd93db3d25d2258303fc22239c09156ff1c8 100644 --- a/src/cmd/go/internal/modload/list.go +++ b/src/cmd/go/internal/modload/list.go @@ -72,14 +72,21 @@ func ListModules(ctx context.Context, args []string, mode ListMode) ([]*modinfo. } if err == nil { - commitRequirements(ctx, modFileGoVersion(), rs) + requirements = rs + if !ExplicitWriteGoMod { + err = commitRequirements(ctx) + } } return mods, err } 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 @@ -101,7 +108,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) @@ -110,7 +117,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 bce9ad85f42e6c593724c6e05bbfb31db6b57521..617b634d263e335946ef51ee84a26eb0cb0dc4d8 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.) // @@ -230,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 @@ -255,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. @@ -274,7 +282,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 +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, []module.Version{Target}) + 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". @@ -324,7 +338,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, @@ -365,7 +379,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. @@ -384,7 +398,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) @@ -393,7 +407,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 @@ -401,13 +415,24 @@ 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) + } + } + + // 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. + // 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.GoVersion, loaded.requirements) + requirements = loaded.requirements for _, pkg := range ld.pkgs { if !pkg.isTest() { @@ -415,12 +440,19 @@ 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 } // 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())) } @@ -436,14 +468,23 @@ 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 _, mainModuleRoot := range modRoots { + if mainModuleRoot == 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 } } - m.MatchDirs() + m.MatchDirs(modRoots) } // resolveLocalPackage resolves a filesystem path to a package path. @@ -485,49 +526,69 @@ 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(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) + } + 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{MainModules: []module.Version{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, "@") { @@ -560,7 +621,7 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string if repl := Replacement(m); repl.Path != "" && repl.Version == "" { root = repl.Path if !filepath.IsAbs(root) { - root = filepath.Join(ModRoot(), root) + root = filepath.Join(replaceRelativeTo(), root) } } else if repl.Path != "" { root, err = modfetch.DownloadDir(repl) @@ -583,7 +644,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. @@ -596,9 +657,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. @@ -645,14 +706,14 @@ func ImportFromFiles(ctx context.Context, gofiles []string) { return roots }, }) - commitRequirements(ctx, loaded.GoVersion, loaded.requirements) + requirements = loaded.requirements } // 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 +723,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{} } // ImportMap returns the actual package import path @@ -783,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 { @@ -807,6 +883,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 @@ -894,10 +971,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") @@ -915,10 +989,10 @@ 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()) + ld.errorf("go: go.mod file indicates go %s, but maximum version supported by tidy is %s\n", ld.GoVersion, LatestGoVersion()) base.ExitIfErrors() } } @@ -935,18 +1009,30 @@ 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)) + 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) } - 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 { @@ -963,7 +1049,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 @@ -1005,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 @@ -1074,15 +1160,15 @@ 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 { - 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() } } @@ -1124,8 +1210,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: // @@ -1168,7 +1253,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 { @@ -1176,6 +1261,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. @@ -1206,14 +1309,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 @@ -1283,7 +1386,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 } @@ -1327,6 +1430,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 @@ -1380,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, } @@ -1425,7 +1537,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. @@ -1446,7 +1558,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. @@ -1485,7 +1597,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 { @@ -1511,7 +1623,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 @@ -1573,7 +1686,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 { @@ -1589,11 +1702,11 @@ 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 } - 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. @@ -1698,13 +1811,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. // @@ -1781,7 +1895,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 } @@ -1813,7 +1927,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 } @@ -1847,7 +1961,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} @@ -1900,9 +2014,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 @@ -1940,18 +2055,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 03e02e73b63f659f0ec6e3eff89299f691763c6d..ec3f57ae3e1da513ae6a3832489beb8f49d0460c 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 @@ -44,23 +47,37 @@ const ( separateIndirectVersionV = "v1.17" ) -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. - go117LazyTODO = false -) +// 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 + } -var modFile *modfile.File + 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 intepreted, or the latest Go version if modFile is nil. -func modFileGoVersion() string { +// in modFile are interpreted, or the latest Go version if modFile is nil. +func modFileGoVersion(modFile *modfile.File) string { if modFile == nil { return LatestGoVersion() } @@ -71,9 +88,9 @@ func modFileGoVersion() 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,39 +99,37 @@ func modFileGoVersion() 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 } -// 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 } -// 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 + workspace // pruned to the union of modules in the workspace ) -func modDepthFromGoVersion(goVersion string) modDepth { - if !go117EnableLazyLoading { - return eager - } - 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 @@ -137,8 +152,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 } @@ -306,23 +323,74 @@ func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string return summary.deprecated, nil } -// 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, 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 := replace[module.Version{Path: mod.Path}]; ok { + return "", r, true + } + return "", module.Version{}, false +} + +// 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 { - 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 + 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.replace); ok { + modRoot := MainModules.ModRoot(v) + if foundModRoot != "" && foundFrom != from && found != r { + base.Errorf("conflicting replacements found for %v in workspace modules defined by %v and %v", + mod, modFilePath(foundModRoot), modFilePath(modRoot)) + return canonicalizeReplacePath(found, foundModRoot) + } + found, foundModRoot = r, modRoot + } } } - return module.Version{} + 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(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, + // 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 { if r := Replacement(m); r.Path != "" { return r @@ -330,10 +398,21 @@ func resolveReplacement(m module.Version) module.Version { 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 replaceMap +} + // 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 @@ -345,12 +424,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)) @@ -358,21 +437,7 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd 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 { @@ -465,7 +530,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 @@ -490,8 +555,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 == "" && !inWorkspaceMode() && MainModules.Contains(m.Path) { + panic("internal error: goModSummary called on a main module") } if cfg.BuildMod == "vendor" { @@ -506,7 +571,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. @@ -515,7 +580,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) @@ -553,27 +618,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 @@ -584,16 +651,20 @@ func goModSummary(m module.Version) (*modFileSummary, error) { // its dependencies. // // 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") } + type key struct { + m module.Version + } type cached struct { summary *modFileSummary err error } - c := rawGoModSummaryCache.Do(m, func() interface{} { + c := rawGoModSummaryCache.Do(key{m}, func() any { summary := new(modFileSummary) name, data, err := rawGoModData(m) if err != nil { @@ -610,9 +681,9 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) { 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)) @@ -648,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(ModRoot(), 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 { @@ -690,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() @@ -718,3 +794,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/internal/modload/mvs.go b/src/cmd/go/internal/modload/mvs.go index 87619b4ace68e28d40621054ab4d437a4b97cf83..588bcf4bdc26453b41e53d2562ecbe66088ee0f3 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 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 m == Target { + if m.Version == "" && 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 e737ca90fcd79d911f741b7fc43e1aa663b97d4b..33808ea1097a7f3dc0f1b06a197fde3a09900eb6 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" { @@ -512,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, } @@ -551,7 +553,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 +561,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 +595,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 +608,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,16 +631,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 { - return nil, nil, &QueryMatchesMainModuleError{ - Pattern: pattern, - Query: query, + } else if len(mainModuleMatches) != 0 { + return nil, nil, &QueryMatchesMainModulesError{ + MainModules: mainModuleMatches, + Pattern: pattern, + Query: query, } } else { return nil, nil, &PackageNotInModuleError{ - Mod: Target, - Query: query, - Pattern: pattern, + MainModules: mainModuleMatches, + Query: query, + Pattern: pattern, } } } @@ -656,15 +663,16 @@ 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 { return r, err } + replacement := Replacement(r.Mod) return r, &PackageNotInModuleError{ Mod: r.Mod, - Replacement: Replacement(r.Mod), + Replacement: replacement, Query: query, Pattern: pattern, } @@ -684,8 +692,8 @@ 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) { - return nil, nil, &QueryMatchesMainModuleError{ + if len(mainModuleMatches) > 0 && len(results) == 0 && modOnly == nil && errors.Is(err, fs.ErrNotExist) { + return nil, nil, &QueryMatchesMainModulesError{ 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: @@ -878,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 @@ -885,11 +899,15 @@ type PackageNotInModuleError struct { } func (e *PackageNotInModuleError) Error() string { - if e.Mod == Target { + 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", Target.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", Target.Path, e.Pattern) + return fmt.Sprintf("%s not contain package %s", prefix, e.Pattern) } found := "" @@ -978,14 +996,13 @@ 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 { + if MainModules == nil { return repo, err + } else if _, ok := MainModules.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. @@ -1024,11 +1041,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) + } } } } @@ -1046,7 +1065,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 } @@ -1073,26 +1101,24 @@ 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") - } + 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 + // 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) - } + if err != nil || semver.Compare(v, info.Version) > 0 { + return rr.replacementStat(v) } } @@ -1108,20 +1134,46 @@ 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 { - Pattern string - Query string +type QueryMatchesMainModulesError struct { + MainModules []module.Version + Pattern string + Query string } -func (e *QueryMatchesMainModuleError) Error() string { - if e.Pattern == Target.Path { +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, Target.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 +// 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 658fc6f55a9c9bb127e600f3d5ef51ffeb8c9773..799c48e50a8caca851b197c1ee584411bf2ad55c 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/stat_openfile.go b/src/cmd/go/internal/modload/stat_openfile.go index 368f893198492984b0cc1efaffe988d5f172c5d5..ff7c124af58a28c6da3ddfe48d144f935a1afdfb 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 e079d7399026feb44091d94973cfe0eeb6da9f05..8a3653ba80b019ae0394540b2291cffe21699850 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 825e60b27af89406122aa400b92df706aba508d5..f29a99165e53001faec5e8553e670a82803522dc 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/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index 80713b0812eacce928f0a39b26eba024e655a56b..5ea82a862083fdd76ed81f0b63ccac63abb88ef9 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" ) @@ -35,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) @@ -134,8 +135,8 @@ 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() { - readVendorList() +func checkVendorConsistency(index *modFileIndex, modFile *modfile.File) { + readVendorList(MainModules.mustGetSingleMainModule()) pre114 := false if semver.Compare(index.goVersionV, "v1.14") < 0 { @@ -146,7 +147,7 @@ func checkVendorConsistency() { } 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) @@ -219,6 +220,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 6969f90f2e681abf23495ab7aab8ba4432453d17..d25d447b0ee397fb603280be92e8b245a402f0d0 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,8 +111,10 @@ 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) - work.Do(10, func(item interface{}) { + for _, target := range targets { + work.Add(target) + } + work.Do(10, func(item any) { m := item.(module.Version) var required []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 598ed666889517a112c01e78d5b6fcb95101fcd2..26d004fee2856ebb2a19cf27033d753b01e11c8d 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/par/work.go b/src/cmd/go/internal/par/work.go index 960cec6fb16994ea9ef028b9e1b9d2b797f35a19..496c41b1509281bcea9b1ba5abfda1effe605e4f 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 f104bc4106f208bc2fac5ce36955a971e5e9f064..add0e640d8c093423e16c1a3fae1cd2b208bd137 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/robustio/robustio_flaky.go b/src/cmd/go/internal/robustio/robustio_flaky.go index d5c241857b476c47cfed2c9bb1c5b1f739426ee3..c56e36ca62412aae46a98f41f5a2d9ad5191fe8e 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 3a20cac6cf88aef9882a484439c2298489a80e2f..da9a46e4face362eb5d95872bccc2ecd4a7a5424 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/run/run.go b/src/cmd/go/internal/run/run.go index 784f7162dfd3f5b01bbd7c60a89975a9e3e5f1aa..c4b70b64fe651b6bed5a3b8b5bcc8a6d0d33c0a1 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -65,14 +65,17 @@ 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", "") } -func printStderr(args ...interface{}) (int, error) { +func printStderr(args ...any) (int, error) { return fmt.Fprint(os.Stderr, args...) } 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 @@ -100,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) @@ -111,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}) @@ -151,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/search/search.go b/src/cmd/go/internal/search/search.go index a0c806a259329c27c2f45739e1250550bec04f06..ebd4990a68413b2b03476f0305fff05924db2093 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 diff --git a/src/cmd/go/internal/str/path.go b/src/cmd/go/internal/str/path.go index 51ab2af82b58a6b42f5fc9eaa5e855d8de6fa5b4..0c8aaeaca1fba0f5f2cbc0d27c2262d8d43932f5 100644 --- a/src/cmd/go/internal/str/path.go +++ b/src/cmd/go/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/cmd/go/internal/str/str.go b/src/cmd/go/internal/str/str.go index 9106ebf74d5e31cb04e7deddf26e1a72ff6e9c74..021bfbff779162b14a7882cbc1e7b63da9fd929b 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) { @@ -109,47 +109,3 @@ func Uniq(ss *[]string) { } *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 -} diff --git a/src/cmd/go/internal/str/str_test.go b/src/cmd/go/internal/str/str_test.go index 147ce1a63ef32d89a537f49e8fb601a70387dbe5..8ea758e0a8b64bf0c8e4314660f9b79050fb4383 100644 --- a/src/cmd/go/internal/str/str_test.go +++ b/src/cmd/go/internal/str/str_test.go @@ -4,7 +4,9 @@ package str -import "testing" +import ( + "testing" +) var foldDupTests = []struct { list []string diff --git a/src/cmd/go/internal/test/flagdefs.go b/src/cmd/go/internal/test/flagdefs.go index 37ac81c26782ae226be515bc2f65a42700de978d..1b79314eff365889fa9b4b1cb9b221e91abfbd49 100644 --- a/src/cmd/go/internal/test/flagdefs.go +++ b/src/cmd/go/internal/test/flagdefs.go @@ -19,6 +19,9 @@ var passFlagToTest = map[string]bool{ "cpu": true, "cpuprofile": true, "failfast": true, + "fuzz": true, + "fuzzminimizetime": true, + "fuzztime": true, "list": true, "memprofile": true, "memprofilerate": true, @@ -33,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 ab5440b3801f15af1124d3ce1738035a894926a0..40dc558e9080c01bf1ae8ea0208d07775b2f30dd 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" ) @@ -17,7 +19,7 @@ func TestPassFlagToTestIncludesAllTestFlags(t *testing.T) { } name := strings.TrimPrefix(f.Name, "test.") switch name { - case "testlogfile", "paniconexit0": + case "testlogfile", "paniconexit0", "fuzzcachedir", "fuzzworker": // These are internal flags. default: if !passFlagToTest[name] { @@ -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 9277de7fee839e216f8c70b31b8720d839f16c5e..10f290090c7cf8e92420c8f61dae4ca559d926d0 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 @@ -16,6 +15,8 @@ import ( "strings" "testing" "text/template" + + "cmd/go/internal/test/internal/genflags" ) func main() { @@ -25,9 +26,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 } @@ -64,7 +74,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) @@ -85,7 +95,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 0000000000000000000000000000000000000000..2195cc34479f31bc611860fa9cdfecbbcc5744f3 --- /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/test.go b/src/cmd/go/internal/test/test.go index 59ea1ef5445178f052006dd37af2d8b0b209b9ef..50e6d5201b0d6e04cc59a3289d30fa8b4e1cb2b0 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -29,11 +29,15 @@ 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" "cmd/go/internal/work" + "cmd/internal/sys" "cmd/internal/test2json" + + "golang.org/x/mod/module" ) // Break init loop. @@ -60,8 +64,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 +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. @@ -78,7 +82,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 @@ -119,16 +124,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: @@ -206,9 +211,10 @@ 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 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 tests matched by -fuzz. -cover Enable coverage analysis. @@ -235,32 +241,67 @@ 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 - of GOMAXPROCS. + Specify a list of GOMAXPROCS values for which the tests, benchmarks or + 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 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 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 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 + 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 - list top-level tests. No subtest or subbenchmarks will be shown. + 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. + Allow parallel execution of test functions that call t.Parallel, and + 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; 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 (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 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 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, @@ -273,11 +314,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. @@ -373,7 +414,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, @@ -430,6 +475,10 @@ A benchmark function is one named BenchmarkXxx and should have the signature, func BenchmarkXxx(b *testing.B) { ... } +A fuzz test 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,7 +518,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 test or benchmark functions. +declaration, and no tests, benchmarks, or fuzz tests. See the documentation of the testing package for more information. `, @@ -483,6 +532,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 @@ -578,6 +628,7 @@ var defaultVetFlags = []string{ func runTest(ctx context.Context, cmd *base.Command, args []string) { pkgArgs, testArgs = testFlags(args) + modload.InitWorkfile() // The test command does custom flag processing; initialize workspaces after that. if cfg.DebugTrace != "" { var close func() error @@ -615,6 +666,52 @@ 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 != "" { + 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 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 + // 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()) } @@ -625,7 +722,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 } @@ -649,7 +748,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) @@ -775,6 +874,41 @@ 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. + 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 skipInstrumentation = map[string]bool{ + "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 !skipInstrumentation[p.ImportPath] { + p.Internal.FuzzInstrument = true + } + } + } + + // 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 @@ -782,7 +916,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") @@ -849,7 +983,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}} @@ -877,6 +1011,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", @@ -1080,6 +1224,8 @@ func declareCoverVars(p *load.Package, files ...string) map[string]*load.CoverVa } var noTestsToRun = []byte("\ntesting: warning: no tests to run\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 @@ -1127,10 +1273,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 @@ -1183,7 +1329,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. @@ -1276,15 +1427,31 @@ 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, noFuzzTestsToFuzz[1:]) || bytes.Contains(out, noFuzzTestsToFuzz) { + norun = " [no fuzz tests to fuzz]" + } + 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" + // 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, @@ -1347,6 +1514,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, @@ -1711,9 +1879,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/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index 08f1efa2c0d26a0cf398f2b778c0adde90fc97ae..b9d1ec91ff7552aba0e1667d96f16d55349931a5 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 @@ -29,6 +28,7 @@ import ( func init() { work.AddBuildFlags(CmdTest, work.OmitVFlag) + base.AddWorkfileFlag(&CmdTest.Flag) cf := CmdTest.Flag cf.BoolVar(&testC, "c", false, "") @@ -57,6 +57,7 @@ func init() { cf.String("cpu", "", "") cf.StringVar(&testCPUProfile, "cpuprofile", "", "") cf.Bool("failfast", false, "") + cf.StringVar(&testFuzz, "fuzz", "", "") cf.StringVar(&testList, "list", "", "") cf.StringVar(&testMemProfile, "memprofile", "", "") cf.String("memprofilerate", "", "") @@ -67,6 +68,8 @@ func init() { cf.String("run", "", "") 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", "") @@ -134,6 +137,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 +146,7 @@ func (f *outputdirFlag) Set(value string) (err error) { } return err } + func (f *outputdirFlag) getAbs() string { if f.abs == "" { return base.Cwd() @@ -150,8 +155,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 +168,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,31 +186,45 @@ 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 + 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) } return nil } @@ -369,7 +395,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 95c90ea7c8da4a3f5121af3d78db4b80d8b18f65..4fe4c2baeda1ff7dbe1a1360f9a1d6d8dd9cb5f4 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/txtar/archive_test.go b/src/cmd/go/internal/txtar/archive_test.go deleted file mode 100644 index 3f734f6762531ec9e4444daa742572b45e1a0721..0000000000000000000000000000000000000000 --- 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/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 91485f6f745b1ffcc64fcbd95f3449cbcb2b7cb6..313dc62b780e6c9f39981ba416bd0d7077ebfa01 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" @@ -17,8 +18,10 @@ import ( "os" "path/filepath" "regexp" + "strconv" "strings" "sync" + "time" "cmd/go/internal/base" "cmd/go/internal/cfg" @@ -29,11 +32,12 @@ 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 - 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 @@ -48,6 +52,14 @@ 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 // Optional. + CommitTime time.Time // Optional. + Uncommitted bool // Required. } var defaultSecureScheme = map[string]bool{ @@ -118,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"}, @@ -139,6 +152,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,10 +163,60 @@ func hgRemoteRepo(vcsHg *Cmd, rootDir string) (remoteRepo string, err error) { return strings.TrimSpace(string(out)), nil } +func hgStatus(vcsHg *Cmd, rootDir string) (Status, error) { + // 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 + } + + // 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 + } + } + + // 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. 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"}, @@ -182,6 +246,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,10 +297,40 @@ func gitRemoteRepo(vcsGit *Cmd, rootDir string) (remoteRepo string, err error) { return "", errParse } +func gitStatus(vcsGit *Cmd, rootDir string) (Status, error) { + out, err := vcsGit.runOutputVerboseOnly(rootDir, "status --porcelain") + if err != nil { + return Status{}, err + } + 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 + } + } + + return Status{ + Revision: rev, + CommitTime: commitTime, + Uncommitted: uncommitted, + }, nil +} + // 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}"}, @@ -251,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) { @@ -294,10 +390,68 @@ 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", - Cmd: "svn", + Name: "Subversion", + Cmd: "svn", + RootNames: []string{".svn"}, CreateCmd: []string{"checkout -- {repo} {dir}"}, DownloadCmd: []string{"update"}, @@ -346,8 +500,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"}, @@ -358,6 +513,7 @@ var vcsFossil = &Cmd{ Scheme: []string{"https", "http"}, RemoteRepo: fossilRemoteRepo, + Status: fossilStatus, } func fossilRemoteRepo(vcsFossil *Cmd, rootDir string) (remoteRepo string, err error) { @@ -368,6 +524,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 } @@ -395,6 +605,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 +766,86 @@ 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, allowNesting bool) (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 _, 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 + // 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. - 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 vcsCmd == nil { + return "", nil, &vcsNotFoundError{dir: origDir} + } + 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") + } - if vcsRet != nil { - if err := checkGOVCS(vcsRet, rootRet); err != nil { - return nil, "", err + 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 vcsRet, rootRet, nil } - return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir) + return nil, err +} + +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) +} + +func (e *vcsNotFoundError) Is(err error) bool { + return err == os.ErrNotExist } // A govcsRule is a single GOVCS rule like private:hg|svn. @@ -707,7 +951,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 @@ -745,7 +993,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 @@ -885,7 +1133,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 +1260,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 } @@ -1063,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() @@ -1340,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/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index c5c7a3283bce57d1fbc8ac0c09549fe80ace5290..c4e4f4d3c6a6c43106e3731811baf027db6e9361 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -6,9 +6,9 @@ package vcs import ( "errors" + "fmt" "internal/testenv" "os" - "path" "path/filepath" "strings" "testing" @@ -205,7 +205,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 { @@ -214,36 +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() - } - - want := RepoRoot{ - VCS: vcs, - Root: path.Join("example.com", vcs.Name), - } - var got RepoRoot - got.VCS, got.Root, 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) } } } diff --git a/src/cmd/go/internal/version/exe.go b/src/cmd/go/internal/version/exe.go deleted file mode 100644 index 0e7deef1491a9c4d022ff0ff6b86341d4a7b0cb4..0000000000000000000000000000000000000000 --- 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 58cbd32e78d1158700c64c2d207f40e4456802c1..52502e95c6d673eed8ec1b1a203ba9b9b55bd268 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" @@ -62,8 +63,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 } @@ -135,90 +142,26 @@ 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) - } - return - } - defer x.Close() - - vers, mod := findVers(x) - if vers == "" { - if mustPrint { - fmt.Fprintf(os.Stderr, "%s: go version not found\n", file) + 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 } - 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) } diff --git a/src/cmd/go/internal/vet/vet.go b/src/cmd/go/internal/vet/vet.go index 1d419dddb98d6cdcc53ef5e3e6eb67b477531988..88b3c570a03b5c52328eaf745dc795d86174c830 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 b5b3c462ff2acced306e495a173b43be76fd579b..3551a5997c5f887d5c3f9f8dd00ac462a902f46b 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/web/bootstrap.go b/src/cmd/go/internal/web/bootstrap.go index 08686cdfcf9f4c11e96587a99738a09aa62b4324..ab88e9e4781f4666c9102104d4e1eccf7948c90b 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 f177278eba1e7d9088014ee0ae246e2efb0dca39..a92326db01e629093235ad88d809329bcadb1ab9 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 @@ -17,6 +16,7 @@ import ( "errors" "fmt" "mime" + "net" "net/http" urlpkg "net/url" "os" @@ -84,8 +84,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) { diff --git a/src/cmd/go/internal/web/url_other.go b/src/cmd/go/internal/web/url_other.go index 453af402b43dd9eb9208af234701127cfa887f25..84bbd72820fcab516624f09755265dcd97f0f81d 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 4d6ed2ec7f8c1dd0d9ab90f83f4478057c36b46d..5c197de800dc1f31e73ca132da21218f7c8df148 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/action.go b/src/cmd/go/internal/work/action.go index 69940cb00159b64c60024a9f248e5a0db337b266..c0862c5efe503af8cf6384aebd1468b9d89e024f 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) @@ -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 0ed2389cd5a81af6f3ff862dd275b9fb9ba0109e..9d0ad27f0dc7b7d284d582ca5450fc44048b780b 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -68,13 +68,16 @@ 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. 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 @@ -85,8 +88,19 @@ 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 + 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. See also -buildinfo. -compiler name name of compiler to use, as in runtime.Compiler (gccgo or gc). -gccgoflags '[pattern=]arg list' @@ -98,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 @@ -121,6 +135,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 +223,7 @@ func init() { AddBuildFlags(CmdBuild, DefaultBuildFlags) AddBuildFlags(CmdInstall, DefaultBuildFlags) + base.AddWorkfileFlag(&CmdBuild.Flag) } // Note that flags consulted by other parts of the code @@ -289,10 +312,13 @@ 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, "") 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. cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "") @@ -364,6 +390,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() @@ -396,7 +423,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)) @@ -415,7 +442,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 { @@ -430,13 +457,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") } @@ -486,14 +513,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 @@ -580,7 +610,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 @@ -608,7 +638,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) @@ -621,7 +651,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") } } @@ -667,14 +697,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) } } } @@ -769,7 +799,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/build_test.go b/src/cmd/go/internal/work/build_test.go index 600fc3083f0d506228fe1e26797013f94e11607b..0b6b83a706cd400faba2bb45ef531adce2166180 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/buildid.go b/src/cmd/go/internal/work/buildid.go index 4e9189a36320ace016890c567fd241ffb92a7a87..76335e9bb170b145d71ff15de5d5383090b2db17 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 } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 5a225fb9f1f62666ca959add62e75a458fc8f279..ccd5aee221bd04f7af1c4c603c26e4008c05e9df 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -36,6 +36,8 @@ import ( "cmd/go/internal/modload" "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/internal/quoted" + "cmd/internal/sys" ) // actionList returns the list of actions in the dag rooted at root @@ -222,18 +224,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) } @@ -281,6 +297,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. @@ -773,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. @@ -1373,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()) } @@ -1487,6 +1512,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 @@ -1921,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 := " ." @@ -1947,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") @@ -2011,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 == "" { @@ -2045,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 { @@ -2382,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...) @@ -2429,12 +2456,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 +2475,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 +2662,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 := quoted.Split(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. @@ -2729,6 +2741,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. @@ -2750,7 +2766,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") } @@ -2976,18 +2992,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 @@ -3309,12 +3331,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. @@ -3326,7 +3342,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 4eb762cb289d28394668f501d1f54b2902da651e..8bbf25bb337e8b44e49cf56ae3dd8dfba4aafcf7 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/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 85da4f89f991f48e4ad9a3aad4b145f622363cb1..40175324d2654dc029ae5f038ebe4ceb1270c2f5 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -22,6 +22,7 @@ import ( "cmd/go/internal/load" "cmd/go/internal/str" "cmd/internal/objabi" + "cmd/internal/quoted" "cmd/internal/sys" "crypto/sha1" ) @@ -29,6 +30,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{} @@ -63,7 +76,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } pkgpath := pkgPath(a) - gcargs := []string{"-p", pkgpath} + defaultGcFlags := []string{"-p", pkgpath} if p.Module != nil { v := p.Module.GoVersion if v == "" { @@ -82,22 +95,19 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg v = "1.16" } if allowedVersion(v) { - gcargs = append(gcargs, "-lang=go"+v) + defaultGcFlags = append(defaultGcFlags, "-lang=go"+v) } } 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 + defaultGcFlags = append(defaultGcFlags, "-std") } + _, 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, // and to implement some special compiler pragmas. - gcargs = append(gcargs, "-+") + defaultGcFlags = append(defaultGcFlags, "-+") } // If we're giving the compiler the entire package (no C etc files), tell it that, @@ -116,25 +126,28 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } } if extFiles == 0 { - gcargs = append(gcargs, "-complete") + defaultGcFlags = append(defaultGcFlags, "-complete") } if cfg.BuildContext.InstallSuffix != "" { - gcargs = append(gcargs, "-installsuffix", cfg.BuildContext.InstallSuffix) + defaultGcFlags = append(defaultGcFlags, "-installsuffix", cfg.BuildContext.InstallSuffix) } if a.buildID != "" { - gcargs = append(gcargs, "-buildid", a.buildID) + defaultGcFlags = append(defaultGcFlags, "-buildid", a.buildID) } if p.Internal.OmitDebug || cfg.Goos == "plan9" || cfg.Goarch == "wasm" { - gcargs = append(gcargs, "-dwarf=false") + defaultGcFlags = append(defaultGcFlags, "-dwarf=false") } if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") { - gcargs = append(gcargs, "-goversion", runtimeVersion) + defaultGcFlags = append(defaultGcFlags, "-goversion", runtimeVersion) } if symabis != "" { - gcargs = append(gcargs, "-symabis", symabis) + defaultGcFlags = append(defaultGcFlags, "-symabis", symabis) } 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, @@ -147,10 +160,15 @@ 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(), gcflags, gcargs} - if p.Internal.LocalPrefix != "" { - // Workaround #43883. + args := []any{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), defaultGcFlags, gcflags} + if p.Internal.LocalPrefix == "" { + args = append(args, "-nolocalimports") + } else { args = append(args, "-D", p.Internal.LocalPrefix) } if importcfg != nil { @@ -172,11 +190,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) @@ -223,7 +236,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 @@ -349,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" { @@ -365,6 +378,16 @@ 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 == "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) @@ -432,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 @@ -536,33 +559,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 := quoted.Join(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 +657,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 +704,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 37a3e2d0ffd1232368863992603432fbd783e828..26192ecaed11cad5ebcbbd6c21ba7b9d0462777c 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -11,8 +11,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/modload" + "cmd/internal/quoted" "cmd/internal/sys" - "flag" "fmt" "os" "path/filepath" @@ -32,27 +32,63 @@ 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() } 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) { - base.Fatalf("go %s: %s environment variable is relative; must be absolute path: %s\n", flag.Args()[0], key, path) + 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) + args, err := quoted.Split(value) + if err != nil { + 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 environment variable is relative; must be absolute path: %s\n", key, path) + } + } +} + +// fuzzInstrumentFlags returns compiler flags that enable fuzzing instrumation +// 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 { + if !sys.FuzzInstrumented(cfg.Goos, cfg.Goarch) { + return nil } + return []string{"-d=libfuzzer"} } func instrumentInit() { - if !cfg.BuildRace && !cfg.BuildMSan { + if !cfg.BuildRace && !cfg.BuildMSan && !cfg.BuildASan { 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() + } + 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() } @@ -61,12 +97,15 @@ func instrumentInit() { base.SetExitStatus(2) base.Exit() } - 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]) - 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 { @@ -77,13 +116,16 @@ func instrumentInit() { cfg.BuildBuildmode = "pie" } } + if cfg.BuildASan { + mode = "asan" + } modeFlag := "-" + mode 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) @@ -96,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/internal/work/testgo.go b/src/cmd/go/internal/work/testgo.go index 8b77871b23f26922b4612c9017522710f1511af5..a09b65a23c35cd3bc928200faec75f5fa8de334c 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/internal/workcmd/edit.go b/src/cmd/go/internal/workcmd/edit.go new file mode 100644 index 0000000000000000000000000000000000000000..c42000710e0f5c56d037288f164156d3d7b7e585 --- /dev/null +++ b/src/cmd/go/internal/workcmd/edit.go @@ -0,0 +1,315 @@ +// Copyright 2021 The Go 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 edit + +package workcmd + +import ( + "cmd/go/internal/base" + "cmd/go/internal/modload" + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "strings" + + "golang.org/x/mod/module" + + "golang.org/x/mod/modfile" +) + +var cmdEdit = &base.Command{ + UsageLine: "go work edit [editing flags] [go.work]", + Short: "edit go.work from tools or scripts", + 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, Edit 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 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. + +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 -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. + +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 Use 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 ( + 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() { + cmdEdit.Run = runEditwork // break init cycle + + cmdEdit.Flag.Var(flagFunc(flagEditworkUse), "use", "") + cmdEdit.Flag.Var(flagFunc(flagEditworkDropUse), "dropuse", "") + cmdEdit.Flag.Var(flagFunc(flagEditworkReplace), "replace", "") + cmdEdit.Flag.Var(flagFunc(flagEditworkDropReplace), "dropreplace", "") + + base.AddWorkfileFlag(&cmdEdit.Flag) +} + +func runEditwork(ctx context.Context, cmd *base.Command, args []string) { + anyFlags := + *editGo != "" || + *editJSON || + *editPrint || + *editFmt || + len(workedits) > 0 + + if !anyFlags { + base.Fatalf("go: no flags specified (see 'go help work edit').") + } + + if *editJSON && *editPrint { + base.Fatalf("go: cannot use both -json and -print") + } + + if len(args) > 1 { + base.Fatalf("go: 'go help work edit' accepts at most one argument") + } + var gowork string + if len(args) == 1 { + gowork = args[0] + } else { + modload.InitWorkfile() + gowork = modload.WorkFilePath() + } + + if *editGo != "" { + if !modfile.GoVersionRE.MatchString(*editGo) { + base.Fatalf(`go mod: invalid -go option; expecting something like "-go %s"`, modload.LatestGoVersion()) + } + } + + workFile, err := modload.ReadWorkFile(gowork) + if err != nil { + base.Fatalf("go: errors parsing %s:\n%s", base.ShortPath(gowork), err) + } + + if *editGo != "" { + if err := workFile.AddGoStmt(*editGo); err != nil { + base.Fatalf("go: internal error: %v", err) + } + } + + if len(workedits) > 0 { + for _, edit := range workedits { + edit(workFile) + } + } + + modload.UpdateWorkFile(workFile) + + workFile.SortBlocks() + workFile.Cleanup() // clean file after edits + + if *editJSON { + editPrintJSON(workFile) + return + } + + if *editPrint { + os.Stdout.Write(modfile.Format(workFile.Syntax)) + return + } + + modload.WriteWorkFile(gowork, workFile) +} + +// 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.AddUse(modload.ToDirectoryPath(arg), modulePath) + if err := f.AddUse(modload.ToDirectoryPath(arg), ""); err != nil { + base.Fatalf("go: -use=%s: %v", arg, err) + } + }) +} + +// flagEditworkDropUse implements the -dropuse flag. +func flagEditworkDropUse(arg string) { + workedits = append(workedits, func(f *modfile.WorkFile) { + if err := f.DropUse(modload.ToDirectoryPath(arg)); err != nil { + base.Fatalf("go: -dropdirectory=%s: %v", arg, err) + } + }) +} + +// 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 + if i = strings.Index(arg, "="); i < 0 { + 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: -replace=%s: separator between old and new is =, not =>", arg) + } + oldPath, oldVersion, err := parsePathVersionOptional("old", old, false) + if err != nil { + base.Fatalf("go: -replace=%s: %v", arg, err) + } + newPath, newVersion, err := parsePathVersionOptional("new", new, true) + if err != nil { + base.Fatalf("go: -replace=%s: %v", arg, err) + } + if newPath == new && !modfile.IsDirectoryPath(new) { + 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: -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: -dropreplace=%s: %v", arg, err) + } + workedits = append(workedits, func(f *modfile.WorkFile) { + if err := f.DropReplace(path, version); err != nil { + base.Fatalf("go: -dropreplace=%s: %v", arg, err) + } + }) +} + +type replaceJSON struct { + Old module.Version + New module.Version +} + +// editPrintJSON prints the -json output. +func editPrintJSON(workFile *modfile.WorkFile) { + var f workfileJSON + if workFile.Go != nil { + f.Go = workFile.Go.Version + } + for _, d := range workFile.Use { + f.Use = append(f.Use, useJSON{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"` + Use []useJSON + Replace []replaceJSON +} + +type useJSON struct { + DiskPath string + ModPath string `json:",omitempty"` +} diff --git a/src/cmd/go/internal/workcmd/init.go b/src/cmd/go/internal/workcmd/init.go new file mode 100644 index 0000000000000000000000000000000000000000..2297ac20d0a4ead31a74fb366c0086aae746c86d --- /dev/null +++ b/src/cmd/go/internal/workcmd/init.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 work init + +package workcmd + +import ( + "cmd/go/internal/base" + "cmd/go/internal/modload" + "context" + "path/filepath" +) + +// 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]", + Short: "initialize workspace file", + 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 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 +https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for +more information. +`, + Run: runInit, +} + +func init() { + base.AddModCommonFlags(&cmdInit.Flag) + base.AddWorkfileFlag(&cmdInit.Flag) +} + +func runInit(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/workcmd/sync.go b/src/cmd/go/internal/workcmd/sync.go new file mode 100644 index 0000000000000000000000000000000000000000..5f33e057f6d58d79e236fd6e76b2879bded0b2d1 --- /dev/null +++ b/src/cmd/go/internal/workcmd/sync.go @@ -0,0 +1,119 @@ +// Copyright 2021 The Go 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" +) + +// 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]", + 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 + } + + 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)) + + // 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) + } + + 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 new file mode 100644 index 0000000000000000000000000000000000000000..97c493685ad95dc83211e5a8b7a411ccf4788925 --- /dev/null +++ b/src/cmd/go/internal/workcmd/use.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 work use + +package workcmd + +import ( + "cmd/go/internal/base" + "cmd/go/internal/fsys" + "cmd/go/internal/modload" + "context" + "io/fs" + "os" + "path/filepath" +) + +// 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]", + 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() + + workFile, err := modload.ReadWorkFile(gowork) + if err != nil { + base.Fatalf("go: %v", err) + } + + haveDirs := make(map[string]bool) + for _, dir := range workFile.Use { + 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.DropUse(filepath.ToSlash(dir)) + } + for dir := range addDirs { + workFile.AddUse(filepath.ToSlash(dir), "") + } + modload.UpdateWorkFile(workFile) + modload.WriteWorkFile(gowork, workFile) +} diff --git a/src/cmd/go/internal/workcmd/work.go b/src/cmd/go/internal/workcmd/work.go new file mode 100644 index 0000000000000000000000000000000000000000..3ddbfbe7726ec25776b4650857171597bdfc1759 --- /dev/null +++ b/src/cmd/go/internal/workcmd/work.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 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 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 modules. + +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{ + cmdEdit, + cmdInit, + cmdSync, + cmdUse, + }, +} diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 16361e02ca7f7c4d1cadee8a6f93aa3d2b3d46ed..c0a1d3ccfc496cd04d7d3edc3d864455dddbcee9 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/proxy_test.go b/src/cmd/go/proxy_test.go index 74bfecc08dbc6de1ca9768c536113eb878d7f3da..517a88554282de5f133b8fc1196e112abf5a0d87 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 ( @@ -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 639e907db075159dd5aba227d38e7ec9261127bf..dbfba2291c44d5971b7faac4e730ee6ab468c117 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" @@ -30,11 +31,14 @@ 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.`) + // TestScript runs the tests in testdata/script/*.txt. func TestScript(t *testing.T) { testenv.MustHaveGoBuild(t) @@ -142,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. @@ -181,6 +186,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") @@ -269,6 +275,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) @@ -332,8 +354,14 @@ Script: ok = canCgo case "msan": ok = canMSan + case "asan": + ok = canASan case "race": ok = canRace + case "fuzz": + ok = canFuzz + case "fuzz-instrumented": + ok = fuzzInstrumented case "net": ok = testenv.HasExternalNetwork() case "link": @@ -347,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. @@ -1109,6 +1137,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) @@ -1125,6 +1164,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. @@ -1151,7 +1257,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 } @@ -1204,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() } @@ -1341,6 +1447,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. diff --git a/src/cmd/go/stop_other_test.go b/src/cmd/go/stop_other_test.go index e1cc6cf8ba755fffd719f14a2e0455b2ae7874e5..35c12858c1d5e1d36772a0285313c410b7643058 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 ac35b240f0ad9727845fed622a5112f704b95909..5939f0d40d996777493cc6f64263ed340d71029e 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/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go index 03869e68defe0845c5cbdef60fa08f2fd3fdf42d..eac2a7ad449a2fea361545cd27a712bfe0821a92 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. @@ -29,7 +30,7 @@ import ( "path/filepath" "strings" - "cmd/go/internal/txtar" + "golang.org/x/tools/txtar" ) func usage() { @@ -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/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 0000000000000000000000000000000000000000..af005ffb4119080e158cd4b9cd7ce44d0b951112 --- /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 0000000000000000000000000000000000000000..ea599aa61109aa2138746686412c0d035582c2ea --- /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/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 35c3f277103df132a0588eb4fe5ef6ca4689e18f..00076d74fc2f8868a1e78de129bcbe6a6fbf1d51 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 917fc0f55992efa69f6767a486fd2a2908bded95..bb1c1fecc9d2713360069cf593b6df89e6e1c303 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/savedir.go b/src/cmd/go/testdata/savedir.go index d469c31a919821171affd2be2e88b12ef3861de0..53c78cfb00bbac391b9b1f818a566a0d8d786555 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. @@ -24,7 +25,7 @@ import ( "strings" "unicode/utf8" - "../internal/txtar" + "golang.org/x/tools/txtar" ) func usage() { diff --git a/src/cmd/go/testdata/script/README b/src/cmd/go/testdata/script/README index 48e4055b0bdb971397be7dd2b0b909205a46a588..2b55fa89777d17f7e2927980a5a52a69b01e60c4 100644 --- a/src/cmd/go/testdata/script/README +++ b/src/cmd/go/testdata/script/README @@ -79,7 +79,9 @@ 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 + - [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/build_cache_disabled.txt b/src/cmd/go/testdata/script/build_cache_disabled.txt index 8b005c857fcf99dd89fda7ef752cf13b52864471..cb1a7558fca71f3edab009c32329376f45b7a45e 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 9a4b9d7b40c7264ea9cec6df11a66006be3a41fe..7ee3c3b41d489a7cd3059efe567737f25b040559 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/build_concurrent_backend.txt b/src/cmd/go/testdata/script/build_concurrent_backend.txt new file mode 100644 index 0000000000000000000000000000000000000000..9cac635e5a6760ca21b89163cdf6eec6b650382f --- /dev/null +++ b/src/cmd/go/testdata/script/build_concurrent_backend.txt @@ -0,0 +1,10 @@ +# Tests golang.org/issue/48490 +# cmd/go should enable concurrent compilation by default + +# 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 ' 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 0000000000000000000000000000000000000000..0ffe1570f6c6e40c062f318f6cf046a568d0f032 --- /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_i_deprecate.txt b/src/cmd/go/testdata/script/build_i_deprecate.txt index 71356e5321eb1ca3ab2b9227c55ceba8eb4710d1..5c1799566999e44a76c4555af4e06cfd67b592fd 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/build_issue48319.txt b/src/cmd/go/testdata/script/build_issue48319.txt new file mode 100644 index 0000000000000000000000000000000000000000..f58a5faa3fdd93584425c2afc244d7f07e778a9a --- /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() +} 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 0000000000000000000000000000000000000000..9123907dc87a40e41803c145433602aada4db3dd --- /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 diff --git a/src/cmd/go/testdata/script/build_overlay.txt b/src/cmd/go/testdata/script/build_overlay.txt index 2932b94e6c42c70cdec8884c1e36dc281e063369..56e812f44b29e7eb943f4302a17a4aeb825582bb 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/build_runtime_gcflags.txt b/src/cmd/go/testdata/script/build_runtime_gcflags.txt index da1b65f06c849788fbf7b7b73a50ee0f40979892..c87e480911933a6211fd31991cbf17ec2e75da44 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/build_single_error.txt b/src/cmd/go/testdata/script/build_single_error.txt new file mode 100644 index 0000000000000000000000000000000000000000..241cdb954ba7664ce796ea16c761d23a59dfe45c --- /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 diff --git a/src/cmd/go/testdata/script/build_trimpath.txt b/src/cmd/go/testdata/script/build_trimpath.txt index 2c3bee8fdc7a925bb9bd9bdcee078a36b0ed9581..f36b1237dc09413f8cf95fea76a278ed48b187f6 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/cgo_path_space_quote.txt b/src/cmd/go/testdata/script/cgo_path_space_quote.txt new file mode 100644 index 0000000000000000000000000000000000000000..955610130088d512759b29d86d0dba92a0875ef2 --- /dev/null +++ b/src/cmd/go/testdata/script/cgo_path_space_quote.txt @@ -0,0 +1,58 @@ +# 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 +[!cgo] 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 . +stdout 1 + +-- 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/go/testdata/script/embed.txt b/src/cmd/go/testdata/script/embed.txt index 04b17cd62b385999188cfa7e6795496bbddd0c50..5f7f6edd77e7f9a4d8fee9c8b26ee278a4d04e8a 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/cmd/go/testdata/script/env_unset.txt b/src/cmd/go/testdata/script/env_unset.txt index 4e0f249509873ed7355470f5bd0a1326defbb1a0..22bc845c37bf4ecc7cde8b989b1d899e7a01e522 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 b5e97391679cc52442322e972c7a82fbed0e30bc..132947c623ff2f0472bad5ac22b9baf99d99cce5 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/gcflags_patterns.txt b/src/cmd/go/testdata/script/gcflags_patterns.txt index f23cecefd3aa30e87ef45d26b15949c2f88d3f28..24ec5aa11b01deaa9d6b6075a3f700623e995c9e 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 @@ -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' diff --git a/src/cmd/go/testdata/script/get_404_meta.txt b/src/cmd/go/testdata/script/get_404_meta.txt index ec4f8d32432179bc97c5fe9fccb56d1527c664e3..29fc5421e12fb9824c62dcec8d4f0bc526d16cf4 100644 --- a/src/cmd/go/testdata/script/get_404_meta.txt +++ b/src/cmd/go/testdata/script/get_404_meta.txt @@ -9,4 +9,10 @@ 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 -- +module m + +go 1.18 diff --git a/src/cmd/go/testdata/script/get_go_file.txt b/src/cmd/go/testdata/script/get_go_file.txt index bed872098769249e851a30ac13a4957c83aed913..f6d0de4d06fe540d92c580fbec4c4f9a9743dfb7 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 2517664dd02308901fe338e5daac43a73c16b306..00bf32fc78effbb635570ffa919e96af69e561ee 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/go_version.txt b/src/cmd/go/testdata/script/go_version.txt new file mode 100644 index 0000000000000000000000000000000000000000..1a787e1b18c1dd9265e6f2ed29f0871ce98f26d8 --- /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 . diff --git a/src/cmd/go/testdata/script/goflags.txt b/src/cmd/go/testdata/script/goflags.txt index 686d1138b8318e3d0ed5affd6673ee66ead24c96..f4872ffd356b5b3874e1205c0959c20c79a38ca0 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/gopath_install.txt b/src/cmd/go/testdata/script/gopath_install.txt index 4b42fc593f9ddf4b9927d1bcadfab461ef0b74e5..6c572eae619f067eac3ec44681314e1706a851f9 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 7ee1f83471c631f4b5f41bab1105bdefa76c5973..54beaca5e8a9c211db89a82d3d729a673880c1dc 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 4180d7da6ab159addd14d344d7d5135e07d50f9d..46f1bd0da2ada67d7cb80664699f6ac3d7e3881c 100644 --- a/src/cmd/go/testdata/script/govcs.txt +++ b/src/cmd/go/testdata/script/govcs.txt @@ -5,64 +5,64 @@ 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 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 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/install_msan_and_race_require_cgo.txt b/src/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt index 7985cd2ab2728dfbb7311e6e96069b62f4b86792..5e88f7b8dbdc7288c3bdc6d8f7c4774b7e7fa1a0 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 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 0000000000000000000000000000000000000000..d86b3a374e919d744f04227e6ec47e9744d06013 --- /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/go/testdata/script/list_all_gobuild.txt b/src/cmd/go/testdata/script/list_all_gobuild.txt new file mode 100644 index 0000000000000000000000000000000000000000..e0a47398bbd92f25d3561239eedd330e8067b299 --- /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 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 0000000000000000000000000000000000000000..b9c5361492be9cfce28f3d94c204cc11be2cdcb9 --- /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 . diff --git a/src/cmd/go/testdata/script/list_shadow.txt b/src/cmd/go/testdata/script/list_shadow.txt index 7b24d9367aede1c6e3c32c38fda4b93c571b90dc..660508de9ff83c1b75b8814682823d866109ca9b 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/list_swigcxx.txt b/src/cmd/go/testdata/script/list_swigcxx.txt index c6acd9ecdbabf4b467c37fd262344be45dac8fec..d4227a80e8e8834d3af5608c3ee94f7e731a490c 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/list_test_err.txt b/src/cmd/go/testdata/script/list_test_err.txt index c6f1ecf40039097acadbde2977f817bf52f17c74..25dbb969b01c06a04d1869879168f4a52422923e 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 diff --git a/src/cmd/go/testdata/script/mod_all.txt b/src/cmd/go/testdata/script/mod_all.txt index 090eeee22df263579b99075bb227f5f32372e0dd..b71a920870a9bb7ffd2ad3668e10af24eb98991c 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. @@ -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 @@ -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_bad_domain.txt b/src/cmd/go/testdata/script/mod_bad_domain.txt index 7a270d0f07cac7fa76a670037dbb6678536db7d6..afd6e5186c152ac7f9ad6ba6547c7d9bafa10064 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' @@ -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 cee055eabe9c26d0c1d6c4ca79d3b2121eb29956..5c3c309b0dc86e40394e88625e9fc3520ba7f263 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_trimpath_issue48557.txt b/src/cmd/go/testdata/script/mod_build_trimpath_issue48557.txt new file mode 100644 index 0000000000000000000000000000000000000000..859eafcf84dff71d478735102d6777d09ec54f85 --- /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() {} diff --git a/src/cmd/go/testdata/script/mod_build_versioned.txt b/src/cmd/go/testdata/script/mod_build_versioned.txt index d1d74de10c22b1b75cd79a237b8e6c3b36db519c..f55041834aefe874bb195b4ce77999545846a668 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_dir.txt b/src/cmd/go/testdata/script/mod_cache_dir.txt index 7284ccf8bab735aa5613f08608228f41ec778c9f..4045928a9781b7e5cbb826508be511f551f395b3 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_cache_rw.txt b/src/cmd/go/testdata/script/mod_cache_rw.txt index a5410764bc00f86469f13173f0bf465d87be9cd4..07755415d608a46748b658ae808f67e575ec5d9b 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 4a4698600f7fb965162272a5eb7df75919712bc0..d3fb11dfa332168acb0ffa4188800d4bbb4a7d60 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 f3d6aaa5abc77bc02d61faed05e242de12cb5476..7c768a096395d93ec984a73eaf712c0ba389ba78 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 8c215251587180600da62bdbde2a77b61f5beed4..e2224d659b23a53dc28092a3eb153a5b0648a655 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 567027935dc338c32ec73644c594253b640c3cc6..8e2771dc1f2250b542c4c737ec0cfeeb196a1278 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 14745b5812c68296354cb7116cc9553b16357b94..c13029d534163e0f58b7e2de27d989cc7fadcf96 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_dot.txt b/src/cmd/go/testdata/script/mod_dot.txt index ca8d5c6cc2d62d9ebd1a64f72efdfaae15d22cf4..cb60e988b6dfcc671e59c35f31a9f28b08f67ac0 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 c2b72b2a02cab8f681872c637d1d9990c9131db5..154e68338b6b3e2f2bdfd63e3d789c7f664dd1e9 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. @@ -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 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 2e1283449554072c43509f293f8e64c11221e30d..46eb666686502cafdea600ab9b0ec044bb454212 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_download_partial.txt b/src/cmd/go/testdata/script/mod_download_partial.txt index 0aab60ddaf00f84c24f19073af65dc0bec5dc8a2..3a02fcd7474b5b795f3159d1ac718e3b541f3764 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_private_vcs.txt b/src/cmd/go/testdata/script/mod_download_private_vcs.txt similarity index 79% 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 75c776a7fa29c78d1856d381fa2a938b15348034..e126793907241b65c6de002dc3cb200f37dd2fea 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 -stderr '^go get: github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b: invalid version: unknown revision 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_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 3817fce9b61f87ee027b88c68bcd1ad87fbc199a..79e00dc9706c9fd80ba7f7a37eec2e076678817b 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 get 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_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 9cbe0d279dea3073b7cbdffd60dd36a7830d4c07..a6b5a59054872926ed3fceb269e8899bc89c38d2 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_e.txt b/src/cmd/go/testdata/script/mod_e.txt index 3a0d18dabc2c94ab57010a316ac6812601139d9a..3cffaf6ef1c1cf1bdc6bda4bc1ac6ae79966be00 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_edit.txt b/src/cmd/go/testdata/script/mod_edit.txt index 5aa5ca1ffc02c520d79eefa46e4d24f3b980dba4..ebc032a73cf7819171cb48b1137f16d497632d38 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_edit_go.txt b/src/cmd/go/testdata/script/mod_edit_go.txt index 38321d071fb35e9adf1c8664f9c7de6edfab9549..7e9740fec43763a0727719f623c7ee708e98de97 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/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt index daed03b02c6cf41b6367d6ffa1846c2e37d1d39d..92149933686a6fc5e7bdbd9733ac8e414c49c808 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 33605f51a5b505570a3b7c394bfe426b72862a39..0af78bd4f252d737e2880c783055dd4414fea408 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 0e7f93bccb5b8773ee9b461b27efa3f5511074cf..1641196007b8e166a685f00d292207a72b69d25c 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 3287b2a6095a1c180fbfbe99031f4d776be772eb..12a112b4d87af75c8302dad7e5c1eedfbfec8a09 100644 --- a/src/cmd/go/testdata/script/mod_get_changes.txt +++ b/src/cmd/go/testdata/script/mod_get_changes.txt @@ -3,9 +3,9 @@ # for changed indirect dependencies. 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$' +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' go list -m all stdout golang.org/x/text @@ -14,18 +14,18 @@ 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 -stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.3.0$' -stderr '^go get: removed rsc.io/sampler v1.3.0$' +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' 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 -stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.5.1$' -stderr '^go get: removed usequote v0.0.0$' +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$' -- go.mod -- module m 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 d31cee1444a6adf5dcc8b4706f06584dbf31ae3c..0000000000000000000000000000000000000000 --- 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 4649491a532a8c7a8b20c88fde9aa16ca7b751be..f60eaab3a77e09d4aee4c57839ce7098f1443f89 100644 --- a/src/cmd/go/testdata/script/mod_get_commit.txt +++ b/src/cmd/go/testdata/script/mod_get_commit.txt @@ -5,18 +5,18 @@ 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 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,19 +24,20 @@ 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 +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 @@ -44,7 +45,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_get_deprecate_install.txt b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt index 63cd27a42d2bc76911d0e36f589adb4f97259f22..03258f52966fc745f3a1e01ac0b182e285c18b13 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,10 @@ 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 'Use ''go install pkg@version'' instead.' +# '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 @@ -13,13 +13,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 get: 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_deprecated.txt b/src/cmd/go/testdata/script/mod_get_deprecated.txt index 7bdd7a58a89b5d15c43520055daf3eb7b4c1d8f8..ec7bcfdb997e2e57218f11108430f09f46ab1862 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_direct.txt b/src/cmd/go/testdata/script/mod_get_direct.txt index 42ccbcd38a143b49c2f6729881d2791adeb7e786..856e05bc329328d2fe33771d12e8ac7d7cfb11a2 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 -- 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 efc38f77c85d37b6d94840acc771bc06c2febf9e..0f5ba992da204ed28a6854cb29b0e6807f348e34 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 c26c5e1c21013ada363965a4b768d36d921c6552..2eed56d9b71b899dac731e794e6bc18a50815653 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade.txt @@ -3,25 +3,25 @@ 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 -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$' +! 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$' go list -m all stdout 'rsc.io/quote v1.5.1' @@ -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 5b768faeb1802c7ffca5389a0eb74d34aa7418db..582593b96cdfb6241e403216c214fd2668642549 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt @@ -4,15 +4,15 @@ 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/... -stderr '^go get: example.net/pkgadded@v1.1.0 conflicts with example.net/pkgadded/subpkg/...@upgrade \(v1.2.0\)$' +! 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 # 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 c20583b22a136822effc89c7844217ab4ea8c8e4..111a54f8f7370cacb24af0852354e88246185921 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 ced1dcd6b14e37a528f1a9e494c3e93a6acbf804..3a46a774ce7c4516ae97074111f3db5d6196fec4 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 c49615cecb34d22ee114a974af6ecc2469814f4e..b678a177b521e32619b4afd6058e839813026327 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_errors.txt b/src/cmd/go/testdata/script/mod_get_errors.txt index 5c37058d1c1b9508e8a77ce8fb3de85eabf34eaf..7cb03ce2f1e6b5b4f5b5efd63110653c0a172740 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_extra.txt b/src/cmd/go/testdata/script/mod_get_extra.txt index 7efa24e87b0d3522d18a14b1c760ca6df88649c5..083e03678e48f1ebc0ffa5b1baece7841e8d258a 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 9733fa366bea57eb19370d6cb125c87933f845f9..35722333d6a0e86b195f80ff13f1fa73c56fa3d1 100644 --- a/src/cmd/go/testdata/script/mod_get_fallback.txt +++ b/src/cmd/go/testdata/script/mod_get_fallback.txt @@ -5,6 +5,11 @@ 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' + +-- go.mod -- +module m + +go 1.18 diff --git a/src/cmd/go/testdata/script/mod_get_fossil.txt b/src/cmd/go/testdata/script/mod_get_fossil.txt index baad544557af8861bed6a0ab30d4126678a2bd8c..c2d42f0f596f4a01b0077a54aa515b9fba1f4f68 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 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 0c7b5dc11c581f7a47d0bcb65e26b572da0a47e6..c81e491b947ecbe93955979ad978dfba8be7497d 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 @@ -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_get_incompatible.txt b/src/cmd/go/testdata/script/mod_get_incompatible.txt index 8000ee61481a01be883b022d17001ed2301f2a6b..5a7d70637180af3eb4c7c5483c102c47819523c8 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 e1cc1ab4115be419f6a779a508f125f17de11e6c..fa7edf22d7b997d0abd8648023d86488229e9b51 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 38b2031d3ae4a0fa16354af38e8879875c45e401..9392e73a174bd69e8efdfe49753f28f2f7d0d6fd 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 new file mode 100644 index 0000000000000000000000000000000000000000..848ee3aa09a9ad3d696b0ed30c37ed3332666145 --- /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 . +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 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 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 0000000000000000000000000000000000000000..0ba486d35bd6cecc2d8a6f4236c42613e445f7be --- /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 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 241a0c2f0dfa8eaf6435c47007ff157f25f8ac26..00da0c316469f9bd3d5e54f8bd67eb931b53047c 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_lazy_upgrade_lazy.txt b/src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt new file mode 100644 index 0000000000000000000000000000000000000000..3dae383de1e57bd5c9d664c290da73470c0fedab --- /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 diff --git a/src/cmd/go/testdata/script/mod_get_local.txt b/src/cmd/go/testdata/script/mod_get_local.txt index eb09da58b3e23404626e37993efd9747d0811ff1..4c81d16a1fe072058a6cd4aeb5abcc6fc1ab519d 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 50b2fee9ae1bfd82cd66feecfd420a324c5a10f7..cddd5f70826eb406a18e9efb55ed018f241f4ab0 100644 --- a/src/cmd/go/testdata/script/mod_get_main.txt +++ b/src/cmd/go/testdata/script/mod_get_main.txt @@ -2,44 +2,44 @@ env GO111MODULE=on 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$' -! go get -d $WORK -stderr '^go get: '$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$' -! go get -d $WORK/... -stderr '^go get: '$WORK'[/\\]\.\.\. is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' +! go get .. +stderr '^go: \.\. \('$WORK'[/\\]gopath\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' +! go get $WORK +stderr '^go: '$WORK' is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' +! go get ../... +stderr '^go: \.\./\.\.\. \('$WORK'[/\\]gopath([/\\]...)?\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' +! 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 -stderr '^go get: can''t request version "v0.1.0" of the main module \(rsc.io\)$' +! 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 -stderr '^go get: package rsc.io/x is in the main module, so can''t request version 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 -stderr '^go get: pattern rsc.io/x/... matches package rsc.io/x in the main module, so can''t request version 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 -- module rsc.io diff --git a/src/cmd/go/testdata/script/mod_get_major.txt b/src/cmd/go/testdata/script/mod_get_major.txt index 367ede9ded45ba5278d47437a4c989bdf44fb2d9..2db13180bd79786283919bba2e6e5d61ebe2c5c3 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 789d42d24dbca7184ff3572e50162f448acc5ab4..5934251e4b8b74688a40d060c261147b77a3e6d1 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 8430a737c40ca00842f14faede5001baa2f81a7e..ba79c8263c06dab4ab02ee466cf08275b99ea02c 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_newcycle.txt b/src/cmd/go/testdata/script/mod_get_newcycle.txt index f71620c1bcb41cac9e49ffc102c683f533a7ae4f..18dc6503617a566937844904736f80c50ab2a341 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_none.txt b/src/cmd/go/testdata/script/mod_get_none.txt index b358f05af36745226e909e1f4a81154bbf6fcdae..5aec209f59fe6fa54ffa3f67ce9d31d73fb665de 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 078e71a041c470463a9a7e7065de6fadb94bc30a..14176a7dc8786d0538c10ea5ec61b1fe1adefdba 100644 --- a/src/cmd/go/testdata/script/mod_get_nopkgs.txt +++ b/src/cmd/go/testdata/script/mod_get_nopkgs.txt @@ -6,17 +6,17 @@ 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 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. @@ -26,8 +26,8 @@ stderr '^go get example\.net/emptysubdir/subdir/\.\.\.: module example\.net/empt # 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 -stderr '^go get builtin/...: malformed module path "builtin": missing dot in first path element$' +! 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 -- 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 053ef621471ecc6b784ae095573aef6f409352ca..35cc276c5c36839788d2e7dd60be4f122d9d648b 100644 --- a/src/cmd/go/testdata/script/mod_get_patch.txt +++ b/src/cmd/go/testdata/script/mod_get_patch.txt @@ -7,8 +7,8 @@ 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 -stderr '^go get: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' +! 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,8 +18,8 @@ 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\)$' +! 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 ' @@ -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_patchbound.txt b/src/cmd/go/testdata/script/mod_get_patchbound.txt index 4fd1ec53e16045fa8def31af242b41e486263144..e4d3c491f45611f45919ef3aca1c3a0d26efe6dd 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_patchcycle.txt b/src/cmd/go/testdata/script/mod_get_patchcycle.txt index d1db56f935ca2ee7c0983bb37fd30c9febf8782a..6600109d2dad9be00b39c17478dec0ec17f1a8f4 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 e39d13a0f4184e515e14f7b097f5ddd0d7935491..28277310aa15e5041c137d69dcc2bbdf9cefb242 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,8 +15,8 @@ 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 -stderr '^go get: example.net/other@v0.1.0 requires example.net/pkgremoved@v0.2.0, not example.net/pkgremoved@patch \(v0.1.1\)$' +! 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 aee4374dc8a88a5dff020078c9e392178d9e7ba1..891353fd4b9a0b6ef59098a609bbe97ddc2112ae 100644 --- a/src/cmd/go/testdata/script/mod_get_patterns.txt +++ b/src/cmd/go/testdata/script/mod_get_patterns.txt @@ -5,29 +5,29 @@ 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... -stderr 'go get: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching 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/... -stderr 'go get: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching 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 # If a pattern matches no packages within a module, the module should not # 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 0c79ec71b7b41d628d6a412e34816399d4599007..7ad3c3c7c44a4caf8c40c05f8d764580815f587b 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,27 +48,27 @@ 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 -stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' +! 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 -stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' +! 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.mod -- 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 be3db42d1d9c1f104c78e0ba0c92c90b49288300..06e2fc686029184d8b15cfa2f0b4e39edb8aad7f 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 9eec2013210350fdd7b4234eeea6160abaa70ec7..03f6810e354a0a3e56a112a424b499ffdb7d1fcb 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 582837a1665e28aaa0b2fd4e4ea83e92d3ca50b9..b964ae448453b9860fa1d854109110e975649b7c 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 0fbd041f8603fd57a3b94e09008072431a56e285..d085f4fa3c8e6b2319bce5ed94c9b569f58d3ded 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 b78e6e644f7622a3d22dd4333672c7f3731dcf48..8e6cd907f183495842855232179f2ed9f16e3bb1 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 d97f3f1a40117242fba478162505e0abb9d6eb97..b1fc8b80563307cb948b50361507275bd8b578ff 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,15 +81,15 @@ 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$' +! go get example +stderr '^go: malformed module path "example": missing dot in first path element$' 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 560fa7bfb256ffee487cb2303faa1267f128a2bf..9757989666728eb3050c3c63a8cd37fce848f6cb 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 b49ba54982b643bc5c395b1e05449bc8ae509fd3..4b4f5da03cdba618d7abed6d297c71af5572f8e9 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 f4e7661f9b2a036135dccb2daa50fe39b64cba5f..0fb22c85d3943efb3d01890772c599962ebd0817 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,22 +54,22 @@ 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$' +! 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 # 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 4f1cf0327770389511b2fb2da0f7178544cab311..0d9a840e779cc4334544df743213f67ea58b5cc7 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_tags.txt b/src/cmd/go/testdata/script/mod_get_tags.txt index e9869e3f0230b3ab6f6bdbb1f756071a2c624a1c..e4fb6c4326b46f52a14b4d8316896a9e18e0d5ce 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_get_test.txt b/src/cmd/go/testdata/script/mod_get_test.txt index 23722bd4e4dcd7f749386b2e68dee7efea25e9a3..0fa7cd98b98fb2fd0f38d08d35ce27b0503a6484 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 c53669353794ade0e4eb2039d0f91f48a89ad1d2..7b469008baffd414014094578da7b0ee36618b3b 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 0093c0eda0c8270eabe147901828f994f88122af..a5651e934181a70dc5e302193792fb939bbe4bd9 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 eeb6d6f6af6f414b5545034bbabf80f9cceec096..51d5990ee179c73a90bcd42661a29f764313a813 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 f5f415aa3fae25e66ec10e62a04469c14c115157..deff9358f060f462a74c0ab349a97139d553202e 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 78c645c6b9f3fe4174cd75f82ee0af1066837a7c..06f9973e431932f35923d937e0e3378247b9ad7a 100644 --- a/src/cmd/go/testdata/script/mod_get_wild.txt +++ b/src/cmd/go/testdata/script/mod_get_wild.txt @@ -11,15 +11,15 @@ 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 -stderr '^go get: no modules to query for example\.\.\./b@upgrade because first path element contains a wildcard$' +! go get -u=patch example.../b@upgrade +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 # 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 d3df2078b072833b9beb058dc3332ecf7013d7c4..aaf526b2ab54beb3245ea4737a313bc54456055f 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 @@ -11,20 +11,21 @@ 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 +go 1.16 -- x.go -- package x import _ "rsc.io/quote" diff --git a/src/cmd/go/testdata/script/mod_getx.txt b/src/cmd/go/testdata/script/mod_getx.txt index ccb8d1375aa7dd2dd16fcfa60a20ff295b5ddc99..b3d06c17c85afa0111bdcc10999d5425a2d8deca 100644 --- a/src/cmd/go/testdata/script/mod_getx.txt +++ b/src/cmd/go/testdata/script/mod_getx.txt @@ -8,7 +8,12 @@ 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 //.*' + +-- go.mod -- +module m + +go 1.18 diff --git a/src/cmd/go/testdata/script/mod_gomodcache.txt b/src/cmd/go/testdata/script/mod_gomodcache.txt index 74a3c79622f1f5ff916edd64cb39facd386edee4..bafa5876241ece08b9e06340673761bf912ce7bf 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 @@ -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_gonoproxy.txt b/src/cmd/go/testdata/script/mod_gonoproxy.txt index 204786969f5b25923e9d9928541cb7a0ebd982e8..d42d668f679eeaf57a76adcdda70d0f6ee313dca 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,27 +26,27 @@ 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$' +! 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 -stderr '^go get golang.org/x/text: module lookup disabled by GOPROXY=off$' +! go get golang.org/x/text +stderr '^go: golang.org/x/text: module lookup disabled by GOPROXY=off$' # GONOPROXY bypasses proxy [!net] skip [!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 5ad9106378f33303b82dfad6df2d99bfedb87bee..beba3e7b02cd6b3e12d62428e5df0ee61a544661 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 28358b5b0c5b560527643096e8e27aa049e968c3..07714e92c720d1d498e4fb4000f6bf00a669399d 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 a4294504661454461eff34a570f60c377f7d2008..75b3374bca0016ebdb3160fd0b35720187d7cb79 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 66f79faa6d9b8dd65d11746777be76eda72843f8..866f7841b9fbb1104e45244a630978c16d10d9e0 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_init_invalid_major.txt b/src/cmd/go/testdata/script/mod_init_invalid_major.txt new file mode 100644 index 0000000000000000000000000000000000000000..ae93e70d6307ff6e432c193d5db86bb187e24808 --- /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 '' ''$' 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 fd02392af1b29387bcd072db6aa802e8a3738ac5..14153b8e9ec60903fba9486f72b516c2500db76b 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 @@ -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 .. @@ -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 @@ -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 .. @@ -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_install_versioned.txt b/src/cmd/go/testdata/script/mod_install_versioned.txt index c6bce418b4fa7093749bf780341a81d749635a60..627a9a81b0bead5747f3ae5793c8e14c150a3225 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 687269d18f6f33e05ce4572423d2d7cfa4efb8be..787b21f379c793f0428d90eb2ecdfc690a493cac 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 333a3ffa35cba157e6228157414be59a4cb59b92..667b76e340a5c4a02f1c22c95b75efde9313ed5e 100644 --- a/src/cmd/go/testdata/script/mod_invalid_path.txt +++ b/src/cmd/go/testdata/script/mod_invalid_path.txt @@ -29,9 +29,9 @@ 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$' -go get -d example.com/dotname/.dot -go get -d example.com/dotname/use +stderr '^go: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$' +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 85934332d145db7194fc62dc1ddb68aaa49e2e7d..484c208f0f7567196b39d19dc00683d787efdc15 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 51dbf936888769d0e4b777292ce807b235b918c3..dd59eb1fedac6870c1696869959f63a5a945d638 100644 --- a/src/cmd/go/testdata/script/mod_invalid_path_plus.txt +++ b/src/cmd/go/testdata/script/mod_invalid_path_plus.txt @@ -4,16 +4,16 @@ # '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. ! 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 -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 6846a792a5df587e00b2ce7d497333413d4f0dd5..428b8aa60e6f8827b32bc424e685c815bc91ccde 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,14 +30,14 @@ 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' # 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' @@ -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,27 +57,27 @@ 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 \(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 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 \(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 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' @@ -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' @@ -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' @@ -214,15 +214,15 @@ 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 -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' +! 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, # not resolve to a pseudo-version. diff --git a/src/cmd/go/testdata/script/mod_issue35317.txt b/src/cmd/go/testdata/script/mod_issue35317.txt index b1852ab0319ebbccdc6e15b063719332fad938a6..92416a54e474e0a8bb22c6422e1dd2a2fca01154 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 2f815fef22ff6398d894ba5d4d74475fa728d525..eb69d2eb8f81e12bb2ee762c290cb25529c4e040 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_lazy_import_allmod.txt b/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt index 97718c4513b55bffd6819544119f32b74b734173..60d4187b1178aec7deb1a5e554fe55d936899d76 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_lazy_new_import.txt b/src/cmd/go/testdata/script/mod_lazy_new_import.txt index 4272a52de1c2671db78a1c2708e199d6351c511e..520d8459cc11d4909ea381c2ed5df476b61af7fe 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: # diff --git a/src/cmd/go/testdata/script/mod_list.txt b/src/cmd/go/testdata/script/mod_list.txt index 239c7caa4a2246e87eaaef22b2ace9ce6ba800dc..06316cc335ed677e32cc0647f3b0f3d2d975d0b1 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_command_line_arguments.txt b/src/cmd/go/testdata/script/mod_list_command_line_arguments.txt new file mode 100644 index 0000000000000000000000000000000000000000..fd99ae84b2e570f1c93dcf15f01b3b487870eeb6 --- /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_list_deprecated.txt b/src/cmd/go/testdata/script/mod_list_deprecated.txt index f0ecbba2cea13d8c65f512036e3d0b8c887a3703..ee985cccbf3a91f5a3fc29dd08d2f181630ed8cb 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 1adab8f027d7374869b7ebba276b528ea5229ca1..7ad65ffbc734dea082e662c407a40e732913a33f 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 62a472f475e7f8f58a13177977a6b4c4c94abc1d..9b7a04c5044302b4aaac7fb5b24fb6738e6bf014 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 f2f2d2b2bb23c40e7993894fcf0ba28ca4ce9f35..eac5ca7dd322040b1dd0dc6a7dc6128b823b8772 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_retract.txt b/src/cmd/go/testdata/script/mod_list_retract.txt index 4b133485152da0b6315c529dff65d77c28fe056e..b7147aa18241fda4c406fc9d5bb0f2d19ff928d6 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_list_sums.txt b/src/cmd/go/testdata/script/mod_list_sums.txt index 86c528f82907b0d2989b014bf49f154ba4b1353d..6c2f57c2b2d88de231fdd05407f3d2daf5308b59 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 c6bbbb04ec7268486fb45e47f80612c527054fcf..7eebe266dbb8f07bc0c87f7f67364f45166314f0 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_list_upgrade_pseudo.txt b/src/cmd/go/testdata/script/mod_list_upgrade_pseudo.txt index b983bec73db903c6414effad41b00c06e9720343..8e51dfcd2aadf8327d79657204e9d61828665d5c 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 eb464ab0d3b84ea1faec6d201ccf10eb7e476389..be2a4bc1db283b92e0c59871cb361b67a0613ae8 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 @@ -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_load_badzip.txt b/src/cmd/go/testdata/script/mod_load_badzip.txt index 65374d2a6d1fdc219b0ed608818679738cf55bd3..58160b4d442252f5903845158950bcd635ac5708 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_missing_repo.txt b/src/cmd/go/testdata/script/mod_missing_repo.txt index 8dae85fa88d1508b724e2574b83c786621001d72..b91a8dbedacb52277ef4cf0f9285a341e92e109c 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_multirepo.txt b/src/cmd/go/testdata/script/mod_multirepo.txt index 0f335a11f0fb3bf3d2ecf2abc81b10ee3c3b1da9..bbefb78d90a48ee9b25874fb1853e33478126e5c 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_no_gopath.txt b/src/cmd/go/testdata/script/mod_no_gopath.txt new file mode 100644 index 0000000000000000000000000000000000000000..ed91f5d42e5c8a8b1f1f84bf856c55764ce0b376 --- /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" diff --git a/src/cmd/go/testdata/script/mod_outside.txt b/src/cmd/go/testdata/script/mod_outside.txt index 33341f7d4b3656fbfb37132fd9e4ec72bf2354a2..f88e2ae7efa6763b93a58929830c3cd52fe553d5 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 get: 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: 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 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 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 +# 'go get' should not download anything. +go clean -modcache +! 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 +! exists $GOPATH/pkg/mod/example.com/version@v1.0.0 # 'go build' without arguments implicitly operates on the current directory, and should fail. @@ -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. @@ -223,35 +223,11 @@ 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 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/mod_overlay.txt b/src/cmd/go/testdata/script/mod_overlay.txt index 86ab04bd3cfab4a8c4a594dce374bbff8a2e1f46..da35be6a196ed619d54d6f00668550b16c7c4b29 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 2d32dcd10fd4c91e35636b88d994d7a51c2eb0a0..77e2508cb7f3b13a6998ddcb89bab5431e32d0d5 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_prefer_compatible.txt b/src/cmd/go/testdata/script/mod_prefer_compatible.txt index 1b408c3e9e925d02cf6ea590bc721fb4880b2f7a..8e88997a3c3089c9360128c1d58dac2cd841e1eb 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 6427cc1527af3793236f9e42d4f5c31acc17514e..63980b839e7743780d6959b26e6dbd6e542e38a2 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_proxy_list.txt b/src/cmd/go/testdata/script/mod_proxy_list.txt index 89129f4fe237d6440935fd836ac9cacf7c2887f9..849cf2c476406554244339100d1699327f5857aa 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.txt b/src/cmd/go/testdata/script/mod_query.txt index a75f86ed7c5729d3c4b55734ae48b33f2f68170b..3758732504d0ca3f056acf169d1d96cf1171af40 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 f8b6e3e97edcff1c2c2d2ec0abadb5b3d3bc04b4..1c39eae5744c31d0b12a483eddd3a59a6d75ce1e 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 -stderr 'go get: example.com/join/subpkg@v0.0.0-20190624000000-123456abcdef: .*' +! 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,8 +39,8 @@ 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 -stderr 'go get: module example.com/join/subpkg: (invalid response from proxy ".+": invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' +! 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 -- 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 b0019694119bb17b2e95bfd180055aafc32daafb..f76b20c6d8830693856d8f59420cb7bb07aa9cb8 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 -stderr '^go get: rsc.io/quote@v1.5.0: excluded by go.mod$' +! 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_query_main.txt b/src/cmd/go/testdata/script/mod_query_main.txt index 39e5841a9cfa42e06a42d7018e958fa867536ccd..2a2fa42318aa1d10ceaef2d8725b868bd6013de6 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_readonly.txt b/src/cmd/go/testdata/script/mod_readonly.txt index d05ad2a3174f8ed5066299fb25516d131e654a08..9e950c389821208b1f4fd9e75459555261ebb8b0 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 a0a367fb1db11c7765ae0f09945fe13bbe2fe622..26b15518d94fa3bcf7e762abdd1f4d0667a0c50b 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_gopkgin.txt b/src/cmd/go/testdata/script/mod_replace_gopkgin.txt index d24f37b7880920f9a3f7d949fdafabe09fd92103..df752d9716e538b4bb89c73679d45df8e1b395ca 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_replace_import.txt b/src/cmd/go/testdata/script/mod_replace_import.txt index 2add31f71c10d43f828c953cfbd7ebe9d29bffb3..7bf3a86fed876faec6d6ff206493bcea64693863 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 d950d78bd3c621b7ebf429e33458214bb0f6cb30..5c1226b15efd46e06af85ed7277b83123bf0e83f 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_retention.txt b/src/cmd/go/testdata/script/mod_retention.txt index 7a371b18068cd2e6619fc7ffdf14ddf03fa63898..9d30026459a8af6440f0eb8bbce61eb0f4d9a179 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... @@ -81,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 @@ -139,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_retract.txt b/src/cmd/go/testdata/script/mod_retract.txt index 4f95ece8d7aaaeb72016d12d273d9c61fe60befe..37aae4896d0c718b983f2a6f15375c2e38f0159c 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_fix_version.txt b/src/cmd/go/testdata/script/mod_retract_fix_version.txt index e45758b627016da1252ace1231bbf4bb11a6c881..9ae49f53ab3797cbcd86b0e5dd899bef5fbd5fb0 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_incompatible.txt b/src/cmd/go/testdata/script/mod_retract_incompatible.txt index 61538e8024445c60874850b5ca6d501b7f19606d..5d09532529239b9201d14b38a6a22a1112eae8c8 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 eb00e8405c01073740f44c1d769647324182b092..27c2b670658e214bd27be9f739da3a6a64560812 100644 --- a/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt +++ b/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt @@ -24,12 +24,12 @@ 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 -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$' +! 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 -- #!/bin/bash diff --git a/src/cmd/go/testdata/script/mod_retract_rationale.txt b/src/cmd/go/testdata/script/mod_retract_rationale.txt index 823c384e488ff6d109d12fd2ae2e01bd419ffa70..92e9b7d6ea573c28e3b55471f5f6fd97a2a3ea1b 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 f54742c5232253b6d4f44927fab010f5770d24a7..38986f333f6474e4ac456162b693224c11f1255d 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 9cd714739abf556dc8818d3ef6f9c93f0a68e66e..788968f420ec54a10cfc302bca1d9938cb7c4169 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_run_nonmain.txt b/src/cmd/go/testdata/script/mod_run_nonmain.txt index 036755d2d1ac2781df0d92185f59975520d93328..8435fc05b496365dcc1b6ebbd97bed7b11c57ac5 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 e921fab508540433d4c240af4bfb68346e53b03b..c3a218d553d5ca19f8f8556d5f3ce71e9148b5d2 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_skip_write.txt b/src/cmd/go/testdata/script/mod_skip_write.txt new file mode 100644 index 0000000000000000000000000000000000000000..9fdb6fc121258721def75cb83756988a7621d388 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_skip_write.txt @@ -0,0 +1,92 @@ +# 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 + +go mod why -m rsc.io/sampler +cmp stdout why.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 diff --git a/src/cmd/go/testdata/script/mod_sum_lookup.txt b/src/cmd/go/testdata/script/mod_sum_lookup.txt index e021921380068778b5befe82ea0d6ba35368fdcb..7513f7f49f352ee9e7af699d358db364999404da 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_readonly.txt b/src/cmd/go/testdata/script/mod_sum_readonly.txt index 113f13ea390852c5138afc1df78dd6794ca0fa1f..57c5bbeefdf0203c43f28b50d8294500b6dff7a7 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_sum_replaced.txt b/src/cmd/go/testdata/script/mod_sum_replaced.txt index b03982d9cff442648606cd83886c6c936a82b6c0..6c322a00d607a95a0ea04c8972cd5beb4a3f590c 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 fa3483c5cb1a510b9d5c19cbf16c4bdf116f155d..d06db4ae69271a53849b8a0cbfbe1a205a7f02f1 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 -stderr 'go get: rsc.io/quote@v1.5.2: verifying module: checksum mismatch' +! 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 1b38475fb5e378c0e1d4fbb88ec266bba83fe90b..063fd20964fde230070699433e4d8ae577f7d65f 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 22fcbf3de84a71f92d3ebbd83aa56377d9485f0f..a834c4800dcf5fa352fff8a1f35797a865a367d9 100644 --- a/src/cmd/go/testdata/script/mod_sumdb_file_path.txt +++ b/src/cmd/go/testdata/script/mod_sumdb_file_path.txt @@ -12,15 +12,15 @@ 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 -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.*)' +! 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, # checksum verification should fall through to the next proxy, # 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 becd88b52e7cffaa18b94b99a574b84c1ab7df2f..a48a5ba1b048c038c63d79fec29903cba91f99f5 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 70b8e3fc4466ffab5676cb06b2aebe8d23aedd39..194c0c92e5705179f7658fd4e1f6f79f9de40c62 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 dbc23fb8f0984722e49f24201fbfe6c20ec95978..0604e1a4c4f1c28493c378d707783506282496f9 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_compat.txt b/src/cmd/go/testdata/script/mod_tidy_compat.txt index e6edef5ee3b78c83a59063f990bf4527f2493b99..18b297da60e1a2cb5d3b1ed1a6866f073947d539 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, @@ -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 c544cb7413fcdc6b4f791d98429fd7c8e3bc7feb..a45de5ad8cdcb8133d9bca070be5168707a31ba9 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 -- @@ -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 ea9e42e87e20fc57b7e14164f9f606954ccad269..11313f144c3a340f35da2cb037d3512ee39680dd 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/go/testdata/script/mod_tidy_convergence.txt b/src/cmd/go/testdata/script/mod_tidy_convergence.txt index 09c46f764bf06fd434f80454fa15f6eb2f2f53af..be0a8e9b8c591444fa32c586061d58f96407ba62 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 3c4d3244d5daa4e5ba92d4df0ba512473a19d42e..99599e551a1d6c21b174b79fe6c14707621b3ba0 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_downgrade_ambiguous.txt b/src/cmd/go/testdata/script/mod_tidy_downgrade_ambiguous.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b508c7ea8a212c37d413ae93b0a6d8193801e1e --- /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= diff --git a/src/cmd/go/testdata/script/mod_tidy_error.txt b/src/cmd/go/testdata/script/mod_tidy_error.txt index 395537b1a7177917d95805970163b3c7ff12edd3..51fc65fa7a8572ab31ec367b20e08d6ea8002f32 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_tidy_replace.txt b/src/cmd/go/testdata/script/mod_tidy_replace.txt index 297f6a6a45c872da732b127e8a4cb8d376b3ba68..274f3bf5090f633bde9680ee2efca1819867772f 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 c583f560586970c6741fc3d975da15ddb5384b9d..5a15818543ef2c4318d4f059624001ebc7d273df 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_tidy_too_new.txt b/src/cmd/go/testdata/script/mod_tidy_too_new.txt index b9c53b510daeb06c5d91e8fb2c720d5dd89b12ca..8c34a997c956a5642d24e69fd76095d36ab0419f 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 8b34f8bf27dfc66070075e4efe2efe78fa2e20ad..79a9808ef03796037489e0e44b17a70db4381b54 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,15 +10,15 @@ 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 -stderr '^go get: can''t query version "patch" of module patch.example.com/depofdirectpatch: no existing version is required$' +! 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 # get -u=patch, with no arguments, should patch-update all dependencies # 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 -stderr '^go get all@patch: can''t query version "patch" of module patch.example.com/direct: no existing version is required$' +! 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' @@ -86,16 +86,16 @@ 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 +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 f8be43cf4c6494442cea992819a23f16b42e435c..9e6e371927bef9f83cd31d9247928201c200dcf2 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.txt b/src/cmd/go/testdata/script/mod_vendor.txt index 2622916f614140cf09b49cb4afba4a9655e22609..a2727ddf7f370ec54b9ee1219f9e4dae1136ace1 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. @@ -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. diff --git a/src/cmd/go/testdata/script/mod_vendor_auto.txt b/src/cmd/go/testdata/script/mod_vendor_auto.txt index b0ea907206a44902b6001a8df73bd80d283f7893..3cace73a896410595cef799f146de5f09a5ad570 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 @@ -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 3b8eec0119b3fd64c23cfd346aab5ecfe2d63b6d..4efda55e08f10fb391c12324bbd2e52813be9f2b 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_vendor_embed.txt b/src/cmd/go/testdata/script/mod_vendor_embed.txt index be114159a1fbf7475fc1fba69ff18bae2e7ac0a1..b14fd9915646f38ac0db6239f2740fb0f8b1cbb4 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/mod_vendor_goversion.txt b/src/cmd/go/testdata/script/mod_vendor_goversion.txt index aa4cb41171a5199aaf94fd8566d050798ec31fff..9e3618a21848ffcd8ec663c04acc83e756d7551d 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: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]:' +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/src/cmd/go/testdata/script/mod_vendor_replace.txt b/src/cmd/go/testdata/script/mod_vendor_replace.txt index 0c1c1d22f5bff1602ea2e7541da02e95fad8b7af..1820af62ad809b8e8d553908c35d04df6f79eadd 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 5451aa773c8b5ea4eb4fed7fb90954199a3427bd..d9d9d9889741cdf58ef3c1c771a9cae60beb6583 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 839c6453cf825ed2cb682fae595883c088a81760..accd9f373deb0e59c4ca10ee18c2c690ee508b2e 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 b5106659a9a9bac55e08bc44629c2670ffe059c3..018709e33b42e3032df92363bad95d0296ef85ef 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 @@ -59,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 0ad08808178316bf50e67686c565ebabe97d4f64..398e523a9ceb65b5438bbc8cd04c9ae4a0c1387c 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 @@ -41,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. @@ -73,7 +78,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 diff --git a/src/cmd/go/testdata/script/run_dirs.txt b/src/cmd/go/testdata/script/run_dirs.txt index 538a6ac6f39cc803b2740d35e32428b6ceb8c09f..bd5cfbe3fb272cb8e0095375f9fcd9be42439666 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" diff --git a/src/cmd/go/testdata/script/run_wildcard.txt b/src/cmd/go/testdata/script/run_wildcard.txt index 72036d1d8dbdc7469dfac3db4d9aa3a0e57ab282..3e7e7b7e42f3066f4328677f6466e4059629f04b 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_benchmark_1x.txt b/src/cmd/go/testdata/script/test_benchmark_1x.txt new file mode 100644 index 0000000000000000000000000000000000000000..b1d4c39c16f0505c6b3e29d4236eb301bbe90e49 --- /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/cmd/go/testdata/script/test_build_failure.txt b/src/cmd/go/testdata/script/test_build_failure.txt index 8d13634c8c4321f877f7459be74cbba2736f7e58..e8c984f272c33bbf95b8c1c2eb1f8427a76a2d6c 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 diff --git a/src/cmd/go/testdata/script/test_cache_inputs.txt b/src/cmd/go/testdata/script/test_cache_inputs.txt index d694a30994710e70145469998b3fd086b5f2964f..3705c700d10bc905f7cfdd63657a1ca7e3dbe1f0 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. 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 0000000000000000000000000000000000000000..43cee565a19c1e5a5819826ef34becd3de8c7564 --- /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) +} diff --git a/src/cmd/go/testdata/script/test_flag.txt b/src/cmd/go/testdata/script/test_flag.txt index 0142b3f308f3b28005cb05f39819ca7073fa2a67..d168cfe6a8c882b5fb7b1b50347f852f35acb848 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_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt new file mode 100644 index 0000000000000000000000000000000000000000..3e048e00c55c39e1598d32d4b896c22f899ab270 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -0,0 +1,498 @@ +[!fuzz] skip + +# Test that running a fuzz target that returns without failing or calling +# f.Fuzz fails and causes a non-zero exit status. +! 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. +! 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=1x 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 fatal_fuzz_test.go +! stdout ^ok +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=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=1x fatal_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. +! 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 + +# Test that f.Fatal within f.Fuzz panics +! go test fatal_fuzz_fn_fuzz_test.go +! stdout ^ok +! stdout 'fatal here' +stdout FAIL +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 'fuzz target' + +# Test that f.Fail within f.Fuzz panics +! go test fail_fuzz_fn_fuzz_test.go +! stdout ^ok +stdout FAIL +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 '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 'fuzz target' +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 +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 +! 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 +! 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 + +# 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 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 +! 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 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 +stdout FAIL + +# 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' + +# 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 + +import "testing" + +func Fuzz(f *testing.F) {} + +-- error_fuzz_test.go -- +package error_fuzz + +import "testing" + +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") +} + +-- 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) { + f.Fuzz(func (*testing.T, []byte) {}) +} + +-- skipped_fuzz_test.go -- +package skipped_fuzz + +import "testing" + +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") + }) +} + +-- 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 + +import "testing" + +func Fuzz(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + f.Skip("skip here") + }) +} + +-- 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 + +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 + +import "testing" + +func Fuzz(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + // no-op + }) + f.Fatal("this shouldn't be called") +} + +-- 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 + }) +} + +-- 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 + +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) + } + }) +} + +func FuzzUnsupported(f *testing.F) { + m := make(map[string]bool) + f.Add(m) + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzAddDifferentNumber(f *testing.F) { + f.Add([]byte("a")) + f.Add([]byte("a"), []byte("b")) + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzAddDifferentType(f *testing.F) { + f.Add(false) + f.Add(1234) + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzWrongType(f *testing.F) { + f.Add("hello", 50) + f.Fuzz(func(*testing.T, []byte, int8) {}) +} + +-- 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" { + t.Fatal("fatal here") + } + }) +} + +func FuzzFail(f *testing.F) { + fuzzFn(f) +} + +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) {}) +} + +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/fuzz/FuzzFail/1 -- +go test fuzz v1 +[]byte("12345") +-- corpustesting/testdata/fuzz/FuzzPass/1 -- +go test fuzz v1 +[]byte("00000") +-- corpustesting/testdata/fuzz/FuzzPassString/1 -- +go test fuzz v1 +string("hello") +-- corpustesting/testdata/fuzz/FuzzPanic/1 -- +malformed +-- corpustesting/testdata/fuzz/FuzzInNestedDir/anotherdir/1 -- +go test fuzz v1 +[]byte("12345") +-- corpustesting/testdata/fuzz/FuzzWrongType/1 -- +go test fuzz v1 +int("00000") 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 0000000000000000000000000000000000000000..552966b06bdd706ac7e9fdd9bef1128357a1e30c --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -0,0 +1,97 @@ +[!fuzz-instrumented] skip + +[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 -fuzztime=100x . +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 + +# 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 + +go 1.16 +-- y_test.go -- +package y + +import ( + "io" + "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) }) +} +-- 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")) + } +} +-- 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/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt new file mode 100644 index 0000000000000000000000000000000000000000..d07fe50f95e71a637db2833301e0172fc485a123 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt @@ -0,0 +1,102 @@ +[!fuzz] skip +[short] skip + +# 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 +! 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 + +# Fuzz successful chatty fuzz target that includes a separate unit test. +go test -v chatty_with_test_fuzz_test.go -fuzz=Fuzz -fuzztime=1x +stdout ok +stdout PASS +! stdout FAIL +stdout -count=1 'all good here' +# Verify that the unit test is only run once. +stdout -count=1 'logged foo' + +-- 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") +} + +-- 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") + 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/cmd/go/testdata/script/test_fuzz_cleanup.txt b/src/cmd/go/testdata/script/test_fuzz_cleanup.txt new file mode 100644 index 0000000000000000000000000000000000000000..b65022bd74e7a060478918783caa03673fd49bc9 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_cleanup.txt @@ -0,0 +1,66 @@ +[!fuzz] 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/cmd/go/testdata/script/test_fuzz_deadline.txt b/src/cmd/go/testdata/script/test_fuzz_deadline.txt new file mode 100644 index 0000000000000000000000000000000000000000..5ba76a3d4fea9af135b17d6284ca579ee6dde186 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_deadline.txt @@ -0,0 +1,35 @@ +[!fuzz] 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 fuzz + +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/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt new file mode 100644 index 0000000000000000000000000000000000000000..56d94a4bcf58e6cab05961c1e2b42853bcbfa993 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -0,0 +1,121 @@ +[!fuzz] skip +[short] skip + +# There are no seed values, so 'go test' should finish quickly. +go test + +# Fuzzing should exit 0 after fuzztime, even if timeout is short. +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=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 + +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. +mkdir count +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 + +go 1.16 +-- fuzz_fast_test.go -- +package fuzz_test + +import "testing" + +func FuzzFast(f *testing.F) { + f.Fuzz(func (*testing.T, []byte) {}) +} +-- fuzz_count_test.go -- +package fuzz + +import ( + "fmt" + "os" + "testing" +) + +func FuzzTestCount(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++ + }) +} +-- 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 + +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + 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[2]) + 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_io_error.txt b/src/cmd/go/testdata/script/test_fuzz_io_error.txt new file mode 100644 index 0000000000000000000000000000000000000000..1a0aa6427e89f69cb09ab99353a5082a63d60d4d --- /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 +[!fuzz] 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/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt new file mode 100644 index 0000000000000000000000000000000000000000..dbf987605f30fbdd992385f47b5af59481f034e4 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -0,0 +1,38 @@ +[!fuzz] skip + +# 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 -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 1x standalone_fuzz_test.go +! stdout '^ok.*no tests to run' +stdout '^ok' +stdout 'no fuzz tests 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 fuzz tests to fuzz' + +-- standalone_fuzz_test.go -- +package standalone_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Fuzz(func (*testing.T, []byte) {}) +} 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 0000000000000000000000000000000000000000..a6dc3f19534e8d83ed00845a7c3b52176347ef14 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -0,0 +1,203 @@ +[!fuzz] skip +[short] skip + +# We clean the fuzz cache during this test. Don't clean the user's cache. +env GOCACHE=$WORK/gocache + +# Test that fuzzminimizetime cannot be negative seconds +! 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 . +! 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 . +! 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 . +! stdout '^ok' +! stdout 'minimizing' +stdout -count=1 'there was an Error' +stdout FAIL + +# Test that minimization is working for recoverable errors. +! go test -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 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 -count=1 '^\s+fuzzing process hung or terminated unexpectedly: exit status 99' +stdout FAIL + +# Check that re-running the value causes a crash. +! go test -run=FuzzMinimizerNonrecoverable . +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 -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 . + +# 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 example.com/y + +go 1.16 +-- y_test.go -- +package y + +import ( + "os" + "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) { + 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.Fatalf("contains a non-zero byte of length %d", len(b)) + } + } + }) +} + +func FuzzMinimizerNonrecoverable(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + os.Exit(99) + }) +} +-- empty/empty.go -- +package empty +-- check_testdata/check_testdata.go -- +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/fuzz/%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) + } + + // 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) + 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_minimize_interesting.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt new file mode 100644 index 0000000000000000000000000000000000000000..5d0de17f6bc53895fad8c66680829e2b289ab626 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt @@ -0,0 +1,251 @@ +[short] 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. +# +# 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=FuzzMinCache -test.fuzztime=1000x +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 + +# 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. +! exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinimizerCrashInMinimization -test.run=FuzzMinimizerCrashInMinimization -test.fuzztime=10000x -test.parallel=1 +! stdout '^ok' +stdout -count=1 'got the minimum size!' +stdout -count=1 'flaky failure' +stdout FAIL +# 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. +! 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 +# Check that the input written to testdata will reproduce the error. +go run check_testdata/check_testdata.go FuzzMinimizerNonrecoverableCrashInMinimization 100 + +-- go.mod -- +module fuzz + +go 1.17 +-- y.go -- +package fuzz + +import ( + "bytes" + "io" +) + +func Y(w io.Writer, s string) { + if !bytes.Equal([]byte(s), []byte("y")) { + w.Write([]byte("not equal")) + } +} +-- fuzz_test.go -- +package fuzz + +import ( + "bytes" + "io" + "os" + "strings" + "testing" + "unicode/utf8" +) + +func FuzzMinimizerCrashInMinimization(f *testing.F) { + seed := strings.Repeat("A", 1000) + f.Add(seed) + 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 s != seed { + // This should hit a new edge, and the interesting input + // should attempt minimization + Y(io.Discard, s) + } + 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(s) == 50 { + t.Error("got the minimum size!") + } + } + }) +} + +func FuzzMinimizerNonrecoverableCrashInMinimization(f *testing.F) { + seed := strings.Repeat("A", 1000) + f.Add(seed) + i := 3 + f.Fuzz(func(t *testing.T, s string) { + if len(s) < 50 || len(s) > 1100 { + return + } + if s != seed { + Y(io.Discard, s) + } + if i > 0 { + i-- + } else if utf8.RuneCountInString(s) == len(s) && len(s) <= 100 { + os.Exit(19) + } + }) +} + +func FuzzMinCache(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_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 + +// 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/cmd/go/testdata/script/test_fuzz_modcache.txt b/src/cmd/go/testdata/script/test_fuzz_modcache.txt new file mode 100644 index 0000000000000000000000000000000000000000..c0f18ea3c073196dbc0cbae76597d7fff9d3966c --- /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 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 0000000000000000000000000000000000000000..1ec4985613fd36eb9f9913e1f13e61fdedb88e52 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_multiple.txt @@ -0,0 +1,49 @@ +# 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. + +[!fuzz] 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 fuzz test: \[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) {}) +} 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 0000000000000000000000000000000000000000..99bae1daf07a1d09cdc4b95bdd8ba24091bbbce0 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -0,0 +1,323 @@ +[!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 +# 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 + +# 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 + +# Running the fuzzer should find a crashing input quickly. +! go test -fuzz=FuzzWithBug -fuzztime=100x -fuzzminimizetime=1000x +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 'FuzzWithBug/[a-f0-9]{64}' +stdout 'this input caused a crash!' + +! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x -fuzzminimizetime=1000x +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 + +! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=100x -fuzzminimizetime=1000x +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[/\\]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[/\\]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[/\\]fuzz[/\\]FuzzWithBadExit[/\\]' +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[/\\]' +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[/\\]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[/\\]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[/\\]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[/\\]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[/\\]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[/\\]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[/\\]fuzz[/\\]FuzzString[/\\]' +stdout 'this input caused a crash!' +go run check_testdata.go FuzzString + +-- go.mod -- +module m + +go 1.16 +-- fuzz_crash_test.go -- +package fuzz_crash + +import ( + "os" + "runtime" + "testing" +) + +func FuzzWithBug(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) != "aa" { + panic("this input caused a crash!") + } + }) +} + +func FuzzWithNilPanic(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) != "aa" { + panic(nil) + } + }) +} + +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) { + if string(b) != "aa" { + t.Fail() + } + }) +} + +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) { + 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 FuzzWithBadExit(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) != "aa" { + os.Exit(1) + } + }) +} + +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 { + panic("these inputs caused a crash!") + } + }) +} + +func FuzzInt(f *testing.F) { + f.Add(0) + f.Fuzz(func(t *testing.T, a int) { + 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 != 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!") + } + }) +} + +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.Add(byte(0)) + f.Fuzz(func(t *testing.T, a byte) { + 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 != 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!") + } + }) +} + +-- 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/fuzz", target) + + 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 new mutation 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) + } + if bytes.Equal(contents, []byte("aa")) { + 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.Fprintf(os.Stderr, "hash of bytes %q does not match filename %q\n", h, fname) + os.Exit(1) + } +} 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 0000000000000000000000000000000000000000..b5eab17349456cdffae387307772d54f933ccc89 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt @@ -0,0 +1,102 @@ +[!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. + +[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/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt new file mode 100644 index 0000000000000000000000000000000000000000..76b86488ad8ba5b29082493675344c549e804151 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -0,0 +1,165 @@ +[!fuzz] skip + +# 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 -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. + +# Test that the mutator is good enough to find several unique mutations. +! go test -fuzz=FuzzMutator -parallel=1 -fuzztime=100x mutator_test.go +! stdout '^ok' +stdout FAIL +stdout 'mutator found enough unique mutations' + +-- 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" + "bytes" + "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 { + b, err := io.ReadAll(r) + if err != nil { + return err + } + if string(bytes.TrimSpace(b)) != `FuzzB "seed"` { + 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 && err != bufio.ErrTooLong { + return err + } + if !sawAMutant { + return fmt.Errorf("worker: did not test any mutants") + } + return nil +} +-- mutator_test.go -- +package fuzz_test + +import ( + "testing" +) + +// TODO(katiehockman): re-work this test once we have a better fuzzing engine +// (ie. more mutations, and compiler instrumentation) +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) + crashes := make(map[string]bool) + // No seed corpus initiated + f.Fuzz(func(t *testing.T, b []byte) { + crashes[string(b)] = true + if len(crashes) >= 10 { + panic("mutator found enough unique mutations") + } + }) +} 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 0000000000000000000000000000000000000000..3764dcb9157a7fd86ac617abd67f8e83c7b90dd7 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt @@ -0,0 +1,74 @@ +# 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 -fuzztime=110x -fuzzminimizetime=10x -v +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 +# 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. 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) + } + 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/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 0000000000000000000000000000000000000000..1051292fcb847ee796c4a0608bf5138abe58879b --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt @@ -0,0 +1,75 @@ +# 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. +[windows] skip +[!fuzz] 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: 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. +# We should save a crasher. +! go test -fuzz=FuzzCrash +exists testdata/fuzz/FuzzCrash +stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status' + +-- 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.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 { + 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/cmd/go/testdata/script/test_fuzz_parallel.txt b/src/cmd/go/testdata/script/test_fuzz_parallel.txt new file mode 100644 index 0000000000000000000000000000000000000000..1795e0b2a5178a5a0f4c5a20fa49b380d827ff78 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_parallel.txt @@ -0,0 +1,59 @@ +[!fuzz] 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/fuzz/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/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 0000000000000000000000000000000000000000..5434c723ad2244e2fdcb68354f82ad3038f608e7 --- /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) {}) +} 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 0000000000000000000000000000000000000000..99a4413d32210f7f5fe779cdb1525f02542ae63f --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_run.txt @@ -0,0 +1,143 @@ +[!fuzz] 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") 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 0000000000000000000000000000000000000000..57c8a8ba659aa7049c46f00985469c3957e72d88 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt @@ -0,0 +1,203 @@ +[!fuzz-instrumented] 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 '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 +# 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 '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 'Failing input 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 'Failing input 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 '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) +! stdout 'execs' + +# 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 '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 +# 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 'Failing input 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 'Failing input 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 '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 'Failing input 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 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 { + t.Error("bad thing here") + } + }) +} +-- testdata/fuzz/FuzzWithTestdata/1 -- +go test fuzz v1 +int(10) +-- cache-file -- +go test fuzz v1 +int(10) +-- cache-file-bytes -- +go test fuzz v1 +[]byte("11111111111111111111") 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 0000000000000000000000000000000000000000..2924569de119029083c2a2d5bef7352adc8a9bd1 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_setenv.txt @@ -0,0 +1,45 @@ +[!fuzz] skip +[short] 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/cmd/go/testdata/script/test_fuzz_unsupported.txt b/src/cmd/go/testdata/script/test_fuzz_unsupported.txt new file mode 100644 index 0000000000000000000000000000000000000000..1ed0b8a6f75368e9bf87d739082dc0702fbe9b78 --- /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/go/testdata/script/test_issue45477.txt b/src/cmd/go/testdata/script/test_issue45477.txt new file mode 100644 index 0000000000000000000000000000000000000000..f435b6a6f435d14eb5b646b6e02d6aecdcaf0517 --- /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/cmd/go/testdata/script/test_race_install.txt b/src/cmd/go/testdata/script/test_race_install.txt index 8b1f343a32595495183343d28178850e540f8fc3..a1d47a7dd3c7b544589d22b61b8b8a84679be399 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 diff --git a/src/cmd/go/testdata/script/test_vet.txt b/src/cmd/go/testdata/script/test_vet.txt index 5af26b54f9141bb189bbf15b55edef6fa09c0919..6151f912ae0db150eb1ede771f4628743d12e87a 100644 --- a/src/cmd/go/testdata/script/test_vet.txt +++ b/src/cmd/go/testdata/script/test_vet.txt @@ -16,6 +16,22 @@ 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 #47309 +! go test -vet=bools,xyz ./vetall/... +stderr '-vet argument must be a supported analyzer' + +# Test with a single analyzer +! go test -vet=httpresponse ./vetall/... +stderr 'using resp before checking for errors' + +# Test with a list of analyzers +go test -vet=atomic,bools,nilfunc ./vetall/... +stdout 'm/vetall.*\[no tests to run\]' + # Test issue #22890 go test m/vetcycle stdout 'm/vetcycle.*\[no test files\]' @@ -51,6 +67,21 @@ import "fmt" func F() { fmt.Printf("%d") // oops } +-- vetall/p.go -- +package p + +import "net/http" + +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 diff --git a/src/cmd/go/testdata/script/vendor_list_issue11977.txt b/src/cmd/go/testdata/script/vendor_list_issue11977.txt index ce2e29f99a7902e0313d58e48353e3aa29c1a086..cdab33c0892bff21c93c41a17d155c711be0eb16 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 8615a4aac5978bdf00d8b4c3022a54567cf0cb06..adca7af7a9de3c7e5c8a5db15e4106b3bf446a06 100644 --- a/src/cmd/go/testdata/script/version.txt +++ b/src/cmd/go/testdata/script/version.txt @@ -16,11 +16,18 @@ 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. -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: .+' @@ -28,6 +35,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 @@ -50,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/go/testdata/script/version_build_settings.txt b/src/cmd/go/testdata/script/version_build_settings.txt new file mode 100644 index 0000000000000000000000000000000000000000..dc9e67681ea998049e2da46a0584b1d6d514174a --- /dev/null +++ b/src/cmd/go/testdata/script/version_build_settings.txt @@ -0,0 +1,70 @@ +[short] skip + +# Compiler name is always added. +go build +go version -m m$GOEXE +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\t-asmflags=example\.com/m=-D=FOO=bar$' + +go build -gcflags=example.com/m=-N +go version -m m$GOEXE +stdout '^\tbuild\t-gcflags=example\.com/m=-N$' + +go build -ldflags=example.com/m=-w +go version -m m$GOEXE +stdout '^\tbuild\t-ldflags=example\.com/m=-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\t-tags=a,b$' +[race] go build -race +[race] go version -m m$GOEXE +[race] ! stdout '^\tbuild\t-tags=' +[race] stdout '^\tbuild\t-race=true$' + +# 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=0$' +! 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=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 + +go 1.18 +-- m.go -- +package main + +func main() {} 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 0000000000000000000000000000000000000000..85db9bab6df40230ce5d97c0a2be1f5cc06b5b5d --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_bzr.txt @@ -0,0 +1,107 @@ +# 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 "modified" is tagged. +exec bzr init +cd a +go install +go version -m $GOBIN/a$GOEXE +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. +exec bzr add a README +exec bzr commit -m 'initial commit' +cd a +go install +go version -m $GOBIN/a$GOEXE +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. +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\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 vcs.revision +rm $GOBIN/a$GOEXE + +# 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\tvcs.modified=true$' +rm empty.txt +rm $GOBIN/a$GOEXE + +# 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\tvcs.modified=true$' +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 -- 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 0000000000000000000000000000000000000000..720306868bc3c6f424768e7c7b4f691a5ffd2341 --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_fossil.txt @@ -0,0 +1,93 @@ +# 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 vcs.revision +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\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 vcs.revision +rm $GOBIN/a$GOEXE + +# 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\tvcs=fossil\n' +stdout '^\tbuild\tvcs.modified=true$' +rm empty.txt +rm $GOBIN/a$GOEXE + +# 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\tvcs=fossil\n' +stdout '^\tbuild\tvcs.modified=true$' +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 -- 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 0000000000000000000000000000000000000000..86d1de06df42d9162ca23c01fcc409043a8a2a49 --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_git.txt @@ -0,0 +1,164 @@ +# 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 vcs.revision +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 +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.$' +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 + +# 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 '^\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. +exec git add -A +exec git commit -m 'initial commit' +go install +go version -m $GOBIN/a$GOEXE +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 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\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. +cp ../../outside/empty.txt ../README +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tvcs.modified=true$' +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 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 vcs.revision +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 vcs.revision +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 +-- $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/a/library/f.go -- +package library +-- repo/a/othermain/f.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 0000000000000000000000000000000000000000..fbbd886102e1bf444f03ce54512152ff46ee39be --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_hg.txt @@ -0,0 +1,91 @@ +# 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 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 vcs.revision +! stdout vcs.time +stdout '^\tbuild\tvcs.modified=true$' +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\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 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\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. +cp ../../outside/empty.txt ../README +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tvcs.modified=true$' +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 0000000000000000000000000000000000000000..08d4c92bafb697ef45f8435cc4e53b75f99b8ad1 --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_nested.txt @@ -0,0 +1,51 @@ +[!exec:git] skip +[!exec:hg] skip +[short] 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 + +# 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: 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. +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/go/testdata/script/version_replace.txt b/src/cmd/go/testdata/script/version_replace.txt index ec98f4e3f3ac260341468fd91374a36eaff28cf6..82b8504458be9af7fd5da4322c2b5fa7307bd605 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 diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt new file mode 100644 index 0000000000000000000000000000000000000000..cbb3746a69a9e91fcf2d8abac56c790a583a02dd --- /dev/null +++ b/src/cmd/go/testdata/script/work.txt @@ -0,0 +1,147 @@ +! go work init doesnotexist +stderr 'go: creating workspace file: no go.mod file exists in directory doesnotexist' +go env GOWORK +! stdout . + +go work init ./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' +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, world.' + +# And try from a different directory +cd c +go run example.com/b +stdout 'Hello, world.' +cd $GOPATH/src + +go list all # all includes both modules +stdout 'example.com/a' +stdout 'example.com/b' + +# -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 use 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 + +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 + +# 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.18 + +use ( + a + b + ../src/a +) +-- go.work.want -- +go 1.18 + +use ( + ./a + ./b +) +-- go.work.d -- +go 1.18 + +use ( + a + b + d +) +-- a/go.mod -- + +module example.com/a + +-- a/a.go -- +package a + +import "fmt" +import "rsc.io/quote" + +func HelloFromA() { + fmt.Println(quote.Hello()) +} + +-- b/go.mod -- + +module example.com/b + +-- b/main.go -- +package main + +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() +} + +-- go.work.backwards -- +go 1.18 + +use ( + d + b + a +) + +-- foo.go -- +package main +import "fmt" +func main() { + fmt.Println("Hello, World") +} 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 0000000000000000000000000000000000000000..c9859b437e29cf521d2a301f35e26f8f1db9a6d2 --- /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 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 0000000000000000000000000000000000000000..fd04bbda6e8ffba80a4d748cc82ce446f8cdd6f5 --- /dev/null +++ b/src/cmd/go/testdata/script/work_edit.txt @@ -0,0 +1,161 @@ +# Test editing go.work files. + +go work init m +cmp go.work go.work.want_initial + +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 -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 -use n -use ../a -use /b -use c -use c +cmp go.work go.work.want_multiuse + +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 -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 -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 +cmp stdout formatted + +-- m/go.mod -- +module m + +go 1.18 +-- go.work.want_initial -- +go 1.18 + +use ./m +-- go.work.want_use_n -- +go 1.18 + +use ( + ./m + ./n +) +-- go.work.want_go_118 -- +go 1.18 + +use ( + ./m + ./n +) +-- go.work.want_dropuse_m -- +go 1.18 + +use ./n +-- go.work.want_add_replaces -- +go 1.18 + +use ./n + +replace ( + x.1 v1.3.0 => y.1 v1.4.0 + x.1 v1.4.0 => ../z +) +-- go.work.want_multiuse -- +go 1.18 + +use ( + ../a + ./c + ./n + /b +) + +replace ( + x.1 v1.3.0 => y.1 v1.4.0 + x.1 v1.4.0 => ../z +) +-- go.work.want_multidropuse -- +go 1.18 + +use ( + ../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 + +use ( + ../a + ./c +) + +replace x.1 v1.3.0 => y.1 v1.4.0 +-- go.work.want_print -- +go 1.19 + +use ( + ../a + ./b +) + +replace x.1 v1.4.0 => ../z +-- go.work.want_json -- +{ + "Go": "1.19", + "Use": [ + { + "DiskPath": "../a" + }, + { + "DiskPath": "./b" + } + ], + "Replace": [ + { + "Old": { + "Path": "x.1", + "Version": "v1.4.0" + }, + "New": { + "Path": "../z" + } + } + ] +} +-- unformatted -- +go 1.18 + use ( + a + b + c + ) + replace ( + x.1 v1.3.0 => y.1 v1.4.0 + x.1 v1.4.0 => ../z + ) +-- formatted -- +go 1.18 + +use ( + 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 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 0000000000000000000000000000000000000000..ec3d3be3ed7b885e633c53978b81132c41195b22 --- /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 + +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 new file mode 100644 index 0000000000000000000000000000000000000000..7e2ae4e6ce4ba31e98d2e26c2fc736d5ef79e004 --- /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.1.0$' + +-- go.work -- +go 1.18 + +use ( + ./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") +} 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 0000000000000000000000000000000000000000..a7661b68ad400c025377ae80bfb28e17dda59097 --- /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 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 0000000000000000000000000000000000000000..81268e50697eb74d7a44141b679c806e0790df65 --- /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 -- +use 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 0000000000000000000000000000000000000000..81d1fcb04356b1902974a1cd3cefd42eca89439f --- /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 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' + +-- foo -- +-- go.work -- +use m +use 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 0000000000000000000000000000000000000000..c62084bee692cecef24ac245c332047854f2b724 --- /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 -- +use m +use 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() { +} 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 0000000000000000000000000000000000000000..19dbb90507a57fc26155fa10d153e2db1836293f --- /dev/null +++ b/src/cmd/go/testdata/script/work_sum.txt @@ -0,0 +1,34 @@ +# 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= +-- go.work -- +go 1.18 + +use . +-- go.mod -- +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 + +import ( + "fmt" + "rsc.io/quote" +) + +func main() { + fmt.Println(quote.Hello()) +} \ No newline at end of file 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 0000000000000000000000000000000000000000..9e9474304e5fe6aed4ecabc0aeea2bb43a0a92c3 --- /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 + +use ./a +use ./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 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 0000000000000000000000000000000000000000..69167d4cc14d047e3f704fba628f5a13f6b4aac4 --- /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 + +use ( + ./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 0000000000000000000000000000000000000000..072323d15da8e57974c4b3b29f176ae9b360ff43 --- /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 + +use ( + ./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_missing_module.txt b/src/cmd/go/testdata/script/work_sync_missing_module.txt new file mode 100644 index 0000000000000000000000000000000000000000..0018c733ee7e1df8da22f2111517bbbb24fdfcad --- /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 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 0000000000000000000000000000000000000000..d7997027d9d74f5ed6d01a8569bca903626e2dc7 --- /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 + +use ( + ./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() +} 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 0000000000000000000000000000000000000000..f5ea89c900e2fc160cf8f54f3a68b3dda4317512 --- /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 + +use ( + foo + foo/bar // doesn't exist +) +-- go.want_work_r -- +go 1.18 + +use ( + foo + foo/bar/baz +) +-- go.want_work_other -- +go 1.18 + +use ( + foo + foo/bar/baz + other +) +-- foo/go.mod -- +module foo +-- foo/bar/baz/go.mod -- +module baz +-- other/go.mod -- 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 0000000000000000000000000000000000000000..7964c914a2c5a25aae95ae75c0d705ff02aad451 --- /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 + +use ( + ./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 + 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 0000000000000000000000000000000000000000..b62918147efb71a1e6abc31bac23a940ea93ea78 --- /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 diff --git a/src/cmd/go/testdata/testterminal18153/terminal_test.go b/src/cmd/go/testdata/testterminal18153/terminal_test.go index 71493efe983741d6f3a41b5a9cb72b2036990116..34ee580c0e99705b31be6498eb77e8ed88884ee8 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 b3c120daab42c41c824c91f6bd901b3eeda25a0c..51f6e652d9ae9d4ef97011967a44108412acaeb4 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 ...any) { + 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 f0d3f8780f40e135f2e86f8d21e1feb61dbfecbd..676c5b43ede28074c7f6ed1694e59b8bb930687b 100644 --- a/src/cmd/gofmt/gofmt_test.go +++ b/src/cmd/gofmt/gofmt_test.go @@ -54,13 +54,15 @@ func gofmtFlags(filename string, maxLines int) string { return "" } -var typeParamsEnabled = false - 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] @@ -77,12 +79,7 @@ func runTest(t *testing.T, in, out string) { *simplifyAST = true case "-stdin": // fake flag - pretend input is from stdin - stdin = true - case "-G": - // fake flag - test is for generic code - if !typeParamsEnabled { - return - } + info = nil default: t.Errorf("unrecognized flag name: %s", name) } @@ -91,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 bab22e04cdac00284170d792fa7a4812ff769e9d..a98c6a0cd9b4837d3cfbc23ba68255dfe4c989e2 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) @@ -290,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/cmd/gofmt/testdata/typeparams.golden b/src/cmd/gofmt/testdata/typeparams.golden index 35f08d13792c70e458b0d14fe2c63b9c8c441d74..d57a2ba59b03e6b42ff96656a08c2910c7c2b984 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 @@ -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 7f3212c8e4a8d833045b8e066dd6d515f9ac1f42..775cf9eb7bdc85242b3af2864803855976e08c5c 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 @@ -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/cmd/internal/buildid/buildid_test.go b/src/cmd/internal/buildid/buildid_test.go index e832f9987e582eb9b262c50f12aa4c8abae23fef..f04e328046c0a90ee1bffaba06c259da39a15e62 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") @@ -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 a7928959c483da9f467fefb6209030c8d34b030d..becc0782424ea054d61486ef2bd5979c5499124a 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") } @@ -148,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/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index ec441c2bcb687d898ff75dd0646ffc5ab5230b1b..be3764170694684e2b61f21fb2750c84289fc1c3 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 ) @@ -325,8 +329,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 @@ -360,6 +366,7 @@ const ( DW_ABRV_STRINGTYPE DW_ABRV_STRUCTTYPE DW_ABRV_TYPEDECL + DW_ABRV_DICT_INDEX DW_NABRV ) @@ -455,6 +462,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 +498,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, @@ -854,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. @@ -1168,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") @@ -1266,7 +1313,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 +1324,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 +1359,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 } @@ -1330,11 +1376,14 @@ func putInlinedFunc(ctxt Context, s *FnState, callersym Sym, 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. @@ -1347,6 +1396,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 @@ -1354,8 +1407,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 } @@ -1370,11 +1422,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. @@ -1387,13 +1442,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 { @@ -1402,8 +1460,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 } @@ -1413,6 +1470,47 @@ func PutDefaultFunc(ctxt Context, s *FnState) 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 { @@ -1492,10 +1590,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. @@ -1586,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) { @@ -1620,8 +1723,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/internal/goobj/builtin.go b/src/cmd/internal/goobj/builtin.go index e7d612aeb746f9237ffe93279b186edce70b5770..aa665fde99a6a2957d2c9d9b4e5479fd3091ca39 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/internal/goobj/builtinlist.go b/src/cmd/internal/goobj/builtinlist.go index 9f248137daabce0eb9b07e93cecb8b73c274f1dd..608c0d72223e4ee2d181b7248b8895da076eda33 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/funcinfo.go b/src/cmd/internal/goobj/funcinfo.go index 6d33a10a51cda4cde69a36aaf281f6c61a520a1c..59cb957fa7df5c600f2ab0a373a02784a833dfaa 100644 --- a/src/cmd/internal/goobj/funcinfo.go +++ b/src/cmd/internal/goobj/funcinfo.go @@ -16,23 +16,13 @@ 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 - - InlTree []InlTreeNode + File []CUFileIndex + InlTree []InlTreeNode } func (a *FuncInfo) Write(w *bytes.Buffer) { @@ -44,10 +34,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,19 +41,7 @@ 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 { - writeUint32(x) - } writeUint32(uint32(len(a.File))) for _, f := range a.File { writeUint32(uint32(f)) @@ -84,31 +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 { - NumPcdata uint32 - PcdataOff uint32 - 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 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 - result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:]) - result.FuncdataoffOff = numfuncdataoffOff + 4 - - numfileOff := result.FuncdataoffOff + 4*result.NumFuncdataoff + // 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 numfileOff = 12 result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:]) result.FileOff = numfileOff + 4 @@ -129,34 +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) 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:])) -} - 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/goobj/mkbuiltin.go b/src/cmd/internal/goobj/mkbuiltin.go index 18b969586cceda54f55d97cb010b610032a33888..c9995fcedef8eee70bc68b8477c13fc4697dc313 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 diff --git a/src/cmd/internal/goobj/objfile.go b/src/cmd/internal/goobj/objfile.go index e2858bd57da0ca42abe5eafc7f8df2f7c8a36882..976505839240bd868d96abeca1c26379ba4b8607 100644 --- a/src/cmd/internal/goobj/objfile.go +++ b/src/cmd/internal/goobj/objfile.go @@ -19,21 +19,19 @@ package goobj import ( - "bytes" "cmd/internal/bio" "crypto/sha1" "encoding/binary" "errors" "fmt" "internal/unsafeheader" - "io" "unsafe" ) // 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 @@ -100,7 +98,6 @@ import ( // } // // Data [...]byte -// Pcdata [...]byte // // // blocks only used by tools (objdump, nm) // @@ -204,7 +201,6 @@ const ( BlkReloc BlkAux BlkData - BlkPcdata BlkRefName BlkEnd NBlk @@ -219,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) @@ -304,6 +300,7 @@ const ( const ( SymFlagUsedInIface = 1 << iota SymFlagItab + SymFlagDict ) // Returns the length of the name of the symbol. @@ -333,6 +330,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))) @@ -357,6 +355,8 @@ type SymRef struct { SymIdx uint32 } +func (s SymRef) IsZero() bool { return s == SymRef{} } + // Hash64 type Hash64Type [Hash64Size]byte @@ -592,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 diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go index ccf5f9e7f8d959da412e76835290e8f694b85599..7b1682776e5316ad657f49a361329300eab6098c 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/arm/obj5.go b/src/cmd/internal/obj/arm/obj5.go index 1454d8a7c92045e0f9b6a9af7a282ecfc577d080..38aa11cde9845e3868787cf96ced56947940e247 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/a.out.go b/src/cmd/internal/obj/arm64/a.out.go index bf75bb4a89156cede1626c676a11c58702c647b0..aa7c54df9aefa9180e9e755386af2efacc902485 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/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index d99afa3d27606f362798eeeed403e8e1420dc4c2..68f0921d4d9aa4cecb22122ab512bc9c867ef115 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}, @@ -415,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}, @@ -692,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}, @@ -714,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}, @@ -734,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}, @@ -754,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}, @@ -775,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}, @@ -795,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}, @@ -2089,13 +2070,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 } @@ -3299,8 +3285,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 } @@ -3419,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) } @@ -3736,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) @@ -3883,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) @@ -4198,6 +4195,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 { @@ -4362,6 +4363,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) @@ -4593,6 +4597,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) } @@ -4609,6 +4616,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) @@ -4636,6 +4646,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) } @@ -4941,6 +4954,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) @@ -7039,8 +7055,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/doc.go b/src/cmd/internal/obj/arm64/doc.go index efd4577f56bae0c8c65813df5756890a7c4c1cea..14f0f4c616f227e9b4175195152d8d817b726e5e 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. diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index e41fb3bb7531cb01e7c8319343c2c2cb5730d3ea..e9eb786cb24f602fd21c218731743a3e08a657ce 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -51,8 +51,99 @@ 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), R1 + 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) p.As = AMOVD @@ -63,7 +154,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 +165,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 +191,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 +206,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 +217,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 +227,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 @@ -161,17 +252,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,13 +290,14 @@ 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) 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 @@ -222,7 +317,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 } @@ -301,7 +396,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 } @@ -321,9 +418,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 @@ -631,38 +728,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 +771,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 +805,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 diff --git a/src/cmd/internal/obj/dwarf.go b/src/cmd/internal/obj/dwarf.go index 6dd53ffd1215e839b91d8657101e4a44ee9648c7..29e367aa4cc0ef34ac63eb20a22dc85e2e2f4d29 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) diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 28626e6e037a5c33f131aec8e2ba81aec5cf086c..11af143f22c3c76ced5568c7fd75bbb6ab578f62 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 @@ -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 } @@ -700,6 +701,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 +731,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 { @@ -826,15 +831,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 { @@ -876,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 @@ -902,16 +907,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/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go index 1f31d0c4cdd32768d7f52ddc374594899589930b..b96a28a94423b8ff9cd8875e95daba89cf890d64 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 @@ -658,6 +664,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 +869,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/objfile.go b/src/cmd/internal/obj/objfile.go index 24fb5a19dec5b1dd48f7da55a4dd79be40ac2fe7..fa616691eb5c073eeef20af55d0d5751db0a2bad 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 @@ -340,6 +321,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):], ".") && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath)+1:], objabi.GlobalDictPrefix) { + flag2 |= goobj.SymFlagDict + } name := s.Name if strings.HasPrefix(name, "gofile..") { name = filepath.ToSlash(name) @@ -348,14 +332,29 @@ 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.HasPrefix(name, "runtime.gcbits."), + strings.HasSuffix(name, ".opendefer"), + strings.HasSuffix(name, ".arginfo0"), + strings.HasSuffix(name, ".arginfo1"), + strings.HasSuffix(name, ".argliveinfo"): + // 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 @@ -363,8 +362,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 { @@ -397,7 +397,40 @@ 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 s.IsPcdata() { + return 'P' + } + 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, ".argliveinfo") || + 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 +} + 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 @@ -432,15 +465,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")) @@ -452,6 +480,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}) @@ -652,16 +685,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 { @@ -676,18 +699,6 @@ 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.Pcdata = make([]goobj.SymRef, len(pc.Pcdata)) - for i, pcSym := range pc.Pcdata { - o.Pcdata[i] = makeSymRef(preparePcSym(pcSym)) - } - 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 { @@ -789,10 +800,13 @@ 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() - 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/pcln.go b/src/cmd/internal/obj/pcln.go index 7af81335fb10f61be799c90f4b50d5ca4331cbae..49b425b12415639c0dcbba1d703b32e9b69084ee 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" ) @@ -26,7 +27,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 { @@ -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) @@ -337,7 +336,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))) @@ -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/internal/obj/plist.go b/src/cmd/internal/obj/plist.go index 6beb4dd94cfdc61a9a3716fa6ab7b831fed2ea51..e5bbdd51a7548de50edb7553b79d8686e5e5574e 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 } } @@ -156,7 +173,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 +189,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/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index 428cac528ac3b63748691c80a501e7ea86b99bf1..1e74e64a29fb5ff0089632923935cfe76dd21c0b 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -79,7 +79,43 @@ const ( REG_R30 REG_R31 - /* F0=4128 ... F31=4159 */ + // 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 REG_F1 REG_F2 @@ -113,7 +149,7 @@ const ( REG_F30 REG_F31 - /* V0=4160 ... V31=4191 */ + /* V0=4192 ... V31=4223 */ REG_V0 REG_V1 REG_V2 @@ -147,7 +183,7 @@ const ( REG_V30 REG_V31 - /* VS0=4192 ... VS63=4255 */ + /* VS0=4224 ... VS63=4287 */ REG_VS0 REG_VS1 REG_VS2 @@ -229,7 +265,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 @@ -240,8 +275,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 */ @@ -294,16 +329,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 @@ -329,18 +365,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 @@ -353,41 +384,65 @@ 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) */ + 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 */ + 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 ( @@ -1017,6 +1072,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 fca4b3e35558b464710b4bce6d370e05cceeef99..0da73ca91ed6c9f8d1036e94c481c918ddc39f12 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/anames9.go b/src/cmd/internal/obj/ppc64/anames9.go index b2632aa9ed00918155f408e0576935d3581b2eb6..05bfd944d111f099fa915c3784e35b7d41720fb6 100644 --- a/src/cmd/internal/obj/ppc64/anames9.go +++ b/src/cmd/internal/obj/ppc64/anames9.go @@ -6,19 +6,30 @@ package ppc64 var cnames9 = []string{ "NONE", + "REGP", "REG", + "FREGP", "FREG", "VREG", + "VSREGP", "VSREG", "CREG", + "CRBIT", "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 316959f62d792763b16382e13b8ba6123ee6be06..31fbb7f7bf9723237e816982f71043bc0ba96bd7 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" ) @@ -72,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 @@ -300,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}, @@ -329,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_CRBIT, a2: C_CRBIT, a6: C_CRBIT, type_: 2, size: 4}, /* logical ops for condition register bits xl-form */ /* Vector instructions */ @@ -428,15 +434,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 */ @@ -480,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}, @@ -510,6 +514,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}, @@ -576,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: @@ -642,9 +651,12 @@ 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) @@ -653,22 +665,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 } } @@ -686,27 +750,57 @@ 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 - var out [6]uint32 for p := c.cursym.Func().Text.Link; p != nil; p = p.Link { c.pc = p.Pc o = c.oplook(p) @@ -715,17 +809,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]) @@ -743,49 +840,52 @@ 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_CR0LT <= reg && reg <= REG_CR7SO { + return C_CRBIT + } + 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 REG_DCR0 <= a.Reg && a.Reg <= REG_DCR0+1023 { - 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 { @@ -856,7 +956,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) { @@ -893,35 +993,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 @@ -970,27 +1082,20 @@ 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) 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 } @@ -1004,65 +1109,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. */ + return cmp(C_VSREGP, b) || cmp(C_VREG, b) case C_ANY: return true @@ -1542,7 +1654,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 */ @@ -1925,6 +2036,8 @@ func buildop(ctxt *obj.Link) { ACMPEQB, AECIWX, ACLRLSLWI, + AMTVSRDD, + APNOP, obj.ANOP, obj.ATEXT, obj.AUNDEF, @@ -2023,50 +2136,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, */ @@ -2074,7 +2169,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 */ @@ -3302,56 +3397,46 @@ 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 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 */ + 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 */ - 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) */ - } + 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 @@ -3534,33 +3619,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 */ @@ -3691,6 +3751,13 @@ 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)) + + 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 70dabc20175a61ffddb75683b8056b3f6cfe6d0a..ee2e5962f753ea43fdf6e5500858d911a73fd513 100644 --- a/src/cmd/internal/obj/ppc64/asm_test.go +++ b/src/cmd/internal/obj/ppc64/asm_test.go @@ -5,8 +5,13 @@ package ppc64 import ( + "bytes" + "cmd/internal/obj" + "cmd/internal/objabi" + "fmt" "internal/testenv" "io/ioutil" + "math" "os" "os/exec" "path/filepath" @@ -15,14 +20,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 @@ -35,6 +46,287 @@ ADD $4, R8 RET ` +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 +// 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. @@ -107,3 +399,157 @@ 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}, + {REG_CR0LT, REG_CR7SO, 31, 0}, + } + for _, t := range testType { + 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_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}, + {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])) + } + } + } +} diff --git a/src/cmd/internal/obj/ppc64/doc.go b/src/cmd/internal/obj/ppc64/doc.go index 6e601df82e3060f8931a27f472b70bbdec8677b7..a9d89c93b4ef00bb3f3cee34d95f3b8d58ede47e 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 461950dc6054e474bebcb2ac6c3a71604c0970d1..ea0dae9e0283638d430343d8315ddac3d9a058ba 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) } @@ -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" } @@ -80,9 +85,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" } diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index c2722b0afb05de401ecb5fc1ba2af29ac69c8465..c986c0d2b6e27ec13d1b712dd720a9223adb327c 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) @@ -885,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 @@ -1049,9 +1053,98 @@ 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 g_stackguard(g), R3 + // 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) p.As = AMOVD @@ -1062,7 +1155,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 +1171,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 +1201,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 +1227,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 +1244,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 +1282,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,13 +1349,14 @@ 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) 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/anames.go b/src/cmd/internal/obj/riscv/anames.go index 6581bb34022ad1ebf3a27f9f8e04023f495cca36..d2a3674ebef8d434e01980486d02fe258e4c3d4c 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/asm_test.go b/src/cmd/internal/obj/riscv/asm_test.go index f8f7b4f2ced0756c5c9ea868cf074a0e55062060..b23142dbe8ecb503ff6c683b3f9c75496bf90bc7 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") @@ -134,9 +201,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/cpu.go b/src/cmd/internal/obj/riscv/cpu.go index b1324b62a0377ea415e6654258a01c10c149e6e3..d9434e74158ba8daeed3768333836ac260ea0296 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, @@ -256,15 +256,23 @@ 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_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. - 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 @@ -586,6 +594,8 @@ const ( ABLEZ ABLTZ ABNEZ + AFABSD + AFABSS AFNEGD AFNEGS AFNED @@ -626,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 @@ -637,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 a305edab4b39348dcb803815e6ab842d28d724a7..5755b118db00f2833d5de75a3cc711d9535c05fb 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 = 0 - 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 = 0 - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_TMP - p.To.Sym = to.Sym - - return p + p.Reg = obj.REG_NONE } // progedit is called individually for each *obj.Prog. It normalizes instruction @@ -72,7 +50,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 +132,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 @@ -218,169 +196,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 p.From.Type { - case obj.TYPE_MEM: // MOV c(Rs), Rd -> L $c, Rs, Rd - 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) - } - 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) - } - - 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) + 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 obj.TYPE_MEM: // MOV Rs, c(Rd) -> S $c, Rs, Rd - switch p.As { - case AMOVBU, AMOVHU, AMOVWU: - ctxt.Diag("unsupported unsigned store at %v", p) + 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_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) } - - default: - ctxt.Diag("unsupported MOV at %v", p) } - - 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 { - 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 - - 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 = 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) - } - - default: - ctxt.Diag("unsupported MOV at %v", p) } } @@ -443,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. @@ -590,7 +428,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) @@ -610,7 +448,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) @@ -637,7 +475,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) @@ -672,7 +510,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: @@ -680,8 +518,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) } } @@ -707,11 +544,11 @@ 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} - p.Reg = 0 + p.Reg = obj.REG_NONE p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} } @@ -746,135 +583,26 @@ 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. + var callCount int 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) - } - } - - // 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 - } - - 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} - - // $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) - 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} + 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 { @@ -899,8 +627,27 @@ 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") + 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 if offset < -(1<<20) || (1<<20) <= offset { @@ -917,7 +664,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 @@ -935,7 +682,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 @@ -943,6 +690,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) @@ -969,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 @@ -1061,14 +870,14 @@ 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) 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) @@ -1089,10 +898,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 } @@ -1165,14 +974,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) } } @@ -1182,13 +991,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))) } } @@ -1205,7 +1014,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) } } @@ -1213,60 +1022,81 @@ 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, "rs2", ins.rs2) + 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, "rs2", ins.rs2) + 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, "rs2", ins.rs2) + 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, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateB(ctxt *obj.Link, ins *instruction) { @@ -1277,6 +1107,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) { @@ -1284,6 +1115,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) { @@ -1294,13 +1126,14 @@ 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) { // 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) } } @@ -1316,6 +1149,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) } @@ -1324,6 +1173,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) } @@ -1402,6 +1255,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) @@ -1410,7 +1268,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 { @@ -1422,6 +1280,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) @@ -1461,12 +1329,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} @@ -1608,13 +1477,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, @@ -1646,13 +1519,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, @@ -1718,9 +1595,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) { @@ -1751,8 +1629,12 @@ 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 { +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{ as: p.As, rd: uint32(p.To.Reg), @@ -1760,43 +1642,190 @@ 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) + } + 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, ins.rs2 = as, uint32(rs), obj.REG_NONE + + 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} + } - inss := []*instruction{ins} + // Split into two additions, if possible. + // 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 + + // 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 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 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 + if low == 0 { + return []*instruction{insLUI, ins} + } + return []*instruction{insLUI, insADDIW, ins} +} - 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) +// 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 as { + case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD: + default: + p.Ctxt.Diag("%v: unknown load instruction %v", p, as) + return nil + } + + // $imm, REG, TO (load $imm+(REG), TO) + ins := instructionForProg(p) + ins.as, ins.rs1, ins.rs2 = as, uint32(rs), 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} +} + +// 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 as { + case ASW, ASH, ASB, ASD, AFSW, AFSD: + default: + p.Ctxt.Diag("%v: unknown store instruction %v", p, as) + return nil + } + + // $imm, REG, TO (store $imm+(TO), REG) + ins := instructionForProg(p) + 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) + 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 { + ins := instructionForProg(p) + inss := []*instruction{ins} + + 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 } - ins.imm = p.To.Offset - 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 { + 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 = AADDI, 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} + inss = []*instruction{insLUI} + if low != 0 { + ins.as, ins.rs1 = AADDIW, ins.rd + 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 { 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 @@ -1830,27 +1859,149 @@ func instructionsForProg(p *obj.Prog) []*instruction { inss = append(inss, ins2) } - 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) + 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: + // 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} + 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 } - ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE - ins.imm = p.From.Offset - case ASW, ASH, ASB, ASD, AFSW, AFSD: - if p.To.Type != obj.TYPE_MEM { - p.Ctxt.Diag("%v requires memory for destination", p) + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM: + // Register to memory stores. + switch p.As { + case AMOVBU, AMOVHU, AMOVWU: + p.Ctxt.Diag("%v: unsupported unsigned store", p) return nil } - ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE + 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: + // 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} + 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)) + + 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: + 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 +} + +// 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: + return instructionsForLoad(p, ins.as, p.From.Reg) + + case ASW, ASH, ASB, ASD, AFSW, AFSD: + return instructionsForStore(p, ins.as, p.To.Reg) + case ALRW, ALRD: // Set aq to use acquire access ordering, which matches Go's memory requirements. ins.funct7 = 2 ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO + case AADDI, AANDI, AORI, AXORI: + 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: // Set aq to use acquire access ordering, which matches Go's memory requirements. @@ -1898,6 +2049,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 @@ -1921,7 +2078,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: @@ -1929,6 +2086,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 @@ -1950,37 +2117,43 @@ 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: - 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 AAUIPC: + 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: + 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 { @@ -1999,25 +2172,23 @@ 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 { - symcode = append(symcode, ic) + 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 } } } - 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) } 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{ 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 de412c64a7832b4ab4dfed9c87dd25d446a25d0d..68d9589bf26174d3da3f24d07f3ef5d5cb31533a 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 { diff --git a/src/cmd/internal/obj/s390x/objz.go b/src/cmd/internal/obj/s390x/objz.go index 201163b0159a1883bde0570d9a516f6a49ab9113..aebbf8dbc55f1a02a2fd9155f6802bcc16b6b34c 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 @@ -487,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 @@ -563,14 +569,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 +660,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 +685,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 +711,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 +758,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/sym.go b/src/cmd/internal/obj/sym.go index 9e8b4dd790f001435f4eac4a48d3d6a267797d32..a8360527ef725fdbaad5957964232e096127f20e 100644 --- a/src/cmd/internal/obj/sym.go +++ b/src/cmd/internal/obj/sym.go @@ -34,12 +34,12 @@ package obj import ( "cmd/internal/goobj" "cmd/internal/objabi" + "crypto/md5" "fmt" "internal/buildcfg" "log" "math" "sort" - "strings" ) func Linknew(arch *LinkArch) *Link { @@ -173,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). @@ -202,13 +210,14 @@ 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) { - 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)) { @@ -324,13 +333,19 @@ 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)) { - lists := [][]*LSym{ctxt.Text, ctxt.Data, ctxt.ABIAliases} + fnNoNil := func(s *LSym) { + if s != nil { + fn(s) + } + } + lists := [][]*LSym{ctxt.Text, ctxt.Data} for _, list := range lists { for _, s := range list { if flag&traverseDefs != 0 { @@ -338,15 +353,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 +365,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) + } + } } } } @@ -410,7 +431,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 { diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go index e8441a69694452544092ef6225fdd8c7d8e3143f..0c9dde7965797c7e39fd4a4095c3edb8a0b597de 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", diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go index ceeae7a257cdcc33313b85c31715fe53ead79a74..1c726f77d34869c9fad72b77ca357aaf2237ed3d 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) { @@ -249,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 @@ -309,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 @@ -347,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} @@ -423,12 +469,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 +519,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 +531,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/aenum.go b/src/cmd/internal/obj/x86/aenum.go index 2c035641f557249b8127266bf1d2bd0bf5f95d2e..f0913d7c55194d823aa5e130ec546417f9564adf 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 e6c00bdbe0e9a88e8f827d294c8edf342c52d79a..7869e366f9be0f07cb7ebb8732ac74979d5f5a2f 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 17fa76727e6212061f46548664530c88570ff734..a508e484e4741c6ee0f6d4a449ea3d6d0e9748bc 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. @@ -1736,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}}, @@ -2036,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 { @@ -2170,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") } diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index e2732d53e3067b4d21c7774d84b180a90908ee22..a82285a0d319448717072cc2d1f9447e8ca82340 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" @@ -645,20 +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 && buildcfg.Experiment.RegabiG && 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 - } - } var regEntryTmp0, regEntryTmp1 int16 if ctxt.Arch.Family == sys.AMD64 { regEntryTmp0, regEntryTmp1 = REGENTRYTMP0, REGENTRYTMP1 @@ -666,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. @@ -975,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 @@ -989,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 { @@ -1002,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 @@ -1028,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 @@ -1173,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) @@ -1181,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/src/cmd/internal/objabi/flag.go b/src/cmd/internal/objabi/flag.go index e41fc570b0894926a29ccd0736fb4199f53b0c6c..f75c054fcb6110c332dfd12d5ec9fdd66d47b5fe 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 "" +} diff --git a/src/cmd/internal/objabi/funcdata.go b/src/cmd/internal/objabi/funcdata.go index 4ff0ebe13d8dba777a742e6ac1f622a6508e933e..4d49a8d548dee836902669f3f35f5cd446e41ed1 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/internal/objabi/funcid.go b/src/cmd/internal/objabi/funcid.go index 93ebd7be943205e9044d5f0fe66fb66f9bda8d82..084fcdf712159104aca4cc33bed4a940074de696 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 @@ -34,7 +35,6 @@ const ( FuncID_gogo FuncID_gopanic FuncID_handleAsyncEvent - FuncID_jmpdefer FuncID_mcall FuncID_morestack FuncID_mstart @@ -60,7 +60,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, @@ -74,7 +73,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/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go index 52827a6deeec5c6a3bcc6606aef5201bdf785c12..a9c3030181aead1f6fea67f4ad33469088838c86 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 @@ -95,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 @@ -218,6 +221,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 +286,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 4638ef14d91f62b58be4b6e199d79432d573040b..d1b15b5a194f29f0d5faba7dbad5570fdd8044cf 100644 --- a/src/cmd/internal/objabi/reloctype_string.go +++ b/src/cmd/internal/objabi/reloctype_string.go @@ -20,19 +20,19 @@ 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_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_USEGENERICIFACEMETHOD-25] _ = x[R_METHODOFF-26] _ = x[R_KEEP-27] _ = x[R_POWER_TOC-28] @@ -58,21 +58,23 @@ func _() { _ = 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_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_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_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, 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, 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/internal/objabi/symkind.go b/src/cmd/internal/objabi/symkind.go index 6c991121e72d5d222984ca38cc52db6e6b2ad73b..28f430fc547cbd2160ecdde32f6665951d9332bf 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 1b1c394038a7d9cea376bcd17357c0de06f129ac..c90cf43b502ef12e55c1ab54bb802e716f36c74e 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/internal/objabi/util.go b/src/cmd/internal/objabi/util.go index 63640950d9f8ee609ad30e607c1528b4664d5b77..6bfa25a5caec05da06a1bd5cb3c9b725f642b85c 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 diff --git a/src/cmd/internal/objfile/goobj.go b/src/cmd/internal/objfile/goobj.go index dd21d223511198448d127596c53095c1ab924700..24d2d0bb5c7b76c9ab91f9123d298f04b1e1c295 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. diff --git a/src/cmd/internal/objfile/objfile.go b/src/cmd/internal/objfile/objfile.go index dcfd158ec209274891640b0cd74fc35611fb0026..d890a0b7562cf4177afc03df877d271a0b499ad3 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/cmd/internal/quoted/quoted.go b/src/cmd/internal/quoted/quoted.go new file mode 100644 index 0000000000000000000000000000000000000000..e7575dfc669c5e0601b08c9837449423942b45e6 --- /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/quoted/quoted_test.go b/src/cmd/internal/quoted/quoted_test.go new file mode 100644 index 0000000000000000000000000000000000000000..d76270c87b493e31907b155d3ff9a1695205e81e --- /dev/null +++ b/src/cmd/internal/quoted/quoted_test.go @@ -0,0 +1,88 @@ +// 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 quoted + +import ( + "reflect" + "strings" + "testing" +) + +func TestSplit(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 := Split(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 TestJoin(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 := Join(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) + } + }) + } +} diff --git a/src/cmd/internal/sys/arch.go b/src/cmd/internal/sys/arch.go index a3e39768b6f5057488be62711d80de8dcbe459ac..ea76b596c15cbc2079d62069d6ea180ac1d5d240 100644 --- a/src/cmd/internal/sys/arch.go +++ b/src/cmd/internal/sys/arch.go @@ -16,6 +16,7 @@ const ( ARM ARM64 I386 + Loong64 MIPS MIPS64 PPC64 @@ -46,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 @@ -60,133 +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 + 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{ @@ -194,6 +224,7 @@ var Archs = [...]*Arch{ ArchAMD64, ArchARM, ArchARM64, + ArchLoong64, ArchMIPS, ArchMIPSLE, ArchMIPS64, diff --git a/src/cmd/internal/sys/args.go b/src/cmd/internal/sys/args.go new file mode 100644 index 0000000000000000000000000000000000000000..cc9fb64af2dc021e7b94ff752c21cfa7c00ba902 --- /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) diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index 0d2bad961278f4392c3c27a1ecc4617ac2d9b74c..f25aaabddd60ea8c044bc7f8ae5a6068d8796f0e 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -34,6 +34,41 @@ 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": + return goarch == "arm64" || goarch == "amd64" + default: + return false + } +} + +// 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 { @@ -70,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", @@ -123,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/internal/test2json/test2json_test.go b/src/cmd/internal/test2json/test2json_test.go index 4683907888cdb618c910a2a7e04b5a8c3c94898c..e69739d3fecdef5a643838e0e439b34d6797f1e5 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 871477447f159454664d222838c72dedf0d5671a..3636c1053de04708d0d85782ace7275d7a24d173 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/link/doc.go b/src/cmd/link/doc.go index 604675caecf1f2ed72398a63a119931821ac6d5a..98c954f0f1ad76e871bb6c8a504d29a64bf0cbe4 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/dwarf_test.go b/src/cmd/link/dwarf_test.go index 3ca59bd47f025cf1eac24eac43fddec1700c2348..78ef3cfe9713691cbb053a8e180cff02dcd66820 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/quoted" "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 := quoted.Split(extld) + if err != nil { + t.Fatal(err) + } + expectDWARF, err = cmddwarf.IsDWARFEnabledOnAIXLd(extldArgs) if err != nil { t.Fatal(err) } diff --git a/src/cmd/link/elf_test.go b/src/cmd/link/elf_test.go index 012c0b51696f8ddfcaae71d48ae8ba5ae315215e..760d9ea60d92d53555a271800350dcc3988ab1a0 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/arm/asm.go b/src/cmd/link/internal/arm/asm.go index ab780214bb65f547c3dc89d7446939fade4e7c63..347932c6e1dbf97cf8985c5e14d9f509077331d4 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 c10bdc4120a601676efdede7bb6859d1b13229fe..abae0f87bcda689c7d2253535f5b38c017092a03 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)) @@ -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/dwtest/dwtest.go b/src/cmd/link/internal/dwtest/dwtest.go new file mode 100644 index 0000000000000000000000000000000000000000..c68edf4187fe1d7e9366f1aa8ebaa70c90aae271 --- /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/config.go b/src/cmd/link/internal/ld/config.go index 20f1d0b8c12c6848fd68f83a7e4b41cd1c9f2b7a..33ab7c3df36777db19d10ef74a46588394704701 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() } @@ -193,10 +193,13 @@ 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 - // 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 +212,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). @@ -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 70fbb9dc4e24cf2d47c78c89b072684625735784..95a8e0facb41f92253a05b4ac2acdb68aa44e9d3 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,8 +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 } - rs = ldr.ResolveABIAlias(rs) - 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 @@ -125,7 +128,6 @@ func trampoline(ctxt *Link, s loader.Sym) { continue // runtime packages are laid out together } } - thearch.Trampoline(ctxt, ldr, ri, rs, s) } } @@ -194,7 +196,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)) { @@ -226,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 @@ -340,7 +343,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++ @@ -436,6 +438,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" { @@ -609,7 +616,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 @@ -621,10 +628,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 @@ -639,13 +645,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 @@ -687,7 +693,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() @@ -700,7 +706,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) @@ -1164,13 +1170,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 { @@ -1370,6 +1369,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) @@ -1705,21 +1709,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 */ @@ -1789,7 +1781,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 { @@ -2175,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 @@ -2192,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 @@ -2450,6 +2451,12 @@ func splitTextSections(ctxt *Link) bool { return (ctxt.IsPPC64() || (ctxt.IsARM64() && ctxt.IsDarwin())) && ctxt.IsExternal() } +// 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 + 8192 + // address assigns virtual addresses to all segments and sections and // returns all segments in file order. func (ctxt *Link) address() []*sym.Segment { @@ -2459,10 +2466,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) @@ -2529,6 +2540,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 @@ -2540,17 +2552,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 } } @@ -2667,6 +2679,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 @@ -2685,6 +2702,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/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 416e5da39838fe73a68f663c6914869571a444ba..dba22323b0c5ea664c9e63056b0e1285e10e1f2d 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()) } @@ -69,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") @@ -96,8 +92,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. @@ -132,7 +130,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() @@ -193,6 +193,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) { @@ -327,8 +334,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 @@ -348,7 +355,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) @@ -408,6 +415,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))) } @@ -418,6 +428,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/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index c53d2408cbe5105fd9011b416e2d2d738241200d..47b4921cd8fe6f58290330cf9769e93151951455 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. @@ -187,6 +173,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, @@ -239,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 @@ -247,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 @@ -280,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 @@ -288,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 @@ -311,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) @@ -387,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 { @@ -471,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 @@ -503,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) @@ -548,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) @@ -557,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) @@ -567,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) @@ -597,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 @@ -605,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) @@ -615,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 @@ -644,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) @@ -654,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++ { @@ -683,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)) @@ -693,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("")) } @@ -744,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 @@ -772,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) } @@ -867,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) } @@ -912,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) }) @@ -926,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) }) @@ -937,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)) } @@ -1190,7 +1182,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") @@ -1425,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. @@ -1618,7 +1610,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()}} } @@ -1662,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) @@ -1755,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. @@ -1766,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) @@ -1831,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() @@ -1889,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) || @@ -1902,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 2f59c2fe0aa9484a0294170ad7e21fa6a0710ca0..2f9bf25d101c1fcb1f0f4d63bb885745e4f6b441 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -7,10 +7,11 @@ 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" "io" "io/ioutil" @@ -101,8 +102,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) } @@ -348,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) } @@ -369,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 { @@ -392,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) @@ -420,200 +427,12 @@ 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) 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() @@ -655,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) } @@ -676,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 { @@ -686,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) } @@ -695,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)) @@ -734,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'", @@ -746,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) @@ -779,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 { @@ -796,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) } @@ -806,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") } @@ -820,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) } } @@ -848,9 +671,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") @@ -866,9 +686,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") } @@ -887,9 +704,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) @@ -985,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") @@ -1509,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) } @@ -1529,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") @@ -1643,6 +1457,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 *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: + // + // -1: varparm attr not found + // 1: varparm found with value false + // 2: varparm found with value true + // + foundParams := make(map[string]string) + + // 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 { + // 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) @@ -1682,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) } @@ -1702,56 +1576,270 @@ 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. + // 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 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 found != expected { + t.Errorf("param check failed, wanted:\n%s\ngot:\n%s\n", + expected, found) + } +} + +func TestDictIndex(t *testing.T) { + // 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" { + 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" + +type CustomInt int + +func testfn[T any](arg T) { + var mapvar = make(map[int]T) + mapvar[0] = arg + fmt.Println(arg, mapvar) +} + +func main() { + testfn(CustomInt(3)) +} +` + + 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 + } + } - // 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: + 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)) + } + } + + rdr.Seek(0) + 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"} { + 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) + } + } +} + +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: // - // -1: varparm attr not found - // 1: varparm found with value false - // 2: varparm found with value true + // - 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 // - foundParams := make(map[string]string) + // The scenarios below don't cover all possible permutations and + // combinations, but they hit a bunch of the high points. - // 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++ - } - } + 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} } +} - // Digest the result. - found := make([]string, 0, len(foundParams)) - for k, v := range foundParams { - found = append(found, fmt.Sprintf("%s:%s", k, v)) +// 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} } - sort.Strings(found) +} - // 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. - 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", - expected, found) +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 := dwtest.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) + } } } diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index 81011638bc5fae6b52cf2898d2849dced105c74d..4a143dfcaa10acfdd2088baf6e26a25368864982 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" ) @@ -480,10 +481,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 +1469,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 +1496,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() { @@ -1685,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 */ @@ -1749,7 +1751,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 } @@ -1790,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 { @@ -1802,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. @@ -2028,6 +2018,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: diff --git a/src/cmd/link/internal/ld/ld.go b/src/cmd/link/internal/ld/ld.go index 7ff9c41f96dda260fd0651b109a8aedd947ceb94..954921844c9280a30ec0a8f3f360248c74f6afa0 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/cmd/link/internal/ld/ld_test.go b/src/cmd/link/internal/ld/ld_test.go index 3702a4d08f586f3674da2f083cbdc493a939586c..2d5a7add9d22d146660763eacf891d31151c4c3e 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/lib.go b/src/cmd/link/internal/ld/lib.go index 644faeb2fbc2fd039b65681621a296cc700d2e53..9e13db7b718783597d8a42644ef6e5c3fc8441a8 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -144,21 +144,14 @@ 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) - // 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) @@ -288,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 { @@ -323,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 @@ -388,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))) @@ -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) @@ -506,10 +507,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 { @@ -535,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] @@ -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 } @@ -773,7 +775,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) @@ -1019,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 { @@ -1100,7 +1103,6 @@ func hostlinksetup(ctxt *Link) { *flagTmpdir = dir ownTmpDir = true AtExit(func() { - ctxt.Out.Close() os.RemoveAll(*flagTmpdir) }) } @@ -1240,7 +1242,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 +1403,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 +1418,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,17 +1488,29 @@ 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) } 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 { @@ -1567,14 +1585,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 ")) { @@ -1639,13 +1661,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. @@ -1718,8 +1758,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 @@ -2111,7 +2150,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") { @@ -2152,19 +2191,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}) } @@ -2319,7 +2345,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. @@ -2480,7 +2506,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/link.go b/src/cmd/link/internal/ld/link.go index 13618beff977a5a5aef902edd354bf6a644d7660..64d18bd62c0752ec012160f7a818d5a987d4af5f 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. diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index 45a3971c33f5463ffc52094baedde2aa5e40696e..8633222ee332fbd9cb717a49acff6af2c15bb2cf 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 { @@ -898,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) diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index cba0e3d81feaea6fafcba964c200b50d96e6d714..26f9db8ec410bf3dbc5a2265c51cc95d6700863d 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/quoted" "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. @@ -66,14 +69,15 @@ 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`") 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 quoted.Flag + flagExtldflags quoted.Flag flagExtar = flag.String("extar", "", "archive program for buildmode=c-archive") flagA = flag.Bool("a", false, "no-op (deprecated)") @@ -168,8 +172,16 @@ 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 { + abiInternalVer = 0 + } + startProfile() if ctxt.BuildMode == BuildModeUnset { ctxt.BuildMode.Set("exe") diff --git a/src/cmd/link/internal/ld/outbuf.go b/src/cmd/link/internal/ld/outbuf.go index 9d5e8854fea65418c75c30717f865f80cfbd03bc..1d21dce9c5a27e0f33e31f02a8df6f44e3e8fa78 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/outbuf_darwin.go b/src/cmd/link/internal/ld/outbuf_darwin.go index 9444b6567e8b723b03560154e1271f65ae3c4907..b1ee3c56282d347111cfdf8afe33ea86780425c3 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 ( @@ -9,6 +12,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 +36,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() { diff --git a/src/cmd/link/internal/ld/outbuf_nofallocate.go b/src/cmd/link/internal/ld/outbuf_nofallocate.go index 6564bd54a3d1bcf27977493fedff76c829c34d0d..3bffe4543dd9bda905292e365cfda72b7113249c 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 f9caa413e3c3c198a906d362e2a0e4aa7e5d8b99..85e64421a30f48064e54b581a8181871eafb79c2 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 diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 05fd30236949671419e6fd0e7efa13b7763b575c..b57e212794625735471f74af83baddeefc8da0f3 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -14,13 +14,13 @@ import ( "internal/buildcfg" "os" "path/filepath" + "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 @@ -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 @@ -68,15 +68,10 @@ 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: uint32(ctxt.Arch.PtrSize + 9*4), - } + state := new(pclntab) // Gather some basic stats and info. seenCUs := make(map[*sym.CompilationUnit]struct{}) - prevSect := ldr.SymSect(ctxt.Textp[0]) compUnits := []*sym.CompilationUnit{} funcs := []loader.Sym{} @@ -90,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. @@ -129,11 +114,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())) { @@ -148,13 +132,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: @@ -179,6 +158,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) @@ -225,8 +205,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 +221,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 @@ -287,11 +278,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) } } @@ -299,7 +314,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) @@ -460,22 +476,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) } } @@ -496,11 +515,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 @@ -509,119 +528,44 @@ func numPCData(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 layout 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 walkPCToFunc. (3) is handled in walkFuncdata. -// -// 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.writeFuncData(ctxt, sb, funcs, inlSyms, startLocations, setAddr, (*loader.SymbolBuilder).SetUint) } - 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) - 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. -// 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 @@ -630,137 +574,88 @@ 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 - // 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) fi := ldr.FuncInfo(s) - size += int64(state.funcSize) + size += 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 } } - size += int64(numPCData(fi) * 4) - if numFuncData > 0 { // Func data is aligned. - size = Rnd(size, int64(ctxt.Arch.PtrSize)) - } - size += int64(numFuncData * ctxt.Arch.PtrSize) + size += int64(numPCData(ldr, s, fi) * 4) + size += int64(numFuncData * 4) } } return size, startLocations } -// 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) { +// writePCToFunc writes the PC->func lookup table. +func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, startLocations []uint32) { ldr := ctxt.loader - 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. - // 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)) - 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])) - funcIndex++ - - // Write the entry location. - setAddr(sb, ctxt.Arch, int64(startLocations[i]), s, 0) + 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) } - - // Final entry of table is just end pc. - 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, funcdataoff := []loader.Sym{}, []int64{} 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, funcdataoff := funcData(fi, inlSyms[s], funcdata, funcdataoff) - if len(funcdata) > 0 { - off := int64(startLocations[i] + state.funcSize + numPCData(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])) - continue - } - // TODO: Does this need deduping? - setAddr(sb, ctxt.Arch, dataoff, funcdata[j], funcdataoff[j]) - } - } + 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. + 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. 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) - funcdata, funcdataoff := []loader.Sym{}, []int64{} + deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) + gofunc := ldr.Lookup("go.func.*", 0) + gofuncBase := ldr.SymValue(gofunc) + textStart := ldr.SymValue(ldr.Lookup("runtime.text", 0)) + funcdata := []loader.Sym{} + 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 inn - // walkPCToFunc. We don't write it here, because it might require a - // relocation. - off := startLocations[i] + uint32(ctxt.Arch.PtrSize) // entry + 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 = 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. @@ -768,57 +663,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(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 = 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(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, funcdataoff = funcData(fi, 0, funcdata, funcdataoff) - off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(len(funcdata)))) + funcdata = funcData(ldr, s, fi, 0, funcdata) + off = sb.SetUint8(ctxt.Arch, off, uint8(len(funcdata))) // Output the pcdata. if fi.Valid() { - for j, pcSym := range fi.Pcdata() { - sb.SetUint32(ctxt.Arch, int64(off+uint32(j*4)), uint32(ldr.SymValue(pcSym))) + for j, pcSym := range pcdata { + 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(fi.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 = int64(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4) + for j := range funcdata { + dataoff := off + int64(4*j) + fdsym := funcdata[j] + if fdsym == 0 { + 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, dataoff, uint32(ldr.SymValue(fdsym)-gofuncBase)) } } } diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 8eb4231c3ab2895f095e2b1197e92d60659eb177..b7d413e9a9eb00a3886fbf39874ed840ee48bea4 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 @@ -1512,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/sym.go b/src/cmd/link/internal/ld/sym.go index 72639962e2ffa6b76a5a40a1219f61c183ef9a3a..d51a59ef467372ec0d23bd8307c0b3dfc7f614ba 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() } }) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 00f557875a939a0dc1addf0d9319ae64e628b1c0..720c03afd2a290d31ebd46037846041ce513ff87 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) @@ -405,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) @@ -506,13 +506,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) @@ -524,6 +520,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++ { @@ -536,33 +534,13 @@ 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. - symGroupType[s] = sym.STYPERELRO - case strings.HasPrefix(name, "go.string."): symGroupType[s] = sym.SGOSTRING 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) @@ -573,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 { @@ -584,20 +562,39 @@ 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, + 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, ".argliveinfo"), + strings.HasSuffix(name, ".args_stackmap"), + strings.HasSuffix(name, ".stkobj"): ldr.SetAttrNotInSymbolTable(s, true) + symGroupType[s] = sym.SGOFUNC ldr.SetCarrierSym(s, symgofunc) - align := int32(4) - if a := ldr.SymAlign(s); a < align { - ldr.SetSymAlign(s, align) + if ctxt.Debugvlog != 0 { + align := ldr.SymAlign(s) + 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 { - align = a + symGroupType[s] = sym.STYPE + if symtyperel != 0 { + ldr.SetCarrierSym(s, symtype) + } } - liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) } } @@ -675,10 +672,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("runtime.rodata", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go.func.*", 0)) 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)) @@ -687,6 +686,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 diff --git a/src/cmd/link/internal/ld/target.go b/src/cmd/link/internal/ld/target.go index f68de8fff13fa83411c3208f5cae16631217631b..58d45d1504677376163e563bb35c95d47969501e 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 12bd23f7e57e1d9410d3c2309ab1938c2b8d3bc9..aaddf19d16a730f417f1ce9905d4700dca45912c 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, @@ -1238,7 +1241,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) @@ -1287,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 @@ -1333,7 +1332,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/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go index c6956297f6c79f8ba62b7e68a6609a0579353b97..d05d8e3b4b691ae2e6e39ae9bc6d60ae172d975b 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. @@ -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 diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 9d5319c31207887082b64f290b3e78de0e09044e..34c1c6a4c86c52a95e3f6aefcc1192e8ba4280ff 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 { @@ -753,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) { @@ -1209,6 +1192,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] @@ -1540,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). @@ -1898,12 +1870,98 @@ 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 +} + +// 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 } @@ -1925,76 +1983,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") - } - 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") @@ -2046,25 +2040,12 @@ 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 { b := r.Data(a.Sym().SymIdx) - return FuncInfo{l, r, b, auxs, goobj.FuncInfoLengths{}} + return FuncInfo{l, r, b, goobj.FuncInfoLengths{}} } } return FuncInfo{} @@ -2183,7 +2164,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 } @@ -2209,7 +2190,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 +2199,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) @@ -2288,27 +2269,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 @@ -2632,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) } diff --git a/src/cmd/link/internal/loader/symbolbuilder.go b/src/cmd/link/internal/loader/symbolbuilder.go index 204d04412dc24985fa3cb7a560989a840026170e..558c0a7dfffbdf3fd89d3f5a15254be41c8f08fc 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") diff --git a/src/cmd/link/internal/loadmacho/ldmacho.go b/src/cmd/link/internal/loadmacho/ldmacho.go index e7d9eebc33f792236e84bc0a9ae725756963f098..5402ecd74848522e9a23131796b7081631c9badb 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. diff --git a/src/cmd/link/internal/mips/asm.go b/src/cmd/link/internal/mips/asm.go index 8505dc61093a6de0726f3f61b9947c8815e5b64a..5891d35888a8196e354eb084ab8f4b90b927bd46 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 f7f91d1e8b2c8b98ed6eaf14f33c43eee4c1ec64..0e64af3e6ae194b4f61387b4c81d113ef1422325 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 b877864b759beca3a1fe7eab405ed5459c1f7da8..d2b140b45dee9a30c68479608038d99605e9f91a 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 := ldr.ResolveABIAlias(r.Sym()) - if target.IsLinux() { - ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) - } + rs := r.Sym() 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 := ldr.ResolveABIAlias(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,17 +685,22 @@ 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 := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() if target.IsAIX() { ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) } @@ -802,7 +899,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. @@ -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 @@ -909,7 +1074,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) @@ -1067,35 +1232,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 +1267,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: diff --git a/src/cmd/link/internal/riscv64/asm.go b/src/cmd/link/internal/riscv64/asm.go index 6eace617dc0a94fea3b1157b308a72c59a1bad8d..cb53a605d7175947c9491243467800c83d540ccd 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 := ldr.ResolveABIAlias(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,13 +222,10 @@ 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 { - 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) @@ -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 917324d92238915584c73452b2eadcc639e108a6..557e8932c98b44dbee83682acf8a12ed37e622c9 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", diff --git a/src/cmd/link/internal/sym/symbol.go b/src/cmd/link/internal/sym/symbol.go index 70cf36a87ee9bed9ef6cb080fed71d2e99c4ae8d..2f2c839006f11d4fbd7b328af63f2d2a8d8def82 100644 --- a/src/cmd/link/internal/sym/symbol.go +++ b/src/cmd/link/internal/sym/symbol.go @@ -6,11 +6,13 @@ package sym import ( "cmd/internal/obj" + "internal/buildcfg" ) const ( SymVerABI0 = 0 SymVerABIInternal = 1 + SymVerABICount = 2 // Number of internal ABIs SymVerStatic = 10 // Minimum version used by static (file-local) syms ) @@ -19,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 diff --git a/src/cmd/link/internal/sym/symkind.go b/src/cmd/link/internal/sym/symkind.go index c176d5e208cb447d1387e90c04ba610aa76bfd48..0a0741f84bf402439649e6058237a2a5243d26b2 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 @@ -118,33 +120,29 @@ const ( SDWARFRANGE SDWARFLOC SDWARFLINES - - // ABI aliases (these never appear in the output) - SABIALIAS ) // 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, - SABIALIAS, - 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 diff --git a/src/cmd/link/internal/sym/symkind_string.go b/src/cmd/link/internal/sym/symkind_string.go index 34cb314bd5b05b0ae36f90e8da88a13b7b4d913d..bf8eda713ec847a8de27a0af78f3eb1aca8b5fed 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 5bdfdbaee63e9bc42626d7057124dd18d108dd1c..01c500ed70e6dc3e0baed4176e4dab2073865ede 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()) diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 7230054bedd2fa3149e4990a2e7d61eafbad31ad..ad7658bb2577f0fb163b8854d63c47c26c470a7a 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 { @@ -545,14 +547,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") } @@ -567,6 +568,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 @@ -993,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) { diff --git a/src/cmd/nm/nm.go b/src/cmd/nm/nm.go index 457239921bc34ff185f144467b7762bec1383f21..178eeb27bea34715c4c7a0a5a9bad09a0b2dd563 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/nm/nm_cgo_test.go b/src/cmd/nm/nm_cgo_test.go index 1544be041a8174eee4b2849d354ecd0274f8cb76..0c826738ec9baede10fca9dc8876826946db11cb 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/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go index f231a7c6e0e2e5c084cb162c1b6c3540d4677b85..ff4316103083ac6d35f3d47b13c46f43863b849b 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) } } diff --git a/src/cmd/pack/pack_test.go b/src/cmd/pack/pack_test.go index 7842b562dc3c1406895292865f4c4e4c4d4c08e3..81e78f53e28d08d4fc461d93c8e1c9d57995f2bb 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 f46e934e0f3cf81d687799fd6d41bf621ef4d7f7..b269177650ae574ff382cd65c5ea3453b2b3dd97 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 @@ -72,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/annotations.go b/src/cmd/trace/annotations.go index 9b45457436bda9966ec698eea03b55718a468f24..1c0dad56d849e6af89f30f5cf405e0598d72f967 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 } diff --git a/src/cmd/trace/annotations_test.go b/src/cmd/trace/annotations_test.go index acd5693c7d5fea053190a80e9b7f174b21d60463..9f1c8e3b3b0e8e38c0ce93c53c732b81b7d1c1c2 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/main.go b/src/cmd/trace/main.go index f94586abf3da6cdcb40928d2ea09ccfc01fd5cae..a30db9a012ad176c779ac8ad3167f55fc58c687f 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() @@ -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 1d1fd2ea94737d3e95c0e700d120f134115330ee..b71dcd64110415369508a027f74f7b5c2e24a63b 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 ca10736c32030b4ce24fb2578c50028cfdca4035..0139639dae5c1e5f9d648d5818d00308467ab175 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/cmd/trace/trace_test.go b/src/cmd/trace/trace_test.go index 2b1a68d7f3d796ec7e454db3694caf1616783744..87fd3a3515c8f018906959644daf2dd9ef5c8054 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 8dc56a8c7be96c3fc93341b09c25eafd13ab875d..f35061ec63030506be56d1de0afe9b0df3d91611 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/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 24c48e649b8875ff0dd0f7fb753a4a8098456911..844c7a475d5174f803142f5d87a6449596d210bb 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 5ed8a1f9f1e3823c884a45c3bdb78055f86184dd..e920eeb2fa204331ec562b24e943e84a54a31df2 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/commands.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go index 4397e253e0d0c751fb36a610b1b57baa92bb5c86..c9edf10bb43787815aa1b58fa8f2b65bfefab1b7 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 b3f82f22c9d94a58515fac4852df49a773ede5ef..9fcdd459b271fa89499815d20e77257aeb35faa4 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 3967a12d45affbb2ec4c818da69f7fa881382130..6a1e64c600e3399724bf3302da521acb593fabf6 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 0000000000000000000000000000000000000000..c2cdfa455eeaf54e8063d7cfb1a0c5272ecdd727 --- /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/github.com/google/pprof/internal/driver/webhtml.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go index b8e8b50b94d63b9eb85ff381f7029c76523ce871..b9c73271b8c928783469546844e1b66b71144fd6 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 52dc68809c7765712d4fa7810fafc86c359df74d..0f3e8bf93c44fbd9ead281a2bf3385928a1f7c22 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 2638b2db2d9a95a5a74eb104a389127e59f1c97e..6447092d3d9978baeea75405fc441c0546d5c87e 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 @@ -284,10 +303,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 +323,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 4a86554880132d11fa44384b1c95bfc88326d343..e2fb00314ca0ab437b6362891093bb0929c112c1 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 54245e5f9ea6a0f2848f6a0b4a063a52bffd03e3..33d04c591d9beba025eb1911f0cbb25be7fd4e67 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/github.com/google/pprof/internal/report/source_html.go b/src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go index 17c9f6eb947c512a0a8f253cfa00f4b1eed94512..851693f1d0e6d717357d4c567b7108d7069f8ec0 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 ef3f94a63d7dd6cda1bea346c255a4d86380243a..2c01cae088fef3e867c2a8c37d19d60f8b277257 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 ccbe5b355988b2786d30d4b2ff3b8930a6345dbf..7b9178f1bb09e0b2ad985a40a4758585f716506a 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 c2667446df07b34461bdb8b5ee4f99d37931ae9c..9eec0aa3c83921792418b06ed6513d95ee2e6502 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 0000000000000000000000000000000000000000..140b631644250ab1caf8485679c0fdd3ca3a562a --- /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/arch/arm64/arm64asm/plan9x.go b/src/cmd/vendor/golang.org/x/arch/arm64/arm64asm/plan9x.go index 3aaf0b2a3030cc33352116b6c94f579c931128db..f4eef8c0a77edde18d186705974e7ff264d9a358 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/arch/ppc64/ppc64asm/gnu.go b/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/gnu.go index 225ef4fb88d2aecf00b2e41bd03c8e8df5d9920a..b4c9bf8df6dd9eec5e6ae412e543c9acd811603b 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 89b917320a314ce45ac5928600f04a6348fcb38c..88e8e1c747baff717c66ed67830e798b99777a97 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 a93bffd441607c31dd40a8cbbd83cc68a35558ea..59d8f97753f2563881056501b5ab950eda58248b 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/mod/modfile/rule.go b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go index 78f83fa7144f0318379ebb0c4797540959c7b511..ed2f31aa70e0e1d56540280cb1a1ecbc8a4e569e 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 "use": + 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.Use = append(f.Use, &Use{ + 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. @@ -956,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() } @@ -1165,6 +1290,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 +1307,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 +1325,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 +1411,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 +1448,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 +1479,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 0000000000000000000000000000000000000000..0c0e521525a9f6bbad4cce0ec2a680c3ad245b5e --- /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 + Use []*Use + Replace []*Replace + + Syntax *FileSyntax +} + +// 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 +} + +// 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 "use", "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.Use { + if r.Path != "" { + f.Use[w] = r + w++ + } + } + f.Use = f.Use[: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) AddUse(diskPath, modulePath string) error { + need := true + for _, d := range f.Use { + if d.Path == diskPath { + if need { + d.ModulePath = modulePath + f.Syntax.updateLine(d.Syntax, "use", AutoQuote(diskPath)) + need = false + } else { + d.Syntax.markRemoved() + *d = Use{} + } + } + } + + if need { + f.AddNewUse(diskPath, modulePath) + } + return nil +} + +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) SetUse(dirs []*Use) { + need := make(map[string]string) + for _, d := range dirs { + need[d.Path] = d.ModulePath + } + + for _, d := range f.Use { + if modulePath, ok := need[d.Path]; ok { + d.ModulePath = modulePath + } else { + d.Syntax.markRemoved() + *d = Use{} + } + } + + // TODO(#45713): Add module path to comment. + + for diskPath, modulePath := range need { + f.AddNewUse(diskPath, modulePath) + } + f.SortBlocks() +} + +func (f *WorkFile) DropUse(path string) error { + for _, d := range f.Use { + if d.Path == path { + d.Syntax.markRemoved() + *d = Use{} + } + } + 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/golang.org/x/mod/module/module.go b/src/cmd/vendor/golang.org/x/mod/module/module.go index ba97ac356e9cb34f73f6a756a9f65eedbdca25b0..355b5a456854ffacbed82fe1e0253bff003f7dd2 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. @@ -803,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. @@ -812,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 7be398f80d33e724ece45da019cb91132563c17b..a30a22bf20f1843be5015b457168fa4a6f26a27a 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/golang.org/x/mod/zip/zip.go b/src/cmd/vendor/golang.org/x/mod/zip/zip.go index 5b401ad4d8fb28fd4b19c076b0c1b06ddbae8567..ca0f7ad42f1819cf89908f04b10559110d102426 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,129 @@ 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. +// +// 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. +// +// 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. +// +// 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 = repoRoot + } else if err != nil { + err = &zipError{verb: "create zip from version control system", path: repoRoot, err: err} + } + }() + + var filesToCreate []File + + switch { + case isGitRepo(repoRoot): + files, err := filesInGitRepo(repoRoot, revision, subdir) + if err != nil { + return err + } + + filesToCreate = files + default: + 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{} + 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 +700,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/golang.org/x/sync/AUTHORS b/src/cmd/vendor/golang.org/x/sync/AUTHORS new file mode 100644 index 0000000000000000000000000000000000000000..15167cd746c560e5b3d3b233a169aa64d3e9101e --- /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 0000000000000000000000000000000000000000..1c4577e9680611383f46044d17fa343a96997c3c --- /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 0000000000000000000000000000000000000000..6a66aea5eafe0ca6a688840c47219556c552488e --- /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 0000000000000000000000000000000000000000..733099041f84fa1e58611ab2e11af51c1f26d1d2 --- /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 0000000000000000000000000000000000000000..30f632c577bd1aa41489c813ed1cd580b6f52d45 --- /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/golang.org/x/sys/plan9/pwd_go15_plan9.go b/src/cmd/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go index 87ae9d2a33e329acee47d6bb947d3a7c7d205288..c9b69937a0d0f5cdc99cbcef81c464dae49fc55d 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 c07c798bc57dd81ca981327afd3fc4859efb24c0..98bf56b7322c94934656abc0ef6d5872183fa47a 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 42edd93ef962d289a747b99166752f7079c65776..62377d2ff96ca750802f638d4c17b2747e59958e 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 c89cf8fc0d712e311fb93ac559aa36fb7774f910..f8da30876dbfdf96000dcbe099039aebc67b19cf 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 4f7f9ad7c86b2b8af853241453d19d53aba50be2..55fa8d025ecaac39bae0dc497e05a45db132d8ea 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 e7363a2f54d5b1c851521476ecaff3dcd6929d72..602473cba37402b23fafbccf69330276023b4d0a 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 6819bc2094d399b753b1d5e2bca763592e57ef16..3f40b9bd743e3671c921b334cb1350d00b3f83ad 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 418abbbfc75b9ad01c44ad994c270680ec2c6d99..0e6a96aa4fa19bf54d887fe5740d362bf6f41e7a 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 3e8a1a58cac83947a963d53ce70a82e18a5520a1..244c501b77ba7517cf5665c82964f5144f0bbca8 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 579d2d73557fb5a9c78c542af11c81a9c67f3faf..7d3c060e12213c48b017dfd2846fb9b1cf413d31 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 @@ -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/asm_bsd_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_bsd_386.s index 7f29275fa000d810cea70b59c9c9fe7f24ea115f..e0fcd9b3deec595ed3b327d134de1913aa0242ae 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 98ebfad9d512f1dcd4ce6ce00bdfa99e49bb3663..d702d4adc77d770ceb4f09f22c616a5878c0aa4b 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 0000000000000000000000000000000000000000..934af313c32315263a07b02b761cca2c0c403195 --- /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 48773f730ac63ccc09db548c59131b7c658f5317..1dadead21e6d6a1ea5b7edebdbdcdec773dec1c6 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/mkall.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkall.sh index 396aadf86de729ea230b7bc2d1f3c675c80a3fbe..ee73623489b07f54e90c2f5622f89d0c97448a49 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 007358af8fc18789e1384d52c1657a10eba5c089..4945739ea0a99b1002f24876eea98353b17a3b13 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=' @@ -217,8 +221,6 @@ struct ltchars { #include #include #include -#include -#include #include #include #include @@ -231,14 +233,17 @@ struct ltchars { #include #include #include +#include #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -258,6 +263,7 @@ struct ltchars { #include #include +#include #include #if defined(__sparc__) @@ -465,7 +471,6 @@ ccflags="$@" $2 !~ /^EQUIV_/ && $2 !~ /^EXPR_/ && $2 !~ /^EVIOC/ && - $2 !~ /^EV_/ && $2 ~ /^E[A-Z0-9_]+$/ || $2 ~ /^B[0-9_]+$/ || $2 ~ /^(OLD|NEW)DEV$/ || @@ -497,10 +502,14 @@ 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)_/ || - $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)/ || @@ -512,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)_/ || @@ -558,6 +567,7 @@ ccflags="$@" $2 ~ /^KEYCTL_/ || $2 ~ /^PERF_/ || $2 ~ /^SECCOMP_MODE_/ || + $2 ~ /^SEEK_/ || $2 ~ /^SPLICE_/ || $2 ~ /^SYNC_FILE_RANGE_/ || $2 !~ /^AUDIT_RECORD_MAGIC/ && @@ -593,6 +603,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/sockcmsg_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/sockcmsg_linux.go index 8bf45705947c7b009ecb73b125a32aa26458d951..5f63147e06c184cb02a89c3e74eff166c4cc80ee 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 d8efb715ff1dc6fbe44c707228b8befc1eeebc31..6192750ce31b31d6f930252c0fe65d573d97d2cd 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 95ac3946b5cc1ca30b1c16fbd1aab8aeaedc6541..0ce45232611f9870eded06e7b8b95afb4b54b736 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 9945e5f9655ad0318ce8f14c80fb2a8a4e617a95..8826f41435e92bcde35f597426c87482e1f80996 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" @@ -47,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: @@ -57,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 } @@ -398,8 +430,62 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) { return x, err } +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 + } + + // 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) +//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 */ @@ -557,10 +643,6 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, 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 8c535768352743581bf0de05566e7a84c8480de6..8d5f294c425047719923573422cc5e4f6c383b98 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 2dd7c8e34a940fd17e902c321e8c898b94f86d4b..4bc5baf77d9630d1bfe17d37e6052e325675a3d3 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,11 +72,22 @@ 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) +func InotifyInit() (fd int, err error) { + return InotifyInit1(0) +} -// 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. +//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. +// +// 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) @@ -102,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) { @@ -111,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) { @@ -161,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 { @@ -349,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 } @@ -364,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 } @@ -415,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 } @@ -832,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 } @@ -851,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 } @@ -869,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 } @@ -904,6 +915,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) } @@ -927,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: @@ -968,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 } @@ -995,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)) @@ -1005,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 } @@ -1144,6 +1185,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 } @@ -1151,11 +1223,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 } @@ -1277,6 +1345,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. @@ -1700,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)) @@ -1731,11 +1816,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) @@ -1788,7 +1869,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) @@ -2223,6 +2304,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 */ @@ -2304,10 +2393,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 7b52e5d8a40a9275989a128ee4baa60be0cffde6..5f757e8aa770632541210c36ba7dd9e1f600924a 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 @@ -105,7 +76,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 +104,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,11 +349,6 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.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) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) } 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 28b76411522f9a3f5d18ee91989f60b32c942ae4..4299125aa7cca0af1a6a33b2e4596a2b6008ec58 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 } @@ -172,13 +133,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.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) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags 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 68877728ec60c92d00388fd1297ee74643bf5303..79edeb9cb14a5723c613901a13744acdf0a5daa2 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 @@ -184,7 +151,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 +179,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,13 +223,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.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) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) } //sys armSyncFileRange(fd int, flags int, off int64, n int64) (err error) = SYS_ARM_SYNC_FILE_RANGE 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 7ed7034761c51585c413aebe6ca9e76e3aaa15ac..862890de29bf224582a6c89fa46fd67f4942e238 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,33 +138,9 @@ 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) + err := Prlimit(0, resource, nil, rlim) if err != ENOSYS { return err } @@ -180,7 +149,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,31 +176,15 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } -// 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 06dec06fa194b43d23a23c20a67cb48e86b634c5..8932e34ad2ad7ddc811c2eee83624a782fd5d659 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 } @@ -217,15 +191,6 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.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) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } 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 8f0d0a5b592a3e723b982f7902b27e8aa5e5655e..7821c25d9f778fce7fc6452bef05193ed6ecd38d 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) { @@ -157,7 +131,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 +159,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,11 +203,6 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.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) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) } 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 7e65e088d29b03163701061f5652ffcfc30b1592..c5053a0f03fdc5414803a2cfc473b313bc379548 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 @@ -13,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 @@ -24,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) @@ -143,7 +139,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 +167,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,39 +211,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.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) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) } //sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 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 0b1f0d6da5799b66db6462c16469059c634b9f7b..25786c4216b514abcda12d9d46d3040324da3b06 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) @@ -100,39 +97,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.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) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } //sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 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 ce9bcd31717ab2de5424f195d3a922dbdb80e0f4..6f9f710414f0672420d101ee43f2e3dd43847828 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 } @@ -188,8 +157,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } func Pause() error { @@ -197,18 +166,6 @@ func Pause() error { 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) } @@ -225,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 a1e45694b441b4b11c7816aff0c5ca5ea6ff3724..6aa59cb270db00b3c7a79cecaab6e37c47c87f56 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 } @@ -129,6 +102,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) { @@ -320,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 49055a3cf51bfa17e818ba0f0075894928cc11ba..bbe8d174f8c12ebbe0eb87a77b70ed73fcc49336 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) @@ -116,37 +114,6 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.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) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } 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 77fcde7c180a282a3295d9ba61d753fc95dca12d..8b88ac213333dcdf1805e2bf6b7a47732fe3cc3c 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" ) @@ -89,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 } @@ -104,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 } @@ -414,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: @@ -425,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 @@ -744,3 +739,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 a7618ceb55e360d9c94a5ca7ee02b15c7bfdfc38..cf296a2433a93ea811d939654fe90eb861bb5603 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/syscall_zos_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go index 1ffd8bfcfb90b1319ea64a798086c7d87964f9d8..5fb76a146843c54227a6954a0aeb2116de0c7982 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/sysvshm_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_linux.go new file mode 100644 index 0000000000000000000000000000000000000000..2c3a4437f0f084134fb018309dc82d939d1f45f8 --- /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 0000000000000000000000000000000000000000..0bb4c8de557b5e67a142eaa5dbd4945f58709d44 --- /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 0000000000000000000000000000000000000000..71bddefdb87db4d1dfb4e3c0808c932af7347d26 --- /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 991996b60911e4e7c9e894d8b6b7815d404c1fd7..476a1c7e77c52814aced93d4bf22f50bd36431d3 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,1550 +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_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 - 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 e644eaf5e757e0f7856c722151b76acb03783071..e36f5178d60089f88323a37a6e73d3e26593daf9 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,1550 +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_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 - 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_freebsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go index 9c7c5e1654643dd289cc2b78e739fd3d8c67b0b7..440900112cd42098c79710f8a691ffb20e35e3f1 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 b265abb25f89036eb36292ed74baf83f47e3d8c5..64520d31226b94632d384575d93f8ed4e05ad4bd 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 3df99f285f14edb9366a758b18f5e7317d851ca3..99e9a0e06e95f785edf015ae06ebea1d5e313a4c 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 218d39906da6c4d51726629d904876a4bac747be..4c837711493ff1bc346f749e9ea163a860abb16e 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 47572aaa690f28311c9014e402f98ee6296f6b14..d175aae896cbc8d7f7a4402225dfd65446890696 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 @@ -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 @@ -228,7 +229,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 @@ -468,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 @@ -475,6 +481,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 +502,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 @@ -710,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 @@ -745,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 @@ -783,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 @@ -805,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 @@ -815,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 @@ -981,12 +1009,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 +1279,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 @@ -1332,6 +1355,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 @@ -1382,6 +1419,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 @@ -1406,6 +1445,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 @@ -1433,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 @@ -1494,7 +1549,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 +1617,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 +1687,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 +1808,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 +1879,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 +1979,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 @@ -1880,6 +2031,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 @@ -1918,6 +2070,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 +2112,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 +2231,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 +2262,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 +2271,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 +2285,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 +2295,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 +2324,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 +2355,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 @@ -2298,12 +2467,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 @@ -2440,6 +2612,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 e91a1a95792b2eeb40672794529fbf96d6320746..3ca40ca7f02abf2d9bec49693f67c8b24f7a4eed 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 @@ -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 @@ -273,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 @@ -289,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_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index a9cbac64439e3ae6836aaed2b09d0aec99c43877..ead332091afded9131afde203606d5cc37faceb7 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 @@ -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 @@ -274,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 @@ -290,6 +311,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 d74f3c15a1d8366c7a088c9665d83bb31db4696e..39bdc9455899a85dba94754071dc4502d3be6d56 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 @@ -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 @@ -280,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 @@ -296,6 +317,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 e1538995b49d1446ee1f91b8d3da3ac87eed93c0..9aec987db1ce6c7da7e2a71df03a1c9571df1d52 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 @@ -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 @@ -270,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 @@ -286,6 +307,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 5e8e71ff863547eac670ea1dc62ad9e8f5d5ba11..a8bba9491e8260f079dceca2057c7d25ef03ecfe 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 @@ -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 @@ -273,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 @@ -289,6 +310,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 e670ee148140522bbbdf03836a1c143d982ff2c5..ee9e7e2020eaa46760dab83009a2ca705a33b1ad 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 @@ -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 @@ -273,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 @@ -289,6 +310,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 dd11eacb81e0b5b0e09dbe818f7bd37445e0dcd6..ba4b288a3c0681990e7a7b6671b4b75c1425d1bd 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 @@ -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 @@ -273,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 @@ -289,6 +310,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 a0a5b22ae93a734c1a13f00b34b45f32d475a84f..bc93afc36751391dce6e3469fc2b76171d74ed32 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 @@ -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 @@ -273,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 @@ -289,6 +310,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 d9530e5fbfbc93b654d1d991c5da7aa14d0a4cc0..9295e69478529ab98e22e41cc0f2f1d652cbc400 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 @@ -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 @@ -328,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 @@ -344,6 +365,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 e60102f6a92add70bc84f17a87be1305e5e5d372..1fa081c9a6733951d8a1da37766e05c4f7a951c7 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 @@ -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 @@ -332,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 @@ -348,6 +369,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 838ff4ea6d069d1ad6733e48883f26bcdc34b097..74b321149463dd6cade944cc03474781bf1795e1 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 @@ -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 @@ -332,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 @@ -348,6 +369,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 7cc98f09c3ed1e24dc6ffa4732fe1f6eb2dae89d..c91c8ac5b01dcaa956f297dc2e38bf541ea58781 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 @@ -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 @@ -261,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 @@ -277,6 +298,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 6d30e6fd846ae378e1dd4c94ce3c78876947cc9e..b66bf22289490cff36748ee020e0b8d66c035f9e 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 @@ -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 @@ -336,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 @@ -352,6 +373,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 d5e2dc94faa4d057530366c3a81595f77964ffb7..f7fb149b0c98db82667f91b310f96e30b82ffa16 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 @@ -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 @@ -327,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 @@ -343,6 +364,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 593cc0feffa01b490e6445699a4493da13f0d04c..6d56edc05ac3cdb8181e5a56d95486b71f1e7fcf 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 a4e4c22314e0a635d4d5d4538aaaeb24d9e83428..aef6c085609ab445c491cb095e9f253b4ea24d33 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_aix_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go index 91a23cc72874d9e7f7a135dffe0ec8abea80a055..85e0cc386678fa7e76ee0b970f06c85d2beaf486 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 33c2609b8b406eecd4228b00c24ccfb5c1389a2f..f1d4a73b089882115c9712aba37dec0725bb61f6 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 8b737fa971e8535fb4b95759df8ce3cc2ae6a24d..2caa5adf95099d4b3e975e0977a43a642af98ab4 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 3c260917ed59067fbbe14ab74a6b13a51276a894..944a714b1ad45191af64f2c1f14305bc5e3b49b8 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/zsyscall_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index d4efe8d457aca1e22cb810498a40af10c34dcce3..0ae0ed4cb8af7d2e6a6afa387efd4df0354dd3a5 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 bc169c2ab9ca8d3526b1970fba3a97f81cf07f24..eac6ca806f4d5c65ff3c9f564a6f3c7de73063d7 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 f2ee2bd33b93f2b31b65ea8f5d0263884f690d8d..cf71be3edb3b34c33cbadcb9b883a158b7cb795d 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 33e19776db4e2bd22f4311ca68090a51ce3a0ad4..4ebcf217585403cd63c424c65b67b83379e51dc2 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 7305cc915b7a77e75b2b88a24de7d057eb312313..93edda4c49394a3d74bcd3b22b6c96bf35d8e3c9 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 @@ -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) @@ -100,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) @@ -389,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) @@ -1201,7 +1236,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) @@ -1935,8 +1970,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 e37096e4deccb9e6dbde1e97c74d31cb5ff223dd..ff90c81e7300eb19641ea5c9b7eb273fde949121 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 9919d8486d41b95ba98830c3b4ce1feb35f7fec4..fa7d3dbe4e94d5ec4912d851cb2acee633c52473 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 076754d48d1d8fa194ce1ad0c41d45b1e79f45ad..654f91530f6950860dfdbbc443cf0fa4111c38ea 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 4703cf3c3385b8d58531e908eaa2da0c5c98e6af..6d1552885314b402c1462928dfa6b2de62eb2bb0 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 a134f9a4d2e06bd3416b247cb9c3a0138204840a..1e20d72df21ec3a4e57d272f9c57ace9ee495c29 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 b1fff2d946a225f91ffeacebfcebe78f6d34559a..82b5e2d9eda459f5f669f442b2cd948b41bd0f9b 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 d13d6da01ef899f932f2cd1f4d33de6a3e124e3a..a0440c1d43be3b9757038590a819bc9dfa6f85f4 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 927cf1a00f0d72b6a8b6b2fc7c18c8a6bf7a1f9e..5864b9ca64903564e0122568d12beff0760b19e8 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 da8ec0396665bdae6808bac03e444691d9d0b950..beeb49e34217a8623d54fb97c96ad0ceaee09c4b 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 083f493bb6f473f1e8f7df4ae0d3f328c734d94c..53139b82c7be1a49e803ab9ff1697d099316c04d 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 bb347407d3d476cb80148854ae30679c49aed5ea..202add37d10a544127ce0a5c6387204207e0a5a8 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 8edc517e1e65c0ea38b95acdfb38f8eee28390bc..2ab268c3435930fc51b6e5efe36b958845552ffe 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/zsyscall_solaris_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index 4e18d5c99fd361fb7ffa828f04b22b390a14626f..b5f926cee2a995e9e109ac2ccfc5c87ab7d87317 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 fbc59b7fdd25a2a88ccee4d1dd1305599bd81a93..31847d2305faedc8cb99c523faa02e3e698e9c2d 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,10 @@ 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 + 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 04d16d771ef78caf3cc2d2f1408a7d95e769f218..3503cbbde385d04caeeea52a183f8806c4a153ff 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,364 @@ 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 + 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 3b1c105137368fa3f450433d1abf6d198a12aab6..5ecd24bf683c2bbaa45c5be05ad91b2d74d3e12c 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 @@ -403,4 +404,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_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 3198adcf77a12293da9d3f7c36953e9b89f42df1..7e5c94cc7feac23bd98b15ff66bc6a253feabef3 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,309 @@ 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 + 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 c877ec6e682141bb281bb7ca70da999c07633960..e1e2a2bf59ed9aecb56e8f76ebd50d815161eb4a 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,9 @@ 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 + 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 b5f29037299aced96b2934dddd1e1dabd5cb6fa0..7651915a3adc2c3fa707a7f7edd910fee4474a4f 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,356 @@ 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 + 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 46077689ab1f02b2052cd0bdc7e90d82e3f3d784..a26a2c050bcaab953c3ea28ec42269d27ec38ea4 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,356 @@ 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 + 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 80e6696b39dbedf1960d311b56789e45e7ee67ef..fda9a6a991310e9a759e1b69f7bafa120f8a6aeb 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,9 @@ 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 + 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 b9d697ffb1c019575b5471c80d4b122f6cfafd9a..e8496150d41022814a03ba147ace0b83df29808b 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,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_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 08edc54d35de252cea6e9d3e83f8ddb94ae38a8d..5ee0678a360c8b3af40a43e3b97dccf418609ba4 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,405 @@ 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 + 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 33b33b08342dc7b36788b424af71de25fdf07f66..29c0f9a39eadf62198b74f545aad7d529c99b3fc 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,405 @@ 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 + 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 66c8a8e09e1a0a90a87d33558556449858fde0bd..5c9a9a3b61c9f66eea7ab3bb475384e940829edc 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,307 @@ 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 + 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 aea5760cea26445a7d11806db1b893b4739906b6..913f50f98b9098c8ea4cf8cb4f61f403f5ee9f51 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,370 @@ 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 + 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 488ca848d17616111630e616e7f5c78750278a46..0de03a7227c3a49749f68b557657434cf4cc6261 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,384 @@ 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 + 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 2673e6c5909c338d0ece15d00768482257afd2d4..885842c0eb402751bd9eff281ca71516471aa527 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 @@ -535,3 +626,143 @@ 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]byte + Xsize int32 + Xrssize int16 + Xccount int16 + Xswrss int16 + Flag int32 + Login [12]byte + 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]byte + 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 +} + +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 1465cbcffe476d872135974ccd6f02be1d32cdcb..b23c02337db3d619930afe899c28e2df7855d697 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 @@ -535,3 +626,143 @@ 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]byte + Xsize int32 + Xrssize int16 + Xccount int16 + Xswrss int16 + Flag int32 + Login [12]byte + 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]byte + 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 +} + +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_dragonfly_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go index 1d049d7a12247c1fd80bf01b707f00f75f63784a..d0ba8e9b86a3483567cc3bcbe01e4a83612d4005 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 c51bc88ffdfcbf7652d3a73c506a037bd583fda1..4eec078e52490863cf2ce9f794afffcd71a453e6 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 @@ -672,9 +674,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 395b69187113e06d10af9d700f1cf8cf012b209a..7622904a532f45f8ef0eb7d37c4dcad01fee1310 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 @@ -675,9 +677,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 d3f9d2541b5ce384f7ebabb8b5f39e0cd910bcd7..19223ce8ecf906522e85e2c5f466f6d041897436 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 @@ -656,9 +658,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 434d6e8e83c4766f6c5dac517a7f473802087d1f..8e3e33f6790587e60208a6cf5f804f8005820320 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 @@ -653,9 +655,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_illumos_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go index 236f37ef6f7ec7f5b3f587321dc2445e05c9bed1..4c485261d6dfd9e6822090db517e29f9cad07318 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 087323591e61d8cbfc35732e935e4707e20f5237..37b521436bc2b7315880a5daf0f1fee19134f557 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 @@ -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 ) @@ -719,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 @@ -993,7 +1019,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 +1791,8 @@ const ( NFPROTO_NUMPROTO = 0xd ) +const SO_ORIGINAL_DST = 0x50 + type Nfgenmsg struct { Nfgen_family uint8 Version uint8 @@ -2330,8 +2358,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 +2935,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 +3158,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 @@ -3238,7 +3266,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 @@ -3426,7 +3455,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 +3486,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 @@ -3591,7 +3620,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 @@ -3742,3 +3773,198 @@ 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 +) + +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 +) + +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 4d4d283de5b1e2afb03885639c0f7b97b0f9966a..bea2549455ea30a530b90bf84e002ecce7e29f39 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 @@ -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 ( @@ -618,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 8a2eed5ec4e37a6e172f915f736e155560536367..b8c8f2894335a888f1788bf05a9db046ef25101b 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 @@ -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 ( @@ -636,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 94b34add64309cae4b36eebe444cd756f4650dcc..4db44301632bc5088638ca0eb0b5daadeb67894b 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 @@ -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 ( @@ -613,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 2143de4d599f5ae9f2e5eca3851223fd51037e41..3ebcad8a88739f5cb4c691ccaa42259585224417 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 @@ -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 ( @@ -615,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 a40216eee60a07907e80e6cd674574eef6f98284..3eb33e48ab539f4e09f97381ebf34ca175bfdca5 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 @@ -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 ( @@ -619,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 e834b069fd5c1e9f847a4e091fd8f8763e782866..79a94467252f19755119487dd1663256ada63a8f 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 @@ -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 ( @@ -618,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 e31083b0489666d06f4709acdb1ede42d2a85dc8..8f4b107cad36bd616a90d280c6c4c02ca4c7e892 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 @@ -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 ( @@ -618,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 42811f7fb5595815f62dcce8be5921816ae5a63f..e4eb2179811f3064e4b3b0745b89c0d68537de51 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 @@ -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 ( @@ -619,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 af7a72017e9fb1c7614483c09c365fe57fadb12c..d5b21f0f7da5556f1736270ff17c71cfb2a000e4 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 @@ -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 ( @@ -625,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 2a3afbaef9fcdb2de0cab51ce71e80a41dd06998..5188d142b9f526e1275b5ac0641ce1f5874468e2 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 @@ -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 ( @@ -625,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 c0de30a658a4ab1f3fa9cd56e8691d5cc2baea0d..de4dd4c736e8b887257cb6e5eba99891c961fb78 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 @@ -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 ( @@ -625,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 74faf2e91fdc579c3f80343827bc8948f5a4d17b..dccbf9b0604051939bca790018bce7fda4e61c91 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 @@ -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 ( @@ -643,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 9a8f0c2c6a3d99879954a962706c5a25bf2632da..6358806106f088687d47f8b1517d5322408e6e9d 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 @@ -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 ( @@ -639,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 72cdda75bde94d60fe92e3fed75432c5ea81b39f..765edc13ff25673166a60940de0f60df461a0c1c 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 @@ -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 ( @@ -620,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/unix/ztypes_netbsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go index b10e73abf95c0754de5b63f5175aa52a57673bed..2fd2060e617a4797a506475d1a24719c785b6dde 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 28ed6d55ae3ac04e1f6d1e369c454962f63112f7..6a5a1a8ae5568680e7e086dc04420128621350b1 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 4ba196ebe563fb23d13e82ab02b54b1e5ca6356b..84cc8d01e6566ec5eb4f4501fb000f15fcc203a5 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 dd642bd9c874dd7e357fcb3c20db93224489448c..c844e7096ff5a58db6ce4c88855e1e3862cb2548 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 1fdb0e5fa5f90b749ca6994b5f8c6c5c2cc14ec9..baf5fe650444612124aa6d4fed9d33bcbf4b7770 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 { @@ -562,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 e2fc93c7c06966ac8e474be7ae0c05ab8c3fb54d..e21ae8ecfa6f4fadc86458afd9613b6064d5af14 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 { @@ -562,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 8d34b5a2fc065eda8ec88c6079f9c7031560dfb3..f190651cd96465f067437ffe276d0e3ed5816301 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 { @@ -563,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 ea8f1a0d9ba2d0bd4712859b188474d0081f8b26..84747c582cfce6c72f1ef8021cbffecaae95e6f6 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 { @@ -556,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 ec6e8bc3f13560564d1897b62d1230655bc89e7c..ac5c8b6370b1f77819c0d86e7ac5d2a814a0b34e 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 { @@ -556,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_solaris_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go index 85effef9c199e6b90c275d5da1829a6c91260787..ad4aad27968699379e0961876f91342d35d2b1d8 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/aliases.go b/src/cmd/vendor/golang.org/x/sys/windows/aliases.go index af3af60db97073da58b9cd3bbc219095aed8b698..a20ebea63312cb6cffdfc55c9f762946d1b1dae5 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 40af946e162f94306b65d77df160cdcd2b32ed72..2cd60645ee7d32bb9e428a4e0a0cd2d90214ca64 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/exec_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/exec_windows.go index 9eb1fb633a46f101b4454dc2c45475359fe7f875..7a11e83b7ec10206ebaf5b547690db3cfeb1de90 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/memory_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/memory_windows.go index 1adb60739a34b9b22284602d4117b8b0882824b7..6dc0920a84da2ab53810713043af3254cac6dc55 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/mksyscall.go b/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go index 328e3b2ace2d3c4f0ad0c58328e066d03b46a8fc..8563f79c57f89551a6f66fe1c18339cf6b31423a 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go @@ -2,8 +2,9 @@ // 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 -//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/race.go b/src/cmd/vendor/golang.org/x/sys/windows/race.go index a74e3e24b557e9d99cb6643e0a274e14ba7654ba..9196b089ca14c16da722f22a12b47c9d5aa768b2 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 e44a3cbf67994455be845fcb87fde02f01787c55..7bae4817a06c6b75368cf82b79385f4259e2c5d5 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/security_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go index 111c10d3a7f6033bd5b8cbe94f085c33a4b31917..d414ef13bef04e1ae1a992502076851f0515a0d2 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/service.go b/src/cmd/vendor/golang.org/x/sys/windows/service.go index b269850d0666eaa46943dde061d76a7b7fe7130d..f8deca8397ae68b0bd5c884192eb80ee1d3eb1d7 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/setupapi_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/setupapi_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..14027da3f3f117cc8b545ec62c131094b35ddf48 --- /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 1681810e04888ba5e1cdac3b5a51ab44eb68fb8e..0000000000000000000000000000000000000000 --- 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/str.go b/src/cmd/vendor/golang.org/x/sys/windows/str.go index 917cc2aae4e1b4163353fbdef21f591169977421..4fc01434e4a2a28709808ebf3fe9016f5e42c7f0 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 6122f557a097a508b31fa34ff100db0d89337140..72074d582f10c4d0237eb15223f6a819aef2ca82 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 bb6aaf89e47c6a40ffa465f68dc88168afe5431e..200b62a00320dc230a05e22fef70ed34731cd0f0 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 @@ -247,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 @@ -273,6 +275,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 @@ -316,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) @@ -395,8 +404,18 @@ 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 +//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 @@ -407,11 +426,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 @@ -872,9 +896,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 } @@ -894,9 +916,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 } @@ -969,9 +989,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: @@ -980,9 +998,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 23fe18ecef2123da402d09a306def62d35d9f999..73087bf5e56dc9f09e7cda48026e85d98b81f594 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 @@ -144,6 +156,8 @@ const ( MAX_PATH = 260 MAX_LONG_PATH = 32768 + MAX_MODULE_NAME32 = 255 + MAX_COMPUTERNAME_LENGTH = 15 TIME_ZONE_ID_UNKNOWN = 0 @@ -242,6 +256,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 @@ -680,7 +702,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 +931,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 { @@ -949,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 @@ -1780,7 +1818,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 @@ -2299,6 +2383,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 @@ -2489,6 +2579,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 @@ -2605,6 +2749,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 @@ -2699,6 +3040,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 @@ -2772,3 +3129,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 559bc845c99cdaa078b0d25125a772218fe0e846..1055d47ed336f1cc7b2beb1b7e38dd11a5b80506 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,13 +49,19 @@ 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") + modversion = NewLazySystemDLL("version.dll") modwintrust = NewLazySystemDLL("wintrust.dll") 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") @@ -69,6 +76,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") @@ -113,6 +121,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") @@ -123,6 +132,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") @@ -195,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") @@ -284,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") @@ -302,6 +315,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") @@ -344,11 +358,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") @@ -358,8 +377,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") @@ -375,11 +399,44 @@ 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") 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") @@ -390,6 +447,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") @@ -424,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 { @@ -553,6 +637,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) @@ -942,6 +1038,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 { @@ -1031,6 +1139,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 { @@ -1660,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 { @@ -2443,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 { @@ -2617,6 +2759,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 { @@ -2971,6 +3121,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 { @@ -2979,6 +3153,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 { @@ -3021,6 +3201,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 { @@ -3090,6 +3278,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 { @@ -3098,6 +3302,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 { @@ -3106,6 +3324,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 { @@ -3205,6 +3429,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 { @@ -3217,6 +3457,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 { @@ -3254,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)) @@ -3339,6 +3830,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 0000000000000000000000000000000000000000..3f8b14b64e83f940ab7b05e8c542fd821b376d3f --- /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 1f6a38fad2abec870a5798073c1dd20f8c4d41a3..d5927088082b208507dbe71863dca036530fdae5 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/golang.org/x/tools/cover/profile.go b/src/cmd/vendor/golang.org/x/tools/cover/profile.go index 57195774cea1541a7a8c145dd15179eb4ee606b9..47a9a541164b23b90bb09e03d4f7a7aab721a6a3 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/internal/facts/imports.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go index 34740f48e04ca1a51a639f3f3c395ddf07251dce..ade0cc6fab407b54ba4af8875de0c3dc3ba34a28 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/asmdecl/asmdecl.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go index eb0016b18f15356465370b9398516059e0b8e79c..7b82d0b6ddb5a5f3ceaa1501ef7b92fb128066f6 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/composite/composite.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go index 4c3ac6647f6acb26810af1d690d2c5712d37d544..d3670aca97a335d5f2adb58c0f936dab79acf7e1 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,61 @@ func run(pass *analysis.Pass) (interface{}, error) { // skip whitelisted types return } - under := typ.Underlying() - for { - ptr, ok := under.(*types.Pointer) - if !ok { - break + var structuralTypes []types.Type + switch typ := typ.(type) { + case *typeparams.TypeParam: + terms, err := typeparams.StructuralTerms(typ) + if err != nil { + return // invalid type } - 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 + for _, term := range terms { + structuralTypes = append(structuralTypes, term.Type()) + } + default: + structuralTypes = append(structuralTypes, typ) } + for _, typ := range structuralTypes { + under := deref(typ.Underlying()) + if _, ok := under.(*types.Struct); !ok { + // skip non-struct composite literals + continue + } + if isLocalType(pass, typ) { + // 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 +133,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/copylock/copylock.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go index c4ebf785710f9431502a85e0f06ab1af2f7a6562..350dc4e0fece53aabcbbdad48e7195a64860233c 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 51600ffc7eb63be7ebbbe4bf81cec7242d5797af..73746d6f04dca4ce8248ea62e1b293064549607b 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 cd42c9897f2d4bfe30999296e22ae0b0936b4f40..850f6f8faed38f56dc453dff8a20ffaf91749204 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 822820f06e9bef9e6872cf713f1d6690f0a93e5f..dee37d78ae0ed1dd2b2fa4a9e1c94806df40a763 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() { @@ -452,8 +453,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 } @@ -490,7 +498,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 @@ -513,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) @@ -555,7 +568,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 +576,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 +590,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 +602,9 @@ 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, KindPrintf: + pass.Reportf(call.Pos(), "%s does not support error-wrapping directive %%w", state.name) return } if anyW { @@ -621,7 +635,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")) } } @@ -833,8 +847,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) } @@ -870,8 +885,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 } } @@ -888,12 +907,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{'#'}) { @@ -949,7 +972,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,40 +1067,39 @@ 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])) } } } } 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 { - 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]) } } } 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") { - pass.ReportRangef(call, "%s arg list ends with redundant newline", fn.Name()) + if s, ok := stringConstantExpr(pass, arg); ok { + if strings.HasSuffix(s, "\n") { + 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/analysis/passes/printf/types.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go index 6a5fae44f469f30c81939ca951e8d8980ea6d775..270e917c8095f3ea440ebd20e72d1ac5217d9c53 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,65 +66,122 @@ 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 } + 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 *types.Struct: // see below @@ -118,19 +190,31 @@ func matchArgTypeInternal(pass *analysis.Pass, t printfArgType, typ types.Type, 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 +226,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 +240,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 +274,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 +309,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 1f3df07ccd1fabea0ada98583ba268d13fb90843..e968f27b4033e59fb0446e8982de13c04ee17033 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,14 @@ import ( "go/ast" "go/constant" "go/token" + "go/types" + "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 +96,36 @@ 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 { + 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 _, t := range structuralTypes { + size := 8 * pass.TypesSizes.Sizeof(t) + 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/stdmethods/stdmethods.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go index 64a28ac0b976265431acd4e2c8d0fa98a828b764..cc9497179da490f2051687b9ce0b3e9c73e44b39 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/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 7a005901e843b3e1b99f9dff8c8dc93dcc47d0d8..e41de809de112c6411d3b00fd9503c9c0601bc0b 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,62 +101,119 @@ 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() + ttypes, err := structuralTypes(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 _, tt := range ttypes { + u, _ := tt.Underlying().(*types.Basic) + if u != nil && u.Kind() == types.String { + T0 = tt + 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) + vtypes, err := structuralTypes(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 _, 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 = vt + 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 _, t := range vtypes { + if !types.ConvertibleTo(t, 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) }) 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/go/analysis/passes/testinggoroutine/testinggoroutine.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go index d2b9a5640d934817249c23bf22f16ffcfc488d63..3d4bd49085281daf0a2d727612b241b9c8a465d0 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. @@ -119,11 +120,47 @@ 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 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 + } + 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 +184,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/go/analysis/passes/tests/tests.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go index 8232276186aeab15f8bbecb5377ed9e20c220715..2c87882496694ae3af9c505aa3d103326fcd5e21 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,12 +8,15 @@ package tests import ( "go/ast" + "go/token" "go/types" + "regexp" "strings" "unicode" "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 @@ -42,10 +45,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 +111,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) @@ -116,6 +171,9 @@ func checkExample(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. @@ -182,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/unmarshal/unmarshal.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal/unmarshal.go index 92b37caff9f113c7f2122dd004f9e324ec065de7..5129048a07662eab3716b6ab4b7f242e79a3f626 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/analysis/passes/unusedresult/unusedresult.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go index bececee7e9399173937c73d1ed77a6ee20290bda..fd94508f883a13ef683ad453e32f08eb76b0a134 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/analysis/unitchecker/unitchecker.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go index 5424489f8b31a46e9779262aba0c1a545c877576..b539866ddd4a6e07687d44c7024d65721931e882 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/go/ast/astutil/enclosing.go b/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go index 6b7052b892ca07ba23a1eddd35645d50992dc42c..a5c6d6d4fa06cbc49cb7be1aea89cea6d5f821cb 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 cf72ea990bda2c11ae7a87865c352b7fc9029730..6d9ca23e2b02c4fd99e0136df1c998d4597e7eaa 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, @@ -251,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) 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 b6b00cf2e1e377ee30c870d0532e73c9d3716a89..11f4fc369a0835ba63b237f6cba4f590fdf353bc 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 cffd7acbee71b88f064022bcb7e617aa1024b5a7..7e96fc234e5af5514a5951b2b83093138a19d613 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 OT operators are encoded as [AFMO]; +// - 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/go/types/typeutil/callee.go b/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/callee.go index 38f596daf9e22c6af285616b54e9ce3c5374994e..2b8960332d1fd01189faf107b54b5bf309abf474 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/golang.org/x/tools/go/types/typeutil/map.go b/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/map.go index c7f754500640938c3a9f896bf7ca5c70e037a656..490ee904a62cb1007b8e9c6a9079a6f107dc8b6b 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/lsp/fuzzy/input.go b/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/input.go index ac377035ec63a342841c4e458a5e6b313e2475e2..c1038163f1a929cd19efd25915e522bad03d0964 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 16a643097de750828ba35e5648d6eda42563f06d..265cdcf1604c06cb5607369d60253e077af2871d 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 0000000000000000000000000000000000000000..062f491fb5ce6e79b47ad6aaf6afbcf20ba11c58 --- /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 0000000000000000000000000000000000000000..961d036fdb018e7adf5f3cd96b6447a7324b7435 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.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 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" + "go/types" +) + +// 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 "]" +} + +// 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/enabled_go117.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go new file mode 100644 index 0000000000000000000000000000000000000000..18212390e19278270d811366bb6d851f5cfecb29 --- /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 0000000000000000000000000000000000000000..d67148823c4d65713e6ed2a74725b61264fc3b6e --- /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/normalize.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go new file mode 100644 index 0000000000000000000000000000000000000000..090f142a5f34b4ad4c9ccadeb626ec99b1ba21b3 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go @@ -0,0 +1,216 @@ +// Copyright 2021 The Go Authors. 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 + +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 +// +// 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. +// +// 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()) + } + 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 + } + 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 +} + +// 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 computeTermSetInternal(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 := computeTermSetInternal(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 := computeTermSetInternal(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 0000000000000000000000000000000000000000..10857d504c4faf4fb00998d7c97092c0e08423fa --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..e509daf7be7f35f56df91c80c8dc8ebc41a153bf --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.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. + +//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) Index() int { unsupported(); return 0 } +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 +} + +// 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 { + 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 holds information about a structural type restriction. +type Term struct { + tilde bool + typ types.Type +} + +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 { + return &Term{tilde, typ} +} + +// 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) {} + +// 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. +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 0000000000000000000000000000000000000000..e45896fb02249f5652f495fe9329d860a70046cb --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go @@ -0,0 +1,196 @@ +// Copyright 2021 The Go 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() +} + +// 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 { + 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) +} + +// 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. +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/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 0000000000000000000000000000000000000000..7ddee28d98754af18a26750a839f1c385aa69795 --- /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/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 17966848771b3c16be035a1f583fc0f3e6e70445..214256617b58d479906b70fb2d0027e2541ab303 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 34dbdaf5dd3a74d28f40b28fb8d209ce1d6576bd..22dd145a55ecef92b0a2de17f026892ec772ae32 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-20211104044539-f987b9c94b31 ## explicit; go 1.14 github.com/google/pprof/driver github.com/google/pprof/internal/binutils @@ -15,20 +15,20 @@ 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-20210502124803-cbf565b21d1e +# 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 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-20211108221036-ceb1ce70b4fa ## 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.6.0-dev.0.20211102181907-3a5865c02020 ## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile @@ -39,16 +39,19 @@ 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/sync v0.0.0-20210220032951-036812b2e83c +## explicit +golang.org/x/sync/semaphore +# golang.org/x/sys v0.0.0-20211205182925-97ca703d548d ## 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-20210503060354-a79de5458b56 +# golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 +# 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 @@ -92,6 +95,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 fca594925f7a8a4c0828d871ddec9496d905ec16..46240e87bfd837c275b2f430091b1954bd06072f 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 diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go index 50dd0735fa9e7ceed0345794463e92e7a3daea4a..714ee320aee603f72975e4fd3e9d703f5825d4e8 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/compress/gzip/issue14937_test.go b/src/compress/gzip/issue14937_test.go index 20da0b6824a6a922d2a3e95b2b407aa3a59a294c..faee9bd43a68ed83b4e63f12afed38016a3e4c8e 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 ( diff --git a/src/compress/lzw/writer.go b/src/compress/lzw/writer.go index 552bdc2ce1746238bb066a2b1a15f1f4c48181b5..cf06ea80c787d7d09d9a3ca8460e58811f927af9 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)<= >. +// If future releases of Go add new ordered types, +// this constraint will be modified to include them. +type Ordered interface { + Integer | Float | ~string +} diff --git a/src/constraints/constraints_test.go b/src/constraints/constraints_test.go new file mode 100644 index 0000000000000000000000000000000000000000..47d4cba52a0780df92a5d14ac3e77053daaef081 --- /dev/null +++ b/src/constraints/constraints_test.go @@ -0,0 +1,117 @@ +// Copyright 2021 The Go Authors. 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 } +) + +// 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] +} + +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 } +) +`) + +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"}, + } { + 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 implement" + 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/container/heap/example_intheap_test.go b/src/container/heap/example_intheap_test.go index 02d3d8668ee01c84aa7338c8c6f3a60769843305..7e7ef8b8df711e48f0cc2034f1071ffd10dc99c4 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 da1a233b7075756cc113d1ee018d4b123af3af68..4511b6c33e0ff70f64eaf00261816ee536070cb2 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 2e09da8613aa3ed2822bedc6cabbdf8b081161be..c3168f9b2779bd96ad3d78067bc8ccf59e0f9bd5 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 f19f9cfa74b79556ec4d110ca7a62b4718d056f7..c9f9f140ea5abd4eecf40dcfc7572da63d7a5622 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 210424ceed7b7cac8bb793f9614845aa3ecc2080..9555ad3900311087dadd759955bcc8045e0842d9 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,25 +100,24 @@ 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) } -// 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,14 +126,12 @@ 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. // 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 @@ -144,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) } @@ -158,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 } @@ -169,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 99e006f39fdafddc07ba9ffd506dfbf920abe516..daa21149970514f296fd5f247023fcd4dc56a910 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) { @@ -283,26 +283,25 @@ 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 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. @@ -312,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. @@ -322,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. @@ -334,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 30bd0d74c9eee01d444f50d15ef69ab8fefec24c..4b659d25da0c73001a84477da62ad6f8ab2aaea7 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 6d3b3e5b322266bd5bebc90f949c564947ff9fa8..ce15032543be9202953c66882ca06b06dbf34a94 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 41d18abf8b6b1c745cb280f7fd2a241340739a73..28acbbc250f078c224b5ad974c70aeba2e10cbfc 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/benchmark_test.go b/src/context/benchmark_test.go index 69d75fff1866baa06362994adbc1ddadc647e226..144f473a4448166892aa66c8d214e8db64848069 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 733c5f56d9274d178923f7d452434bc8a379db7a..cf010b2a69547e8950d6e56450aa3d9a79d4cf16 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,11 +348,11 @@ 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 } - return c.Context.Value(key) + return value(c.Context, key) } func (c *cancelCtx) Done() <-chan struct{} { @@ -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,9 +559,35 @@ 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 c.Context.Value(key) + return value(c.Context, key) +} + +func value(c Context, key any) any { + 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) + } + } } diff --git a/src/context/context_test.go b/src/context/context_test.go index a2e2324a0eb2575ae6a179ac2da9298d09ff4d70..8673c0fdeaa82af7c78a27b27ae0df76a4ae8f50 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/aes/aes_gcm.go b/src/crypto/aes/aes_gcm.go index 1de0e457a266e02bd8fff70a84c73b6f606d1478..98fb6d8e9bf3249eec28284c7dc0c9042fc83b05 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/asm_ppc64le.s b/src/crypto/aes/asm_ppc64le.s index a69cb78c8b56a8bead4b8516d407b4b2d728cf31..f3a96a3a1705bb9c392700a8a59f904f29d1f40f 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 + diff --git a/src/crypto/aes/cipher_asm.go b/src/crypto/aes/cipher_asm.go index 4251805ef9b5a0f67880fdc34abca0091d3fcc06..c948f1a579ef2fd2390c15230a9970e107e73cf5 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 22ce3be7f3c0a88ee916141539099a887a2e7615..bff21ae54b59c01c2c06b65e624b6f5ab43c6f04 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 01b4e0875738d0f5140bdbf9dfa99c8babf34772..cba6c8873fecf4dfb59fb96b3d3f7950924d3622 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 03208402d79bd459b3552dacbeec21c980f6163d..43517a8e20329be56b5b5195598844e735201bed 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 f520208a379011889a7078113398eb6077cdd71c..f81eec531d8983793e103cdfd1dfd0c07290b61c 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/cipher/xor_ppc64x.s b/src/crypto/cipher/xor_ppc64x.s index 2ba6d9639c46c96d6d0acb2dd5ef3f37f20db30d..a2ec95c0be01ef1552978416ef998dcdaacee57f 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/crypto.go b/src/crypto/crypto.go index ce473b5afe1a4ac1f94d778d91b2f7158fce2a34..fe1c0690bc2211ad90a7e3d500049f24b43b713d 100644 --- a/src/crypto/crypto.go +++ b/src/crypto/crypto.go @@ -150,10 +150,30 @@ func RegisterHash(h Hash, f func() hash.Hash) { } // PublicKey represents a public key using an unspecified algorithm. -type PublicKey interface{} +// +// 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 any // PrivateKey represents a private key using an unspecified algorithm. -type PrivateKey interface{} +// +// 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 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. @@ -200,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/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go index 219436935f2c96f4bcf5c7943b173c7c90f06f44..282596d2d2df5e725bbdc11e1c0d2413d6e5e60a 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 diff --git a/src/crypto/ecdsa/ecdsa_noasm.go b/src/crypto/ecdsa/ecdsa_noasm.go index 68670a4f93fc61463d27ea405c11b3eabd561172..7fbca10b56f26166de48db64f4d3f9737b38a64c 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 f5633fb8a62dec57d7e48f96774dadc92577948f..fd1dc7c0605a5d94cf0aff5e632cc82f95c35f4f 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/ecdsa/ecdsa_test.go b/src/crypto/ecdsa/ecdsa_test.go index 556818acf4d14ac411cfc3393746e8bb075dca56..c8390b2cc9ffc4516b79114a5d40178ba6a0c22a 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/ed25519/internal/edwards25519/field/fe_amd64.go b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go index 8fe583939f15a5d0079ed309fa6866b3764aed0d..363020bd6b8fc86888933d9fc24e835bb97c3a58 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 ddb6c9b8f7f2453bfedcf56d7533048b38255d1a..9da280d1d887d01790b1a4c936a77b9eaefa20e7 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 af459ef51549e743f65998ef295447dc0feac8ff..075fe9b925742e031a45f7f398fbe3ffea18d3e0 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 234a5b2e5d18abb386567fe10e05517930cc4815..fc029ac12dae057c74925b3e5336c0367b73f831 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/ed25519/internal/edwards25519/scalar_alias_test.go b/src/crypto/ed25519/internal/edwards25519/scalar_alias_test.go index 18d800d5560538ff7513f26a1e6632644a9dd24b..827153b9bd316b6b911f8e40acdc6d0ed0948395 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/ed25519/internal/edwards25519/tables.go b/src/crypto/ed25519/internal/edwards25519/tables.go index beec956bf7e0a5d6df19297844808413d5f20708..5ca40f7bfa7a87f1b54ff65ced24d56db7142e6a 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/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go index f072960bfeddf83ce69d6a6ec1c701b99a2a6d9b..d06a284154659643d181ee20835c9ffbb319d92b 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 @@ -82,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) } @@ -125,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) } @@ -215,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) } @@ -287,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) } @@ -310,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) } @@ -428,7 +431,6 @@ func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) { } var initonce sync.Once -var p384 *CurveParams func initAll() { initP224() @@ -437,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), @@ -467,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 183861a54b52fe2678f9165b171a38b471e9b40f..f5b36f75ca0439a28d90c8cd2c75557252089c53 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 @@ -109,6 +108,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) { @@ -232,6 +240,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 @@ -274,3 +292,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/export_generate.go b/src/crypto/elliptic/export_generate.go new file mode 100644 index 0000000000000000000000000000000000000000..f15b302d8cdbb810f3b82d1e19e0f8c33937c60e --- /dev/null +++ b/src/crypto/elliptic/export_generate.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 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/fuzz_test.go b/src/crypto/elliptic/fuzz_test.go index 8ff3bf3cc245056169cc4c74d74de4db0d390217..2b5ddae1d9e96ee61293b245fae397976f31d08f 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 new file mode 100644 index 0000000000000000000000000000000000000000..367bd4b67d9248cac863f63a01041a0f359c4320 --- /dev/null +++ b/src/crypto/elliptic/gen_p256_table.go @@ -0,0 +1,110 @@ +// Copyright 2021 The Go 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" + "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 + +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/internal/fiat/Dockerfile b/src/crypto/elliptic/internal/fiat/Dockerfile index 7b5ece0e30f482066b4c1bf808b49d8e3020fc80..2877e0b2c125036d3e7313a2bee52eca0fcc6195 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 171f57a32742f85391482ea1672f1ad68fe83aeb..916ebc14ce8ad607516e88aad231bc246ae577d0 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 0000000000000000000000000000000000000000..9ecd8637886bace87db99f5af7c380baaec1c5ed --- /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 0000000000000000000000000000000000000000..fd8509de45897d213d4cf64495fbd8c47cf94608 --- /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 0000000000000000000000000000000000000000..4dddeb07a4199b394ad01d910e1d1577b5370f7d --- /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 0000000000000000000000000000000000000000..4ece3e9220837eff7a51e78deb12e40dbe4c3ae9 --- /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 0000000000000000000000000000000000000000..4163ed0c672336c857cf22cd86f928af4de7a634 --- /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 0000000000000000000000000000000000000000..5474d77d48276d097c6748df59076e5701865718 --- /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 0000000000000000000000000000000000000000..493bed47e1c2bf12702d4d8c8e4aa5f1eea45224 --- /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 0000000000000000000000000000000000000000..24169e98d92cfd385699ef1b4a00fc1cdf7b77d2 --- /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 dc677327e6de899c7c84047aabd242d717ef071d..3d12117e496a661872cbc49a2b88fc4b4b184009 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 } @@ -53,145 +51,85 @@ 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. - var out [66]byte - p521ToBytes(&out, &e.x) + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [p521ElementLen]byte + return e.bytes(&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 little-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[65] > 1 { - return nil, errors.New("invalid P-521 field encoding") + if len(v) != p521ElementLen { + return nil, errors.New("invalid P521Element encoding") } - var in [66]byte + for i := range v { + if v[i] < p521MinusOneEncoding[i] { + break + } + if v[i] > p521MinusOneEncoding[i] { + return nil, errors.New("invalid P521Element encoding") + } + } + var in [p521ElementLen]byte copy(in[:], v) - p521FromBytes(&e.x, &in) + p521InvertEndianness(in[:]) + var tmp p521NonMontgomeryDomainFieldElement + p521FromBytes((*p521UntypedFieldElement)(&tmp), &in) + p521ToMontgomery(&e.x, &tmp) return e, nil } // 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) +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] } - - // _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) - } - 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 f86283b587eb9a03d28b27459edc314e5c2560cb..9f4f290f4cae2de70cb802f79b48ce7b702470f5 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 0000000000000000000000000000000000000000..407711af36ce5b9732cdf9aa6d54c5aa65f25521 --- /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 661bde397e43924d519ca77b7fa3a400191ca71c..0000000000000000000000000000000000000000 --- 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[65] &= 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 0000000000000000000000000000000000000000..4eae998c5d7be46634889027f94638a6cb724fc5 --- /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 0000000000000000000000000000000000000000..74dbc184dd6e693fe08e38d7d24bc4a7b4bad446 --- /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 0000000000000000000000000000000000000000..24a166de0a6c4ec23d135289038b3d6d8d2d9d5e --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..cdbd195cf436a4bcd660e1f3c36845a839d0781f --- /dev/null +++ b/src/crypto/elliptic/internal/nistec/p521.go @@ -0,0 +1,310 @@ +// Copyright 2021 The Go Authors. 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 (&P521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element), + z: new(fiat.P521Element), + }).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/p224.go b/src/crypto/elliptic/p224.go index 8c76021464207f4f78a1bd0a7bc3d7d8e7bbb20e..a8533b85ff4c35f471374eed02752e6c22776f4e 100644 --- a/src/crypto/elliptic/p224.go +++ b/src/crypto/elliptic/p224.go @@ -1,778 +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 ( + "crypto/elliptic/internal/nistec" + "crypto/rand" "math/big" ) -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 { - 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] +// p224Curve is a Curve implementation based on nistec.P224Point. // -// 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 = [8]uint32{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] - } - - // 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 -} - -// 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. -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 := 0; i < 15; i++ { - 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 := 0; i < 15; i++ { - 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 << 1 - } - } - } - - 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 -func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) { - for i := 0; i < 8; i++ { - in[i] += p224ZeroModP63[i] - } - - // Eliminate the coefficients at 2**224 and greater. - 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 - - // 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 - - 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 - - // 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]. - 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. -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 := uint32(int32(out[i]) >> 31) - 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. - for i := 3; i < 7; i++ { - out[i+1] += out[i] >> 28 - out[i] &= bottom28Bits - } - top = out[7] >> 28 - out[7] &= bottom28Bits - - // Eliminate top while maintaining the same value mod p. - out[0] -= top - out[3] += top << 12 - - // 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. - - // 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 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 - 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 := uint32(int32(out[i]) >> 31) - 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 } -// 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 iff the least-significant-bit of control -// is true, and it runs in constant time. -func p224CopyConditional(out, in *p224FieldElement, control uint32) { - control <<= 31 - control = uint32(int32(control) >> 31) - - for i := 0; i < 8; i++ { - out[i] ^= (out[i] ^ in[i]) & control +// 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. -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 +func (p224Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { + p, ok := p224PointFromAffine(Bx, By) + if !ok { + return p224RandomPoint() } - ret &= bottom28Bits - return ret, buf + return p224PointToAffine(p.ScalarMult(p, scalar)) } -// 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) -} - -// 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 b213b273d23d887b5c6e6d888e29872022d45f3c..7971f631bf2a31b433d8c1bb0056c7cc59db9d02 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((*p224FieldElement)(&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, (*p224FieldElement)(&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 b2b12c8f138bfeace215e47cc36cc2f3a5b33df6..7ff7e335487509e54a11cc5c6720e80103bd0d1c 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 @@ -210,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. @@ -270,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_asm.go b/src/crypto/elliptic/p256_asm.go index 9a808f260ac09535d488dfa390b61584506beba4..ff0c1596aa0cd59c5cabf0dd01589e528d162077 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 @@ -19,6 +18,8 @@ import ( "math/big" ) +//go:generate go run -tags=tablegen gen_p256_table.go + type ( p256Curve struct { *CurveParams @@ -79,7 +80,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 +411,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 +438,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 c77b11bcf25c11a8179a2ee6ccacefe5ec5b695b..bd16add24175af6173c8f61d441f35571ec672a9 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 f571c5034284f43b94910070945a21420d619d49..2b2355d57cfa67c7ab0ebfd90788903f272d1e5e 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 16a4b4f22457fc667e2ce900c02f4b6804d67f19..ad2c6c2c51f3d8ef60d30285419dec615b22fd70 100644 --- a/src/crypto/elliptic/p256_asm_table.go +++ b/src/crypto/elliptic/p256_asm_table.go @@ -2,1472 +2,1429 @@ // 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 6b64f26286e506c62e0d6f06fcafd8a32f806940..6abd8cb11bc5ab21c9dea568729de1a2daf76758 100644 --- a/src/crypto/elliptic/p256_asm_table_test.go +++ b/src/crypto/elliptic/p256_asm_table_test.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 -// +build amd64 arm64 package elliptic import ( + "encoding/binary" "reflect" "testing" ) @@ -45,7 +45,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) } } diff --git a/src/crypto/elliptic/p256_generic.go b/src/crypto/elliptic/p256_generic.go index 25762a8f768b3b4825c0e59de47ffac0b68e9da8..7f8fab5398ecf825489cc5aa2ec09c966a50f4b2 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 40d9ed9d40fdc3fa99a5ce0845365d1efb8c97aa..e9a6a067a2258a23e90e8071ba183b699e7fab76 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 91e613b6310e1d76857700adbe14b502bd9ac919..735e9f57f1294019606a4756f02c128318f96694 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/elliptic/p256_test.go b/src/crypto/elliptic/p256_test.go index 1435f5e1a58a8f9a7f1a9cffe7d5ca03f08f79c7..c6862d95476c6fb8d40b247dfad1aa1fba531fac 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 0000000000000000000000000000000000000000..0fb7471850d82b8a90c10d8bfe98ce4b2c0fc213 --- /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 3d355943ec7fae1545ea804c20a9e63b398dcf47..6c9eed30e536cd715a28bfe6a7e50bf2183172fd 100644 --- a/src/crypto/elliptic/p521.go +++ b/src/crypto/elliptic/p521.go @@ -5,255 +5,158 @@ package elliptic import ( - "crypto/elliptic/internal/fiat" + "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 + 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.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) - b := bigIntToFiatP521(curve.B) // TODO: precompute this value. - - // 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, b) - - // y² = x³ - 3x + b - y2 := new(fiat.P521Element).Square(y1) - - return x3.Equal(y2) == 1 -} - -type p521Point struct { - x, y, z *fiat.P521Element + // 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 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] +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 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 } - return new(big.Int).SetBytes(xBytes) + return p, true } -// 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) { - 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) - 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) - - return fiatP521ToBigInt(xx), fiatP521ToBigInt(yy) + x, y = Unmarshal(P521(), out) + if x == nil { + panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding") + } + return x, y } -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] - } - x1, err := new(fiat.P521Element).SetBytes(xBytes) +// 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 } -// jacobianFromAffine converts (x, y) affine coordinates into (x, y, z) Jacobian -// 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 { - // (0, 0) is by convention the point at infinity, which can't be represented - // in affine coordinates, but is (0, 0, 0) in Jacobian. - if x.Sign() == 0 && y.Sign() == 0 { - return &p521Point{ - x: new(fiat.P521Element), - y: new(fiat.P521Element), - z: new(fiat.P521Element), - } +func (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() } + return p521PointToAffine(p1.Add(p1, p2)) } -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)) -} - -// 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) +func (p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + p, ok := p521PointFromAffine(x1, y1) + if !ok { + return p521RandomPoint() } - 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) - - q.x.Set(x) - q.y.Set(y) - q.z.Set(z) - return q + return p521PointToAffine(p.Double(p)) } -func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { - p := curve.jacobianFromAffine(x1, y1) - return curve.affineFromJacobian(p.doubleJacobian(p)) +func (p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { + p, ok := p521PointFromAffine(Bx, By) + if !ok { + return p521RandomPoint() + } + return p521PointToAffine(p.ScalarMult(p, scalar)) } -// 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) - - return q +func (p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { + p := nistec.NewP521Generator() + return p521PointToAffine(p.ScalarMult(p, scalar)) } -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), - } - - for _, byte := range scalar { - for bitNum := 0; bitNum < 8; bitNum++ { - p.doubleJacobian(p) - 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)) - } +func bigFromDecimal(s string) *big.Int { + b, ok := new(big.Int).SetString(s, 10) + if !ok { + panic("invalid encoding") } - - return curve.affineFromJacobian(p) + 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/crypto/internal/subtle/aliasing.go b/src/crypto/internal/subtle/aliasing.go index 86e0f3cfe70b70d70d300c405536af4b79ee357d..16e2fcab124814cc809f8fb4afdfa8c1ac07ee99 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 35b442f7a2321e77fea5e0bfaf7bf8b22f804b91..90ac4b61cc2ebd67b8ef56e772445086a177bec4 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 29729fad015e3de3ae0dec6e2010c1f7d02c17aa..cd2700a5cfeb8b07eb2c4f33421d1a4d84c8a9f5 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/md5_test.go b/src/crypto/md5/md5_test.go index acd456af2151782686a90f6acb20b4a736cde8a3..851e7fb10d42f59530d8a5dd9d6933d71dff908a 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_decl.go b/src/crypto/md5/md5block_decl.go index bc2d58c06940b3b5401512b5e2539c32eb072426..6716a0c9db7db68c798a333b1963f6a66d757c75 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 ea4fbcd0b41012630b43ca7e584ccfb2c0efd02a..c929c2b84aca519cece6c9508c792b52ee60030c 100644 --- a/src/crypto/md5/md5block_generic.go +++ b/src/crypto/md5/md5block_generic.go @@ -3,10 +3,11 @@ // 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 const haveAsm = false -var block = blockGeneric +func block(dig *digest, p []byte) { + blockGeneric(dig, p) +} diff --git a/src/crypto/md5/md5block_ppc64x.s b/src/crypto/md5/md5block_ppc64x.s index 8c28ec2473ca024f8793e73ff9e324d7c9ff8816..69a20e7cad3399abf864bf13dcaf976897657ab0 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/rand/eagain.go b/src/crypto/rand/eagain.go index 85d4d9d47f9db4bc0025c183d51fc3db2efe6e34..f018e759312c3ad2741435984ca55be7a232b91b 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.go b/src/crypto/rand/rand.go index fddd1147e6e3c692b3f2d4da69f427a10e8eb6fb..b6248a443874df146ac71757fbdeed19660ed66c 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. diff --git a/src/crypto/rand/rand_batched.go b/src/crypto/rand/rand_batched.go index d7c5bf3562d54747f0ab5db368f90a219dae964c..3e8e62038292040a38b4826eb3e8cc4448515f61 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 2d20922c8253098f59eac79fe913c28ff9631cf1..28e45aa689ec185976c02a4b69caf54983a7fc28 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 f82018a4951c743c82f15c28b82262b601112f27..2bf2f520324438acf005b0364c85eaec01baa6f4 100644 --- a/src/crypto/rand/rand_getentropy.go +++ b/src/crypto/rand/rand_getentropy.go @@ -2,8 +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 || openbsd -// +build darwin openbsd +//go:build (darwin && !ios) || openbsd package rand diff --git a/src/crypto/rand/rand_js.go b/src/crypto/rand/rand_js.go index 7ddc2b6169cbe6d7f2587947ad150b68c6cc1739..91e69fae5d63fa778db48430429dc72d9be73268 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 81277eb6a5dea924896a1fa5f87aab0315f360a2..40347874c53412b4ce6491b0be7df80940c2a4ea 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 4bb8b3324f293b7f27493ccfded6305e4938d2bc..45d1f57d39cfd352d678c07e69e3dfb9658d2f6f 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 436f78c74534d40f4fef63a31bebb354baad4edf..df4e28f64eee9e149bb1df5fa9faa224a08986d6 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/sha1_test.go b/src/crypto/sha1/sha1_test.go index c3e6010af121928d28227bb4d1095c5437fa14e4..ab43c7792d4949800532408cd407fe33ce4c31e1 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_decl.go b/src/crypto/sha1/sha1block_decl.go index 93054efa7c1827e1c117fe22a37f18bd6a03dafc..518a4b6b67871d32872a5c66acf100c2eac48811 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 feaba5a23abab38cb230443280f0fbfdf45b6f20..ba35155d0b92ef4d4c801f8dea8d70d5ec36775d 100644 --- a/src/crypto/sha1/sha1block_generic.go +++ b/src/crypto/sha1/sha1block_generic.go @@ -3,8 +3,9 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !386 && !arm && !s390x && !arm64 -// +build !amd64,!386,!arm,!s390x,!arm64 package sha1 -var block = blockGeneric +func block(dig *digest, p []byte) { + blockGeneric(dig, p) +} diff --git a/src/crypto/sha256/fallback_test.go b/src/crypto/sha256/fallback_test.go index 7ce88cbb2a8b2f525e6e0123c035b1dda8d3d19e..3f561aadd65ee62154795788d5aed97d165372ac 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/sha256.go b/src/crypto/sha256/sha256.go index e1cccf65a60307517d7adecf7dcefdbd47d88aa5..659531dc716f7f7109edd9c851b2a19d0aef477c 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/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go index a2794b015dbc44375cb502afc08fe53d38111b8a..702aa0b371abb6d65b57c235479f7bcedcc14277 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_decl.go b/src/crypto/sha256/sha256block_decl.go index a6bb396f1339c2e2601f5d29629669d32c88bfa5..c9c11944876d49d4c2e4efdee5982d555586729d 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 620c048b93c0672c3957e0a9374a2ceb4b82b220..a8878c2eeea21fe34f4ebc84de8e9ad4066582b0 100644 --- a/src/crypto/sha256/sha256block_generic.go +++ b/src/crypto/sha256/sha256block_generic.go @@ -3,8 +3,9 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !386 && !s390x && !ppc64le && !arm64 -// +build !amd64,!386,!s390x,!ppc64le,!arm64 package sha256 -var block = blockGeneric +func block(dig *digest, p []byte) { + blockGeneric(dig, p) +} diff --git a/src/crypto/sha512/fallback_test.go b/src/crypto/sha512/fallback_test.go index faf732670adf220ed938c22e758428ea27be5071..db5b13c38c4f080cd179dac7bb9bd183e47f9965 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/sha512.go b/src/crypto/sha512/sha512.go index 9c143a2a2817786095b94b2775db18210ff3a7be..d5715558c0484b40706d37e6957849e1874dc1b7 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 } diff --git a/src/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go index 0e1528fc69f6018162473f9223557a7cfbee9d3a..aea772c7da5e60a4df3d2e85fee0025b87497c86 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) diff --git a/src/crypto/sha512/sha512block_amd64.go b/src/crypto/sha512/sha512block_amd64.go index e2386f29ab6fe2d90f3a3f246d18b0200163ec97..8da3e1473f6c45289a690dd6af8783c85d63beab 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 6c22f44801beb9cf014ad40ce4492cfa054a07d0..c6dcdf5db624461bf7af68dcf7478c25c39e89f0 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 865a7356f1ef75adb185458c83dffa1feb96d68e..62ea237867bce0ce270981405eae9a433955bf68 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/cipher_suites.go b/src/crypto/tls/cipher_suites.go index 4bf06468c6dae4741d0302b15b77f5219bc054ad..d164991eec94c1c05f53d837e2bdadcded4c0717 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 d561e61707edd979576c9c21ec8224aa2228c447..e6e7598ce97ea13c4fe6934826eac532bd8783fa 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" @@ -659,7 +660,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 @@ -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") } @@ -1444,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 969f357834c0a5c1733b7b939248ebf07d514510..28ab063782000652361949af4ecb3a00ec734339 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -151,21 +151,28 @@ 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 { 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 } @@ -190,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 @@ -928,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) }, } @@ -1004,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 7ea90f8a7b51c32f0d7e595a94d96db724872233..74509c9deaab2504273143119033897e2756dbbe 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. @@ -38,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 @@ -58,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 4af3d998a36f800c02989a37b9f8ba0d3eaed36a..a3e00777f12559e4739eaf424e227695de1b3126 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) @@ -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 b6eb488a4d7899bc19ad2c6e330ff8c60bf4beb4..0950bb0ac4533f6961732fb18bb5078da3fab238 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 @@ -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.go b/src/crypto/tls/handshake_messages.go index b5f81e443668a1ead5e0c9c5e8806437b32f7a6c..17cf85910fafd8603949d68a6360b972e3aa5802 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") } } diff --git a/src/crypto/tls/handshake_messages_test.go b/src/crypto/tls/handshake_messages_test.go index bb8aea86700509d82222e73ae6f30eedb59ef1f7..cc427bf72a01726b54b1748f696174a83fd504a8 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 43f30e2fefd4fbec79f49f8e5ad78b51876c6dbe..097046340b87b6714ad1ff7d8684c7b3d6a6a496 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") } @@ -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 f61b4c88efaf1d270c00d9bafc7831e4db6bf124..6d2c4056261feea212d893c93ea874f82741d372 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 @@ -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. @@ -582,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/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index 08251b84def7eee0deb1f961c025dbe350856749..0b195027621ef04160f48742a765375cadba9500 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 9bfb1177f27d04402ae687e2e1365154bbc8a818..bacc8b7d4fed57805ff3eb920abab998f62c113e 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 { @@ -364,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 diff --git a/src/crypto/tls/handshake_unix_test.go b/src/crypto/tls/handshake_unix_test.go index 19fc6986769f62fdb5eb29ca1c84694b51e8013b..b61e7c24efb2049429a3051dbfc7e7c8d9e924d9 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/cert_pool.go b/src/crypto/x509/cert_pool.go index bcc5db3b703ae3f188f15ab36207110659e8560c..873ffeee1dae21703a5c0cdf3a92da42780c4d48 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,11 +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") - } - if sysRoots := systemRootsPool(); sysRoots != nil { return sysRoots.copy(), nil } @@ -239,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 0000000000000000000000000000000000000000..d4dd9d5c22f59d7b8eb353a90793c838df4e4525 --- /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/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go index fcfbc1e561573d9ae59a7a4feb0704de5e06d975..cda1d95d8141f3aef9c7359feac77d06f3ce1c7c 100644 --- a/src/crypto/x509/internal/macos/corefoundation.go +++ b/src/crypto/x509/internal/macos/corefoundation.go @@ -2,8 +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 -// +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 @@ -15,6 +14,7 @@ import ( "internal/abi" "reflect" "runtime" + "time" "unsafe" ) @@ -36,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. @@ -127,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 cda2336c9d1b66301b14bf6c19a63c030c0c29a4..d69f72f795cd949504851c32a9b4be7599076f59 100644 --- a/src/crypto/x509/internal/macos/corefoundation.s +++ b/src/crypto/x509/internal/macos/corefoundation.s @@ -2,8 +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 -// +build darwin,!ios +//go:build darwin #include "textflag.h" @@ -28,3 +27,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 0f6fa42b7bf61baad76663f566719297bc953d6c..ef64bda49fd258bf42807b3792d913076e6781a4 100644 --- a/src/crypto/x509/internal/macos/security.go +++ b/src/crypto/x509/internal/macos/security.go @@ -2,13 +2,13 @@ // 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 +//go:build darwin package macOS import ( "errors" + "fmt" "internal/abi" "strconv" "unsafe" @@ -30,6 +30,19 @@ const ( SecTrustSettingsResultUnspecified ) +type SecTrustResultType int32 + +const ( + SecTrustResultInvalid SecTrustResultType = iota + SecTrustResultProceed + SecTrustResultConfirm // deprecated + SecTrustResultDeny + SecTrustResultUnspecified + SecTrustResultRecoverableTrustFailure + SecTrustResultFatalTrustFailure + SecTrustResultOtherError +) + type SecTrustSettingsDomain int32 const ( @@ -79,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" @@ -116,3 +115,120 @@ 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() + +//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 0038f25b27701a33a3cde4b2d78eadeac9fe11a0..36f814f3cd5d4a1aebdda20977b7da4d897e11f8 100644 --- a/src/crypto/x509/internal/macos/security.s +++ b/src/crypto/x509/internal/macos/security.s @@ -2,8 +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 -// +build darwin,!ios +//go:build darwin #include "textflag.h" @@ -12,9 +11,27 @@ 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 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) +TEXT ·x509_SecCertificateCopyData_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecCertificateCopyData(SB) diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go index c59a7dc1a62c7343fbc7126a9a965a6613b4e548..04c1e7a627453437ca810a67e496894d7094b7db 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 @@ -1846,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 f085162a4e88be3d998cdb1bdfebb61282cdee0f..5e6bd543686e50ca6b46bb58cb1d28a9da119da3 100644 --- a/src/crypto/x509/parser.go +++ b/src/crypto/x509/parser.go @@ -214,22 +214,22 @@ 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 } -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/pem_decrypt.go b/src/crypto/x509/pem_decrypt.go index 781cb3de834d94c02eaad1abe3ce362e1ca7af73..682923ac531fdaca2bbcef78d2598ffcdb1dbe8e 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/crypto/x509/pkcs8.go b/src/crypto/x509/pkcs8.go index a5ee4cfbfeff14be4c8610671b51945f89b12b5c..d77efa315612ac29d332ef818419a5094f4a8772 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 62ae06549645f7063d9e34951801645266e42e19..e9179ed0679be5dfc8570e04e3de66f6955d99a2 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/root_aix.go b/src/crypto/x509/root_aix.go index 4d50a134738e025050f5fb894001991ae89d4d36..99b7463a2a7149c0d132393964af0f78f0d9dc2b 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 6712ea32a68414681c5cd0658dc12f930107327f..a76aef8659b55a2551d08931b5d9963062798193 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 @@ -15,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_darwin.go b/src/crypto/x509/root_darwin.go index 05593bb1055b50d06df34ec12455385621f3b856..1ef9c0f71e54506a1cfe90c752e4a9c2b852c367 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -2,239 +2,107 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !ios -// +build !ios - package x509 import ( - "bytes" macOS "crypto/x509/internal/macos" - "fmt" - "os" - "strings" + "errors" ) -var debugDarwinRoots = strings.Contains(os.Getenv("GODEBUG"), "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.SecCertificateCopyData(cert) + if err != nil { + return nil, err } + return ParseCertificate(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 macOS.SecTrustSettingsResultUnspecified, nil +func loadSystemRoots() (*CertPool, error) { + return &CertPool{systemPool: true}, nil } diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go index ae2bd02bf85dfc2ca329da3dff9f7e2f2dc0ff02..90a464f624960a75bd39d390d7e1d492a499a511 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/root_ios.go b/src/crypto/x509/root_ios.go deleted file mode 100644 index 9bc62f8abb6802747da47494632341f5c37a7d73..0000000000000000000000000000000000000000 --- a/src/crypto/x509/root_ios.go +++ /dev/null @@ -1,4873 +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 -// +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 05bd672d5d8355a4bb32fd70e64c121edbdf5614..0000000000000000000000000000000000000000 --- a/src/crypto/x509/root_ios_gen.go +++ /dev/null @@ -1,181 +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 -// +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". - -// +build ios -// +build !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_js.go b/src/crypto/x509/root_js.go index f2c2c0af3803851cca5811c627cff5f1979366d8..7b3f1e486ff5cb2e4dcd60c565186d0641936136 100644 --- a/src/crypto/x509/root_js.go +++ b/src/crypto/x509/root_js.go @@ -3,13 +3,11 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm 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 ad6ce5cae79dc020eb656996434bd118f7e958af..e32989b999ed7118db6ebf6de9e94dad4c843852 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_omit.go b/src/crypto/x509/root_omit.go deleted file mode 100644 index 81f2f112d07da5e2933a008d5518e76d774135d8..0000000000000000000000000000000000000000 --- a/src/crypto/x509/root_omit.go +++ /dev/null @@ -1,27 +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 -// +build darwin,arm64 darwin,amd64,ios -// +build 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 158bd7f91aebedc7195d4cbbd96f6fd6446ca612..0000000000000000000000000000000000000000 --- a/src/crypto/x509/root_omit_test.go +++ /dev/null @@ -1,24 +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 -// +build darwin,arm64 darwin,amd64,ios -// +build 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/root_plan9.go b/src/crypto/x509/root_plan9.go index 2bdb2fe7136aced8f87c1a344ffe77bd9c737050..3bd06fe50d85bf2f2e6eba64d126759b718de102 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_solaris.go b/src/crypto/x509/root_solaris.go index 97c19139e3e759a75c93826cec9f1eecb8c60be4..617f26961f60bf335693a55acd0f4dbb5099744e 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", } diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go index dede825eddf4967fee4e2cbf9be06593c69f3d02..aa54f891ca003a6c9dcaedc50a95a8c28569fa85 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 7118f12d744cdf5e4a8515d47496652eb3297f6a..7197a0de3b185c26e597b894ee2fc56b426daea1 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/root_windows.go b/src/crypto/x509/root_windows.go index 1e9be80b7dd67d35c73cfb01ec743a23c879da3a..d65d8768d9052885cfed1972f74b43d4649502e4 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. @@ -218,11 +222,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 @@ -276,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 0000000000000000000000000000000000000000..ce6d9273d98f01f3c774b9a41d5b1e3265a76e20 --- /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 9ef11466a470a3730ea08614a4a0dd8e907d723f..e8c7707f3fee4a19680fc896260eeda61781678b 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 @@ -741,9 +741,20 @@ 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" { - 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 { @@ -1085,14 +1096,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 9954a670da0bd16cfd3b5e594c6e2b63da5941f6..f4ea08bbf5516a7ee53108ea5a945ebc0c3aff92 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" @@ -203,19 +204,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. @@ -482,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 { @@ -547,6 +538,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) @@ -932,93 +927,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 @@ -1932,8 +1840,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" || runtime.GOOS == "ios" { + 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.go b/src/crypto/x509/x509.go index 4304ab54e1a7052f7a7c40e6eb589900db7c56e9..47be77d994df9634ca0c4b2d77038c68e7d3524d 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" @@ -51,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 { @@ -68,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{ @@ -113,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 @@ -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 @@ -635,7 +636,7 @@ type Certificate struct { SignatureAlgorithm SignatureAlgorithm PublicKeyAlgorithm PublicKeyAlgorithm - PublicKey interface{} + PublicKey any Version int SerialNumber *big.Int @@ -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 @@ -801,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) } @@ -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 @@ -1339,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) { @@ -1465,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") @@ -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) } @@ -1627,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") @@ -1702,7 +1723,7 @@ type CertificateRequest struct { SignatureAlgorithm SignatureAlgorithm PublicKeyAlgorithm PublicKeyAlgorithm - PublicKey interface{} + PublicKey any Subject pkix.Name @@ -1839,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 a4053abf41d4160c6d8112164fabb5ba2bef51e4..a42b852a424882b5352e440f2709e34c99ba6e1d 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,14 +581,14 @@ func TestCreateSelfSignedCertificate(t *testing.T) { tests := []struct { name string - pub, priv interface{} + pub, priv any 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}, @@ -1234,7 +1233,7 @@ func TestCRLCreation(t *testing.T) { tests := []struct { name string - priv interface{} + priv any cert *Certificate }{ {"RSA CA", privRSA, certRSA}, @@ -1386,13 +1385,13 @@ func TestCreateCertificateRequest(t *testing.T) { tests := []struct { name string - priv interface{} + priv any 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 = ` @@ -1949,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" || runtime.GOOS == "ios" { + t.Skip("not implemented on Windows (Issue 16736, 18609) or darwin (Issue 46287)") } a, err := SystemCertPool() if err != nil { @@ -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 diff --git a/src/crypto/x509/x509_test_import.go b/src/crypto/x509/x509_test_import.go index ef3ee807bf0c5d037d7ce8beea4a7d8be9f39acb..2474e3d810edfd4a591c48226cf4b0bad2f6a3ea 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/database/sql/convert.go b/src/database/sql/convert.go index b966ef970c17047731eed681d5a6729de15e3e54..4d9d070137b012deed10435458725979f7007625 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 } @@ -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 @@ -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 @@ -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/convert_test.go b/src/database/sql/convert_test.go index 2668a5ed5e76b15313142ac6a6df2e8a76e1123e..6d09fa1eaee76865c69cd62e458c77930d5e17c5 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 @@ -51,9 +51,6 @@ var ( scanbytes []byte scanraw RawBytes scanint int - scanint8 int8 - scanint16 int16 - scanint32 int32 scanuint8 uint8 scanuint16 uint16 scanbool bool @@ -61,7 +58,7 @@ var ( scanf64 float64 scantime time.Time scanptr *int64 - scaniface interface{} + scaniface any ) func conversionTests() []conversionTest { @@ -164,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{} @@ -188,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)) } @@ -219,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...) } @@ -263,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 @@ -304,7 +301,7 @@ func TestNullString(t *testing.T) { type valueConverterTest struct { c driver.ValueConverter - in, out interface{} + in, out any err string } @@ -338,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"}, @@ -358,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) } @@ -433,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, @@ -446,7 +443,7 @@ func TestDriverArgs(t *testing.T) { }, }, 1: { - args: []interface{}{nilValuerVPtr}, + args: []any{nilValuerVPtr}, want: []driver.NamedValue{ { Ordinal: 1, @@ -455,7 +452,7 @@ func TestDriverArgs(t *testing.T) { }, }, 2: { - args: []interface{}{nilValuerPPtr}, + args: []any{nilValuerPPtr}, want: []driver.NamedValue{ { Ordinal: 1, @@ -464,7 +461,7 @@ func TestDriverArgs(t *testing.T) { }, }, 3: { - args: []interface{}{"plain-str"}, + args: []any{"plain-str"}, want: []driver.NamedValue{ { Ordinal: 1, @@ -473,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 f09396175acf86099e5d902fb944d1f8131210e2..5342315d124a9d044776690da5a25b00a969e45c 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 { @@ -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/driver/types.go b/src/database/sql/driver/types.go index 24c3a45483637816365a6b5682394d8c600e334e..506ce6c2cd3c356a291f4f4e4fec68018da4d294 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) } @@ -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 @@ -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 } @@ -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/database/sql/driver/types_test.go b/src/database/sql/driver/types_test.go index 4c2996da85f4eb7853d88884ebd1de2d55fa7c9c..80e5e05469186a100dbd49796d265435e319eb9e 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 4b68f1cba9fe1aa7f9b2806494a8eb4c6c9e066f..8f953f6cb68dc7d5f8598beac088c5a4e8c1a8ed 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 @@ -113,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 { @@ -185,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) @@ -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 } @@ -491,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...)) } @@ -573,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": @@ -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 @@ -816,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 { @@ -826,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 @@ -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 @@ -917,7 +930,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( rows: [][]*row{ { { - cols: []interface{}{ + cols: []any{ txStatus, }, }, @@ -967,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 { @@ -983,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]] } @@ -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 @@ -1161,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 @@ -1176,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 } @@ -1247,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 68fb392e0dbb45f5f4246fa8f95797250dee0735..d55cee1210971c4292d6cbab9bd95f83a1f68f4e 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 @@ -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 @@ -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 { @@ -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 { @@ -1079,7 +1080,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 +1089,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: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 +1302,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++ @@ -1287,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 @@ -1351,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 } @@ -1412,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 } @@ -1426,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 } @@ -1441,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 @@ -1521,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 @@ -1594,16 +1627,18 @@ 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 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 @@ -1614,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 @@ -1626,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) }() @@ -1667,16 +1702,18 @@ 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 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 @@ -1687,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 @@ -1704,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 { @@ -1774,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} } @@ -1788,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...) } @@ -1805,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 @@ -1884,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 { @@ -1954,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 @@ -1964,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 @@ -1978,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} } @@ -2002,9 +2043,9 @@ 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 +// 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 @@ -2054,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) } } @@ -2248,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) @@ -2280,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 { @@ -2323,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. // @@ -2442,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 @@ -2455,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 @@ -2473,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...) } @@ -2483,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} } @@ -2497,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...) } @@ -2574,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() @@ -2586,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 @@ -2594,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 } } @@ -2606,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() @@ -2722,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() @@ -2734,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 @@ -2768,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 } } @@ -2780,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) @@ -2800,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} @@ -2822,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...) } @@ -3144,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) @@ -3222,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 { @@ -3305,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 f771dee4a9772a37444ef9b65d27de9b12af887a..1bb9afc4070e97a4ae15e9a36efd9c80235ad4e9 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 { @@ -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 @@ -3151,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 } @@ -3896,14 +3904,80 @@ 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 { + tm = tm.Add(time.Nanosecond) + nowFunc = func() time.Time { + return tm + } + c, err := db.Conn(ctx) + if err != nil { + t.Error(err) + } + conns[i] = c + } + + for i := len(conns) - 1; i >= 0; i-- { + tm = tm.Add(time.Nanosecond) + nowFunc = func() time.Time { + return tm + } + if err := conns[i].Close(); err != nil { + t.Error(err) + } + } + + return tm +} + func TestMaxIdleTime(t *testing.T) { + usedConns := 5 + reusedConns := 2 list := []struct { - wantMaxIdleTime 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.Nanosecond, 1, 10 * time.Millisecond}, - {time.Hour, 0, 10 * time.Millisecond}, + { + 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, + 0, + time.Second, + 0, + 0, + 10 * time.Millisecond, + 0}, } baseTime := time.Unix(0, 0) defer func() { @@ -3917,23 +3991,43 @@ 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) + db.SetConnMaxLifetime(item.wantMaxLifetime) preMaxIdleClosed := db.Stats().MaxIdleTimeClosed - if err := db.Ping(); err != nil { - t.Fatal(err) - } + // Busy usedConns. + 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. + tm = testUseConns(t, reusedConns, tm, db) + + tm = tm.Add(item.secondTimeOffset) nowFunc = func() time.Time { - return baseTime.Add(item.timeOffset) + return tm } db.mu.Lock() - closing := db.connectionCleanerRunLocked() + nc, closing := db.connectionCleanerRunLocked(time.Second) + if nc != item.wantNextCheck { + t.Errorf("got %v; want %v next check duration", nc, item.wantNextCheck) + } + + // 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.Unlock() for _, c := range closing { c.Close() @@ -3944,8 +4038,8 @@ 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) + if g, w := maxIdleClosed, item.wantMaxIdleClosed; g != w { + t.Errorf("got: %d; want %d max idle closed conns", g, w) } }) } @@ -4035,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"}, @@ -4224,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/buildinfo/buildinfo.go b/src/debug/buildinfo/buildinfo.go new file mode 100644 index 0000000000000000000000000000000000000000..2c0200e8dcb161c19a2bf295a72431a436ebaf5c --- /dev/null +++ b/src/debug/buildinfo/buildinfo.go @@ -0,0 +1,397 @@ +// Copyright 2021 The Go Authors. 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) { + vers, mod, err := readRawBuildInfo(r) + if err != nil { + return nil, err + } + bi := &BuildInfo{} + if err := bi.UnmarshalText([]byte(mod)); err != nil { + return nil, err + } + bi.GoVersion = vers + 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 { + 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. + // 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. + // 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]) + if data[15]&2 != 0 { + vers, data = decodeString(data[32:]) + mod, data = decodeString(data) + } else { + 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:])) + } + if vers == "" { + return "", "", errNotGoExe + } + 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 +} + +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)) + 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 0000000000000000000000000000000000000000..8346be01095c4ef43267494641882fc5194c57ac --- /dev/null +++ b/src/debug/buildinfo/buildinfo_test.go @@ -0,0 +1,227 @@ +// Copyright 2021 The Go Authors. 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" + "regexp" + "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) + } + } + + 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\t-compiler=") { + return match + } + return "" + }) + return got + } + + 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: "go\tGOVERSION\n" + + "path\texample.com/m\n" + + "mod\texample.com/m\t(devel)\t\n" + + "build\t-compiler=gc\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: "go\tGOVERSION\n" + + "path\texample.com/m\n" + + "build\t-compiler=gc\n", + }, + { + 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 if got := cleanOutputForComparison(string(got)); got != tc.want { + if got != tc.want { + t.Fatalf("got:\n%s\nwant:\n%s", got, tc.want) + } + } + } + }) + } + }) + } +} diff --git a/src/debug/dwarf/entry.go b/src/debug/dwarf/entry.go index 9f5ac570803d4c4d351633155f51ddb679eb617e..cbdc838a12b1d142064d357118a92e9ad7f31375 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)) @@ -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) } diff --git a/src/debug/dwarf/entry_test.go b/src/debug/dwarf/entry_test.go index 1f41d742ea5de2916561339a7c790d2af1877286..8c6ca7259ea6060020820f7f19f44e0502f01a41 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/dwarf/testdata/typedef.c b/src/debug/dwarf/testdata/typedef.c index 4780a0b2bad80e94b7fec5e6d187faceb8b370cc..3e7e008621e832d81af45f1e77f8d1fcdc645d44 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 Binary files /dev/null and b/src/debug/dwarf/testdata/typedef.macho4 differ diff --git a/src/debug/dwarf/type.go b/src/debug/dwarf/type.go index eb5a666ed38d3bcaf1cc42a0b54c5e28ef63453a..2e5a605174c378f29ab89acad9a28240555f133a 100644 --- a/src/debug/dwarf/type.go +++ b/src/debug/dwarf/type.go @@ -516,7 +516,10 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off }).Basic() t.Name = name t.BitSize, _ = e.Val(AttrBitSize).(int64) - t.BitOffset, _ = e.Val(AttrBitOffset).(int64) + haveBitOffset := false + if t.BitOffset, haveBitOffset = e.Val(AttrBitOffset).(int64); !haveBitOffset { + t.BitOffset, _ = e.Val(AttrDataBitOffset).(int64) + } case TagClassType, TagStructType, TagUnionType: // Structure, union, or class type. (DWARF v2 §5.5) @@ -578,7 +581,9 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off haveBitOffset := false f.Name, _ = kid.Val(AttrName).(string) f.ByteSize, _ = kid.Val(AttrByteSize).(int64) - f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64) + if f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64); !haveBitOffset { + f.BitOffset, haveBitOffset = kid.Val(AttrDataBitOffset).(int64) + } f.BitSize, _ = kid.Val(AttrBitSize).(int64) t.Field = append(t.Field, f) diff --git a/src/debug/dwarf/type_test.go b/src/debug/dwarf/type_test.go index fda03fdbb09cf22230a006747a2a80e000f11898..431d0853e0546d0361dc627d6920e25065a37bcd 100644 --- a/src/debug/dwarf/type_test.go +++ b/src/debug/dwarf/type_test.go @@ -228,3 +228,54 @@ func TestUnsupportedTypes(t *testing.T) { } } } + +func TestBitOffsetsELF(t *testing.T) { testBitOffsets(t, elfData(t, "testdata/typedef.elf")) } + +func TestBitOffsetsMachO(t *testing.T) { + testBitOffsets(t, machoData(t, "testdata/typedef.macho")) +} + +func TestBitOffsetsMachO4(t *testing.T) { + testBitOffsets(t, machoData(t, "testdata/typedef.macho4")) +} + +func TestBitOffsetsELFDwarf4(t *testing.T) { + testBitOffsets(t, elfData(t, "testdata/typedef.elf4")) +} + +func testBitOffsets(t *testing.T, d *Data) { + r := d.Reader() + for { + e, err := r.Next() + if err != nil { + t.Fatal("r.Next:", err) + } + if e == nil { + break + } + + if e.Tag == TagStructType { + typ, err := d.Type(e.Offset) + if err != nil { + t.Fatal("d.Type:", err) + } + + t1 := typ.(*StructType) + + for _, field := range t1.Field { + // We're only testing for bitfields + if field.BitSize == 0 { + continue + } + + // Ensure BitOffset is not zero + if field.BitOffset == 0 { + t.Errorf("bit offset of field %s in %s %s is not set", field.Name, t1.Kind, t1.StructName) + } + } + } + if e.Tag != TagCompileUnit { + r.SkipChildren() + } + } +} diff --git a/src/debug/elf/elf.go b/src/debug/elf/elf.go index 9f8399d4d3cef70a68bdb126b4a5c59f1be127d8..4c51bc4de2a16a0c7b061b864711390196d3a377 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"}, diff --git a/src/debug/elf/elf_test.go b/src/debug/elf/elf_test.go index f8985a8992361fb1f4ff958515f705bae3575f65..a61b491090d173a24235ca66becd05afed23cb86 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 b25d8209e36f95a90e91beecdcf1176cc5ec9742..eefcaab8d6994e6d17148e599444008415550e7a 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 { @@ -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. diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index a72f9847d7cc08f371e041d89959acd9171492f3..d9ae8b73a93bc89cd722a076cd7a5cd6372dc24b 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" ) @@ -22,6 +23,7 @@ const ( ver11 ver12 ver116 + ver118 ) // A LineTable is a data structure mapping program counters to line numbers. @@ -48,10 +50,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 uint64 // address of runtime.text symbol (1.18+) funcnametab []byte cutab []byte funcdata []byte @@ -166,8 +169,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. @@ -193,10 +199,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 || @@ -217,30 +225,49 @@ 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 } + t.version = possibleVersion - // 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]) + 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 ver118: + t.nfunctab = uint32(offset(0)) + t.nfiletab = uint32(offset(1)) + 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) + t.pctab = data(6) + t.funcdata = data(7) + t.functab = data(7) + functabsize := (int(t.nfunctab)*2 + 1) * t.functabFieldSize() + t.functab = t.functab[:functabsize] 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:] - functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize + 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 := (int(t.nfunctab)*2 + 1) * t.functabFieldSize() t.functab = t.functab[:functabsize] case ver12: t.nfunctab = uint32(t.uintptr(t.Data[8:])) @@ -248,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:] @@ -257,59 +284,50 @@ func (t *LineTable) parsePclnTab() { default: panic("unreachable") } - 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. - defer func() { - recover() - }() + if !disableRecover { + defer func() { + recover() + }() + } - n := len(t.functab) / int(t.ptrsize) / 2 - funcs := make([]Func, n) + ft := t.funcTab() + funcs := make([]Func, ft.Count()) + syms := make([]Sym, len(funcs)) 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):]) - info := t.funcdata[t.uintptr(t.functab[(2*i+1)*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(t.binary.Uint32(info[t.ptrsize+2*4:])) - f.Sym = &Sym{ + f.FrameSize = int(info.deferreturn()) + syms[i] = Sym{ Value: f.Entry, Type: 'T', - Name: t.funcName(t.binary.Uint32(info[t.ptrsize:])), + Name: t.funcName(info.nameoff()), GoType: 0, Func: f, } + f.Sym = &syms[i] } return funcs } -// findFunc returns the func corresponding to the given program counter. -func (t *LineTable) findFunc(pc uint64) []byte { - if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) { - return nil - } - - // 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:]) { - return t.funcdata[t.uintptr(fm[t.ptrsize:]):] - } else if pc < t.uintptr(fm) { - nf = m - } else { - f = f[(m+1)*2*t.ptrsize:] - nf -= m + 1 - } +// findFunc returns the funcData corresponding to the given program counter. +func (t *LineTable) findFunc(pc uint64) funcData { + ft := t.funcTab() + if pc < ft.pc(0) || pc >= ft.pc(ft.Count()) { + return funcData{} } - return nil + idx := sort.Search(int(t.nfunctab), func(i int) bool { + return ft.pc(i) > pc + }) + idx-- + return t.funcData(uint32(idx)) } // readvarint reads, removes, and returns a varint from *pp. @@ -355,6 +373,106 @@ 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 { + if t.version >= ver118 { + return 4 + } + return int(t.ptrsize) +} + +// funcTab returns t's funcTab. +func (t *LineTable) funcTab() funcTab { + 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. +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 { + u := f.uint(f.functab[2*i*f.sz:]) + if f.version >= ver118 { + u += 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.sz:]) +} + +// uint returns the uint stored at b. +func (f funcTab) uint(b []byte) uint64 { + if f.sz == 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 + 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.funcTab().funcOff(int(i)):] + 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 { + // 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)) + f.t.textStart + } + 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") + } + // 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) +} + // 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) @@ -409,7 +527,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 { @@ -436,37 +554,37 @@ 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 recover() != nil { + if !disableRecover && recover() != nil { line = -1 } }() 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)) } -// 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 recover() != nil { + if !disableRecover && recover() != nil { file = "" } }() 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 { @@ -478,17 +596,17 @@ 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) } 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 recover() != nil { + if !disableRecover && recover() != nil { pc = 0 } }() @@ -504,13 +622,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:]) - if t.version == ver116 { - cuoff := t.binary.Uint32(f[t.ptrsize+7*4:]) * 4 - cutab = t.cutab[cuoff:] + f := t.funcData(i) + entry := f.entryPC() + filetab := f.pcfile() + linetab := f.pcln() + if t.version == ver116 || t.version == ver118 { + cutab = t.cutab[f.cuOffset()*4:] } pc := t.findFileLine(entry, filetab, linetab, int32(filenum), int32(line), cutab) if pc != 0 { @@ -550,12 +667,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 diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go index 7347139b5df2bdc1da77f9b57011afe4259e7d47..d690a1e3f2de21a61ede6087ceff17d7dbdbb56d 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() @@ -267,7 +268,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 +278,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 +321,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) + } + } + }) +} diff --git a/src/debug/gosym/symtab.go b/src/debug/gosym/symtab.go index 00701c2875aaace9dac055a40c93ef073556891c..4e63f1cdf705ef1f4d90e2cd52414c326842c43a 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 @@ -710,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/gosym/symtab_test.go b/src/debug/gosym/symtab_test.go index b6ed8f554c517d8773b6fd439365556e10844de1..da3c21209d68f11b2ca1fe0a4b2d3a697062fdd4 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"} diff --git a/src/debug/macho/file.go b/src/debug/macho/file.go index 085b0c8219bad436e5438e3aae5190dc2510583b..b57dba8496bf6978ed382e313c137a9ba96eab24 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 { @@ -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 @@ -641,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 } @@ -653,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/macho/file_test.go b/src/debug/macho/file_test.go index 03915c86e23d9955b00d320be02f0a610140e508..313c376c54a27f9cb9e6f91ba3e9e2f1d5228aa5 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 @@ -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 0000000000000000000000000000000000000000..8e0436639c1096901776c28c755f81cf39233810 --- /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 diff --git a/src/debug/pe/file.go b/src/debug/pe/file.go index e50229e5a3676b8c4e30ad61de9ca3c326fc7c6d..aa0955a1334e841200606aa549703832996e0c46 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) @@ -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 } @@ -444,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 @@ -465,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_cgo_test.go b/src/debug/pe/file_cgo_test.go index 13eb4e62b2ed7687eacd4d0c25be3766b028be80..9280de1a4977c5d6f089c654e9d5ebf49a1d68e8 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/debug/pe/file_test.go b/src/debug/pe/file_test.go index 8964b4f847be6ee4d263adfd77e00beec98121dd..5368e08ad72342e22b220900a73d9c0c316688f0 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 314608da6108331b37adfc190a0d166dfd882662..0c33fa10bb77984b483f23ff8cd3b206dafc47fe 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 { @@ -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() diff --git a/src/embed/embed.go b/src/embed/embed.go index 851cc216fca2eba28e5898486cc4488113df7967..9737ccdf6bb491bee7bfa902d5621b87d92982af 100644 --- a/src/embed/embed.go +++ b/src/embed/embed.go @@ -80,11 +80,15 @@ // 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. -// 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 @@ -228,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 } @@ -292,6 +296,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 { @@ -339,6 +345,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 } diff --git a/src/embed/example_test.go b/src/embed/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5498c275fdf9d3572a87a176958e5d2bf09282bb --- /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) + } +} diff --git a/src/embed/internal/embedtest/embed_test.go b/src/embed/internal/embedtest/embed_test.go index 2d50f5e01f1fafe1975dad2fc43c0fa83720e696..cbd58ee846aa22f8129425e0915f5fda3ca78f61 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") @@ -89,11 +94,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 @@ -129,3 +136,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 any) { + 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) +} diff --git a/src/encoding/ascii85/ascii85.go b/src/encoding/ascii85/ascii85.go index d42eb0ab00a6f970ba2d166dc61ebeb9d9f70413..f1f7af863c33363ec45c17611c5a13252d77f540 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/ascii85/ascii85_test.go b/src/encoding/ascii85/ascii85_test.go index c63710394264331bc6d69b451bf30487764aa66a..9e6b34e9972b4b2a0c211950ad42215561ee0eca 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 cffc06dc9c8689f528203cbdb7251301322aa396..cad1d7b08f8e9a437119c234e89df9a33d444f48 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, "") } @@ -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() @@ -1109,9 +1109,9 @@ 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.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/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go index 8985538468e6b37ce6e9b094e163239dd42386b4..b1e05b96ae39550f9417ec0c25a8a2f558547d54 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/common.go b/src/encoding/asn1/common.go index 1c712e1eff4f05bffa72da895b698a58e3cd3f92..40115df8b4b6aae141b603a360e1af6fb1761179 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/asn1/marshal.go b/src/encoding/asn1/marshal.go index 5b4d786d495576bcf1007e99f11342eb0840bd81..c243349175623d6bb23521078fc6ded40481a8d9 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 f0217ba8a5e25c68cd870a97d94c791dc310aa8a..d9c3cf48fa21c371b91fd5c3cc4814a85c53debf 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.go b/src/encoding/base32/base32.go index 2f7d3637e5a85329e97474310e34c54f25053ead..3feea9ba473f7fd0d82e2e71af22a31767d5d7a7 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/base32/base32_test.go b/src/encoding/base32/base32_test.go index 8fb22b907810e662cc55c2e34ff7fb27ed87ab71..dbd2b613b42aefac03e6545e675a016ed3d98752 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/base32/example_test.go b/src/encoding/base32/example_test.go index 2a302d88da2b4eaea929daa6385f6f64c77da6d3..251624f0bd825438f83ffa600bf9f95e6cec617b 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) diff --git a/src/encoding/base64/base64.go b/src/encoding/base64/base64.go index 0c33f8e5f844348c3ffe35f909de6da83be72ff6..4a3e590649ea95e62dadd92cea0006227f008a4b 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 diff --git a/src/encoding/base64/base64_test.go b/src/encoding/base64/base64_test.go index 51047402bd48b275cac0e6b6b9270754ee8e5b1e..57256a3846acbeb1eb2fa4f27bfda83b9b55fd3c 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/base64/example_test.go b/src/encoding/base64/example_test.go index 73f119ac5e549c945e97bfd0d5144bad22855b0a..61a3adc5adfae14026db29dbba460dc0a9e3eb9c 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) diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go index a31149979da62951f254c871a1f5e411aec4029f..ee933461ee1a1a62b65f4553df897bce706af063 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) @@ -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: @@ -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 83af89e8a7c88bd0459efbf7074f3698b40109a3..9e1b5f12db404fa0ca31a130ef6a82b10bda2ead 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 b994b897ce1b569003c6b0122f58bb0671095e9d..4c10daaf68800b776f06a5a36a60df8707bbc64f 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/csv/fuzz.go b/src/encoding/csv/fuzz.go index a03fa83d8ce3a7a7c2075369e95c0ea6e577b71d..5f5cdfcbf8187e4fe7d17c95bf772975b58e05ab 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/codec_test.go b/src/encoding/gob/codec_test.go index f38e88b638abbc4042d8434f667177f72735afca..1ca9d878eecfc76b9306fa2da279d319886ed268 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 5965fea921f9d30bd098e3d414f48b79a07c91eb..b6d5a3e95c4522e920a389ffd5e9803212d416e4 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 @@ -119,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/decgen.go b/src/encoding/gob/decgen.go index 994be877d935b60be097398cf5d9538509cfffc2..e40816eb869ba92af55dac5da521bc5579f98a39 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/decode.go b/src/encoding/gob/decode.go index d2f6c749b1b6065693cb44940d89e91775f17805..34f302a5cf54d60e6e5cf9d163d4ad8f6f9c7a6b 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())) } @@ -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) @@ -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()) @@ -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) } @@ -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 b476aaac93be537f24ef16c72c208bee6538078d..86f54b41932b794ad6f38276e49e89ebcef2a748 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 } @@ -177,14 +186,14 @@ 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{}) } 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 } @@ -199,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/dump.go b/src/encoding/gob/dump.go index 8c0bbc4ff2e50bbc1f5a891f433b8ada36022f26..f4b1bebfba1dcc0a5506b95f2b449a92f377a09d 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 b562da177dbb34d0b4faf149ced9c1464706946c..e5f68786a0607f66fdaf8ab875ab71546eb7e826 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/gob/encode.go b/src/encoding/gob/encode.go index 8f8f170c1643c14e84b91a2271599bf15c718c9a..548d614f524740c1d490d374185a2c62838e9cee 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 @@ -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 @@ -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) } @@ -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 53e2cace1667457a2ff11f1f5c6a1b3d66830d99..5a80e6c3e827e07f66ba2feca4dccca302cdfae4 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)) } @@ -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/encoder_test.go b/src/encoding/gob/encoder_test.go index 6183646f60c8d39ddbf15896911e3d036848c474..6934841b3af8c2cb24508c29a9bcc708fa7d877c 100644 --- a/src/encoding/gob/encoder_test.go +++ b/src/encoding/gob/encoder_test.go @@ -9,14 +9,16 @@ import ( "encoding/hex" "fmt" "io" + "math" "reflect" + "sort" "strings" "testing" ) // Test basic operations in a safe manner. func TestBasicEncoderDecoder(t *testing.T) { - var values = []interface{}{ + var values = []any{ true, int(123), int8(123), @@ -226,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) @@ -254,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 }, } @@ -270,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) @@ -416,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 } @@ -534,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 { @@ -542,7 +544,7 @@ type NewType0 struct { } type ignoreTest struct { - in, out interface{} + in, out any } var ignoreTests = []ignoreTest{ @@ -557,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) { @@ -619,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 { @@ -633,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) @@ -692,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}, @@ -874,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) @@ -885,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) @@ -925,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 { @@ -957,7 +959,7 @@ func TestNilPointerPanics(t *testing.T) { ) testCases := []struct { - value interface{} + value any mustPanic bool }{ {nilStringPtr, true}, @@ -989,7 +991,7 @@ func TestNilPointerPanics(t *testing.T) { func TestNilPointerInsideInterface(t *testing.T) { var ip *int si := struct { - I interface{} + I any }{ I: ip, } @@ -1047,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{} } @@ -1058,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) @@ -1089,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{ @@ -1152,3 +1154,114 @@ 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) + } +} + +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/encoding/gob/error.go b/src/encoding/gob/error.go index 949333bc0370177b93eaad841b431dd39e5b5e89..3c9515b5ed6df462c9b175c06bb09b4dd0f79935 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 6d2c8db42d0d8925f7b77715715493e1ef44da05..1d5dde22a4eeb50b490b04272a476e11d6d46371 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 3478bd247ed8562c0a0336ca73bd55edc97dd9ad..bdee39c447d5d981253161c7e30ab7d54986d568 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) @@ -279,9 +279,23 @@ 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 { + a[i] = []byte("now is the time") + } + benchmarkDecodeSlice(b, a) +} 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 31c0ef7af1513f462f008a85c485d2549bbcc919..6e2c7242324fa17eb111f3b9057027589cf2a06b 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 } } @@ -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) @@ -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 { @@ -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() @@ -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 934270eedd8a547d5af9a2dc070de0c244d9c03b..f5f8db8bcb4a3db5a9c402bdfe4c39212272f7a3 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"}, @@ -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 { @@ -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 73c7b09fb6f6f75e761046dc14c06fb364c1839f..95609140b0d58ee0cf04a2dc8d1d52c739300469 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 a9917e72c761cd408021d37b712620d14ac2a84f..555df0b7e876ad8e4934a2e3dbde4f2ecde96e38 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. @@ -161,15 +161,15 @@ 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() + ")" } -func (d *decodeState) unmarshal(v interface{}) error { +func (d *decodeState) unmarshal(v any) error { rv := reflect.ValueOf(v) - if rv.Kind() != reflect.Ptr || rv.IsNil() { + 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) @@ -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 @@ -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 } @@ -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 } @@ -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 219e845c7b0b2cf47d6ffc2ca006715edb10e56e..c2c036b60914dde7fc237e8782a07f4bd4904b37 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}, @@ -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 } @@ -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 e473e615a9ed43f5f974853e86b220259c81c091..1f5e3e446a9c9c2d92f21edfd5e84f2cea8e88fb 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 { @@ -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/json/encode_test.go b/src/encoding/json/encode_test.go index 0dad9510952702948d743932aeeaf583d62a0007..0b021f0074991d49f218bbc7b0a0682e1a60f3d2 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 fbecf1b59397bff0ea1028f3d7a80715150cb43b..2261c770c01f274398fc239c9151703174f16437 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 d3fa2d111384152b18e9b804bea4bf429c1548ed..b8f4ff2c1d6023eeca74f0c51738b936a2f67372 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 @@ -12,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 9dc1903e2db24b17d90ab90fb8de930131adb336..dbaa821becc10281ff456eae4cd406e82297d5f0 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 3737516a45065caf94388a183ad6ecb06d1658d0..3474b3e4810deb767194f3ee9545c3cd7efceb3f 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 81f404f4267d0891e85317d78636c49e67d09f0d..6362170d5df229da92b5f1bd6ab6752a41d11285 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 c284f2d9650e3ee7993e1f505166577f21b955d6..0e156d98e9454624e18effd8e2e9817a24bfeb7d 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 bbb4e6a28d24fa719dbbc172cb66c8594a210977..6330efd3c21f9214ad2aa105752695281efa6639 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/json/tags.go b/src/encoding/json/tags.go index c38fd5102f6302deb1e10639dbe4552ee255837e..b490328f4c46e70aa85413ac5a4ee5a0190592e9 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 a7272da5ad3a81575c3930fd405aafb824375004..e7adf88382320d4de57851430f0ea2211f139c5a 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/marshal.go b/src/encoding/xml/marshal.go index d8a04a95a2520fa39b8028dd97f43bef70804aba..6859be04a221ec4ba22a8c6bd6cdf4e2c99ee994 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 @@ -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 } @@ -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} } @@ -599,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 } @@ -793,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 } @@ -942,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 } @@ -1051,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/marshal_test.go b/src/encoding/xml/marshal_test.go index d2e5137afd7c05a7ad0ad1414e227f168ee4bf54..5fdbae7ef0a8bd2cd2e30c8d5b9923863da2041f 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,10 +520,14 @@ type DirectAny struct { type IfaceAny struct { T1 T1 - Any interface{} `xml:",any"` + Any any `xml:",any"` T2 T2 } +type Generic[T any] struct { + X T +} + var ( nameAttr = "Sarah" ageAttr = uint(12) @@ -536,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 @@ -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", @@ -1695,7 +1700,7 @@ type BadAttr struct { } var marshalErrorTests = []struct { - Value interface{} + Value any Err string Kind reflect.Kind }{ @@ -1733,7 +1738,7 @@ var marshalErrorTests = []struct { } var marshalIndentTests = []struct { - Value interface{} + Value any Prefix string Indent string ExpectXML string @@ -1928,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 @@ -2322,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 ef5df3f7f6aecca09302cb07050711d8b79b51da..0701e18625953e0b18abb44caea0ede01c57a51f 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,9 +143,9 @@ 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.Ptr { + if val.Kind() != reflect.Pointer { return errors.New("non-pointer passed to Unmarshal") } return d.unmarshal(val.Elem(), start) @@ -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() @@ -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/read_test.go b/src/encoding/xml/read_test.go index 8c2e70fa22ee68e06956dae82a3fafa1c2b779a1..391fe731a800f5af9d95c030c4d3095231d2eb5e 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/typeinfo.go b/src/encoding/xml/typeinfo.go index 162724ef1a58b02d452a7783a11f523c65c3d6bf..6b399b9a0e67392de2e09b10bdd24806387db4da 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 { @@ -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. @@ -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/encoding/xml/xml.go b/src/encoding/xml/xml.go index c14954df155a64a0ff3ef1126f22376538f4f78a..8a0a9c253ade3994aa4aa35f253057f7fc24643e 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 { @@ -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/errors/wrap.go b/src/errors/wrap.go index 4eb4f9ae378bdbb182d4403edfd725cebbd6dfa6..263ae16b48dc0c599590b31f4e2cd370a2f97dc2 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 @@ -58,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 @@ -74,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") } @@ -92,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 6f66e99c4a20cc7778bc3229697cfbf63fa747a3..eb8314b04bb67b8b88a341962fd84f54b7cdc594 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", @@ -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 +} diff --git a/src/expvar/expvar.go b/src/expvar/expvar.go index 13b5c99b6e536fef7c6c978e5322519243e85c44..8bbf41b151db295a2a7cb7f471e3779615b4f149 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 69b0a76058f8d503e829875d5349e8bdbcc62761..ba95a36066c390135b05bd1ba555069a0efad122 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 885a4c8369663f99b9b492bb65d4e768b66d51f6..4e2af450c5065e6b7ce03feb0724f353a37556d7 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. @@ -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) @@ -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 466a620353310b6d6322c60783aae143f5727a59..4f4daf19e1448b98e13e0f93da7ef4ab65809e40 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 87fb32380946ee6aee54b98fe7c424b32468fa12..a4c65b8f5ee72398d38b6a354bb2f36724f7279a 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 8bc225f5484ae4171e650d52cba6c93db13beadb..1c37c3cb7b3896ef61f980196fd7ededdba7104a 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) @@ -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) @@ -533,12 +533,12 @@ 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 // 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 } @@ -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{} @@ -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 { @@ -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 381577049c0fc9343eaf4b3b29798e6a763d04e3..d38610df35595fedd172662b1c0733393b715231 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. @@ -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 } @@ -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 1cc469ce3610c1411003ac255fc8c51005157449..da0dfd19a2d4f992e0512cd7d0f5a127b709414f 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) @@ -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() @@ -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.mod b/src/go.mod index 379dcf504e5316fe43a502bc12e92411650dd9d6..07d0acf2bde6163f3f68b99518d7e21ae690d0b8 100644 --- a/src/go.mod +++ b/src/go.mod @@ -1,10 +1,13 @@ module std -go 1.17 +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/sys v0.0.0-20210511113859-b0526f3d8744 // indirect - golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f // indirect + golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa + golang.org/x/net v0.0.0-20211209124913-491a49abca63 +) + +require ( + 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 6e869b96f711b2edf6bbbd876a638649313c6b98..cec5bc4d0e15a8e5ab569abacbd00f9bcaf3e42c 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= +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-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= +golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0= diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index 337c87fd797351c344bf3e4b2ea01c20b3235c2e..bc140473d58d2fbc634a70197b34956d447a3e3a 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 } @@ -344,6 +340,15 @@ type ( Rbrack token.Pos // position of "]" } + // An IndexListExpr node represents an expression followed by multiple + // indices. + IndexListExpr 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 @@ -440,6 +445,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") + 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. InterfaceType struct { Interface token.Pos // position of "interface" keyword @@ -479,6 +492,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 *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() } @@ -512,6 +526,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 *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 } @@ -543,6 +558,7 @@ func (*CompositeLit) exprNode() {} func (*ParenExpr) exprNode() {} func (*SelectorExpr) exprNode() {} func (*IndexExpr) exprNode() {} +func (*IndexListExpr) exprNode() {} func (*SliceExpr) exprNode() {} func (*TypeAssertExpr) exprNode() {} func (*CallExpr) exprNode() {} @@ -892,6 +908,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 + 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 + } ) // Pos and End implementations for spec nodes. @@ -968,8 +994,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/ast/ast_notypeparams.go b/src/go/ast/ast_notypeparams.go deleted file mode 100644 index fa132fba85892fca8fa79cc321eff5d75e42150d..0000000000000000000000000000000000000000 --- 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 24fdc5f1317e5f2cd1a6c27be8aac26bc8873273..0000000000000000000000000000000000000000 --- 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/print.go b/src/go/ast/print.go index d86d9ba64b78168f42ff2fdef7e6b1f676e31e07..85e6943928d691ec314ef78bc8843f9b6f209a30 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 @@ -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}) } @@ -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/go/ast/print_test.go b/src/go/ast/print_test.go index 210f1643010c716bae62b262a9797baaf94045a0..6691ccd63a3153e44fa2f9f2423ad0b37345785f 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 c1830b5e4db3075ff6e2a1cf6133a9bb83bb351e..126a27b18cdd97d350eb4eeadfd581dfd12f914e 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 a400c7152a668a3e28e89ef9f18ff90d5357269a..d24a5f0e002fd14a1657e6d1426e7cafafdf0612 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/ast/walk.go b/src/go/ast/walk.go index 9224264e291e2fc8904fc208d94d0915f2e626f4..308662f633b50cec49ec14e355f98c4aa24bbded 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). @@ -114,6 +116,12 @@ func Walk(v Visitor, node Node) { Walk(v, n.X) Walk(v, n.Index) + case *IndexListExpr: + Walk(v, n.X) + for _, index := range n.Indices { + Walk(v, index) + } + case *SliceExpr: Walk(v, n.X) if n.Low != nil { @@ -161,7 +169,9 @@ func Walk(v Visitor, node Node) { Walk(v, n.Fields) case *FuncType: - walkFuncTypeParams(v, n) + if n.TypeParams != nil { + Walk(v, n.TypeParams) + } if n.Params != nil { Walk(v, n.Params) } @@ -316,7 +326,9 @@ func Walk(v Visitor, node Node) { Walk(v, n.Doc) } Walk(v, n.Name) - walkTypeSpecParams(v, n) + if n.TypeParams != nil { + Walk(v, n.TypeParams) + } Walk(v, n.Type) if n.Comment != nil { Walk(v, n.Comment) @@ -363,7 +375,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 d43e13dd11ad76dffeadc38b85f7b0507247877f..0000000000000000000000000000000000000000 --- 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 b6621335b8ec41e18186dc25cee6e561ec35884c..0000000000000000000000000000000000000000 --- 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/build/build.go b/src/go/build/build.go index 8afa9d5240408a6d36df874ca9d5a8fe43bb708f..6f7260b78f37ca490a01892123397ba9f626a63c 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")] } @@ -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 80f930f3c23bef47516580717c8cb729273d93d1..cfe9c5e4bb286b82a944e41929adb72c080bfd2a 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/deps_test.go b/src/go/build/deps_test.go index 45e2f25df74da3444f3256f52ea8ab6cdf23b616..7f25038d2d09da29f507b8c750611033e0cc05ab 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -70,18 +70,20 @@ import ( var depsRules = ` # No dependencies allowed for any of these packages. NONE - < container/list, container/ring, - internal/cfg, internal/cpu, internal/goexperiment, + < constraints, container/list, container/ring, + internal/cfg, internal/cpu, internal/goarch, + internal/goexperiment, internal/goos, internal/goversion, internal/nettrace, 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. - internal/abi, internal/cpu, internal/goexperiment, unsafe + internal/abi, internal/cpu, internal/goarch, + internal/goexperiment, internal/goos, unsafe < internal/bytealg < internal/itoa < internal/unsafeheader @@ -171,7 +173,7 @@ var depsRules = ` io/fs < embed; - unicode, fmt !< os, os/signal; + unicode, fmt !< net, os, os/signal; os/signal, STR < path/filepath @@ -185,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 @@ -212,7 +216,6 @@ var depsRules = ` mime/quotedprintable, net/internal/socktest, net/url, - runtime/debug, runtime/trace, text/scanner, text/tabwriter; @@ -269,8 +272,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. @@ -328,7 +333,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. @@ -349,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 @@ -357,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; @@ -393,7 +407,8 @@ var depsRules = ` < crypto/subtle < crypto/internal/subtle < crypto/elliptic/internal/fiat - < crypto/ed25519/internal/edwards25519/field + < crypto/elliptic/internal/nistec + < 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, @@ -421,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 @@ -508,10 +523,14 @@ 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; - internal/testlog, runtime/pprof, regexp + 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 < testing/internal/testdeps; OS, flag, testing, internal/cfg @@ -526,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; ` @@ -615,7 +637,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 @@ -652,6 +674,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 } diff --git a/src/go/build/gc.go b/src/go/build/gc.go index e16e186e0df9662ee420c51d2ad41eaced1f6a31..434991f66ef80163b2a467a59939ab2f9dbed88a 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 c8ec7041fb3653cd71ce0799925851303fd50868..f806729f7e0e283f3e75ca89e251ab03f29a28ab 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/build/read.go b/src/go/build/read.go index b98c7938a855993454b5e374ff99d9b9ebd04b95..de5c33a4f849ce337fabc3a62920ba36fb552563 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 { @@ -516,12 +537,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 1e5e1c2de2e6d110b539058fe64711c97547ee89..6851e6b6d6003eec431616fdf20ddf2968d6bf18 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/build/syslist.go b/src/go/build/syslist.go index 60ac5511bda72f1cbd1cb47f764300f87450298a..0f6e3369253ff2a84e6f5607ee3d4ef50f46d94f 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/go/constant/kind_string.go b/src/go/constant/kind_string.go new file mode 100644 index 0000000000000000000000000000000000000000..700332511d8b7c2e4af13609a171f21974e72dbd --- /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 78cb3f896f535cd7fddd64a2f2b34e03f1ec81dd..dee3bce9eef412beda43ba232db4aa2261138953 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 @@ -577,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) @@ -608,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 91ad0b0c2b9d998a2a28feb2827d8b118cb56124..e41315ee27c7164d2134f8e28490bd218bd5a812 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) } @@ -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/comment.go b/src/go/doc/comment.go index 92131a3b83f02700cb4b48d21d2ed3947056c082..a93c05fbb7e315494f229b7014bd270fd9e1b4b2 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/doc.go b/src/go/doc/doc.go index 79d38998e7b51164eb427dfa819049584947837f..5ab854d084b66f2ec45b87c70c72bef12ab9365d 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 cbdca62aa1d113bc76b0ab5d57367dc4edc804a2..3d17036f01f69da1af42b1b4e63b4127f78f6dca 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/example.go b/src/go/doc/example.go index 274000cecb7a4b194193cbe2f87e7a1d5753f867..0a880cdefb617462b49ca7262af681caa72f955a 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 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 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 { @@ -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 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 { if !strings.HasPrefix(name, prefix) { return false diff --git a/src/go/doc/example_test.go b/src/go/doc/example_test.go index cf1b702549e5242e57d60e4998873c558d5fed72..21b71290f7d4e64ed0e9c9423932ea3e2c3d6eb6 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/go/doc/exports.go b/src/go/doc/exports.go index 819c030c9bf51c9f7f36f50a20688df98bd04c14..671c622205b2d4d96127421a2cf7bb7b17d9784e 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 a6f243f33e5825e07f99cef220b185a7ae19ebf8..9904da150e96ac4052794fb6c16124633a9160dc 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/headscan.go b/src/go/doc/headscan.go index 28cb84f91da8f0436684072703ad84c5ce231210..320895e43a4c576797a2ac53f7b1ca7be69cf170 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; @@ -23,10 +22,10 @@ import ( "go/doc" "go/parser" "go/token" - "internal/lazyregexp" "io/fs" "os" "path/filepath" + "regexp" "runtime" "strings" ) @@ -37,7 +36,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 +48,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/doc/reader.go b/src/go/doc/reader.go index c277b35e89420acfe14bd95ee5a6af7393e91ded..7ff868f0627cc8927f05b04571f94048b3231e82 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 { @@ -418,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++ @@ -439,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 @@ -679,10 +707,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 +898,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/benchmark.go b/src/go/doc/testdata/benchmark.go index 1d581f057e619a8d340f487d8a40442161a3c1e1..d27bf116aafa902a46cfbf55729760f158f028e6 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/generics.0.golden b/src/go/doc/testdata/generics.0.golden new file mode 100644 index 0000000000000000000000000000000000000000..91c874c84d69eb58329bd144453864c0f7b44b90 --- /dev/null +++ b/src/go/doc/testdata/generics.0.golden @@ -0,0 +1,76 @@ +// 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]]]() + + // 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 ... + 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 0000000000000000000000000000000000000000..923a4ce5d9ae65cdf5c361cca40669e6fdcfa886 --- /dev/null +++ b/src/go/doc/testdata/generics.1.golden @@ -0,0 +1,66 @@ +// 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]]]() + + // 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 ... + 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 0000000000000000000000000000000000000000..91c874c84d69eb58329bd144453864c0f7b44b90 --- /dev/null +++ b/src/go/doc/testdata/generics.2.golden @@ -0,0 +1,76 @@ +// 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]]]() + + // 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 ... + 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 0000000000000000000000000000000000000000..ba7187e4dd9f9d8f4dc04b401be57b474ad5d878 --- /dev/null +++ b/src/go/doc/testdata/generics.go @@ -0,0 +1,74 @@ +// Copyright 2021 The Go Authors. 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 }) + +// 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 +} diff --git a/src/go/doc/testdata/testing.0.golden b/src/go/doc/testdata/testing.0.golden index 83cf37cd3a9c3d90dcd77b089dfc498cd1eef8cb..61dac8bb66ca5937e374e1cb14ae8083e66f1561 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 b9d14517a9cfebd00d5292ebabfcf39ddaa6a794..1655af11a8cddb7487058e753148908ae9f867c2 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 83cf37cd3a9c3d90dcd77b089dfc498cd1eef8cb..61dac8bb66ca5937e374e1cb14ae8083e66f1561 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 52810f7a564c17389dd6e5f30404dc517ba8d967..80238df283a7eb35eeeae817a29c1043717e2f0d 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 a603d9630e6794bc2d62f190ae29bdf9487128c2..ea8dd208238cc2571adcf9505f88f641e793af69 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/importer/importer_test.go b/src/go/importer/importer_test.go index 0f5121d80212bd57e9f18ad94f995a69a1cf733d..27c4aa787173d82e2027a812493a70a06d02e32c 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/internal/gccgoimporter/parser.go b/src/go/internal/gccgoimporter/parser.go index 1b1d07d3f6ed57da2ccbc9edd570064f5be7d101..48335fa6d8fdbd034cfb20156d12e641e699f596 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) @@ -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)) } } @@ -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,14 +759,14 @@ 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) 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 } @@ -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/gccgoimporter/testdata/escapeinfo.gox b/src/go/internal/gccgoimporter/testdata/escapeinfo.gox index 1db81562c1d74a34f1739fd1bf1ac5dd269502d8..94ce0393fc0353bc2647ff1e3babc16c50d848cb 100644 Binary files a/src/go/internal/gccgoimporter/testdata/escapeinfo.gox and b/src/go/internal/gccgoimporter/testdata/escapeinfo.gox differ diff --git a/src/go/internal/gccgoimporter/testdata/time.gox b/src/go/internal/gccgoimporter/testdata/time.gox index 80c2dbcb472813d114032c583c85134a8f340590..a6822ea19859bef114e34b24b05ddca7c8966833 100644 Binary files a/src/go/internal/gccgoimporter/testdata/time.gox and b/src/go/internal/gccgoimporter/testdata/time.gox differ diff --git a/src/go/internal/gccgoimporter/testdata/unicode.gox b/src/go/internal/gccgoimporter/testdata/unicode.gox index e70e539655e9f00af598bffa62f987c77cd96009..ae1a6f758b4d807567569126b1fe2df57a3152cb 100644 Binary files a/src/go/internal/gccgoimporter/testdata/unicode.gox and b/src/go/internal/gccgoimporter/testdata/unicode.gox differ diff --git a/src/go/internal/gccgoimporter/testdata/v1reflect.gox b/src/go/internal/gccgoimporter/testdata/v1reflect.gox index ea468414d9fa8ad66e978799a8ff5d2f90eb4961..d693fe631b53ee3ac530c76d6ce35782421db9a0 100644 Binary files a/src/go/internal/gccgoimporter/testdata/v1reflect.gox and b/src/go/internal/gccgoimporter/testdata/v1reflect.gox differ diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 3c76aafde39947ef49d9e42dd8107b5d753c210b..15a7b176bb7926d4369923e02b7528e6a08f9c59 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) @@ -110,28 +118,152 @@ func TestImportTestdata(t *testing.T) { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) } + testfiles := map[string][]string{ + "exports.go": {"go/ast", "go/token"}, + } + if !goexperiment.Unified { + testfiles["generics.go"] = nil + } + + 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) + } + } + } + } +} + +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) - 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) + // 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 && 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) { @@ -258,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/iimport.go b/src/go/internal/gcimporter/iimport.go index 76d47d08f1f88a9a11a4761604aba4d753d5fe5f..c5b89aa042a746ce154fc91465e5b2b590a8c69f 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 { @@ -41,6 +42,21 @@ func (r *intReader) uint64() uint64 { return i } +// Keep this in sync with constants in iexport.go. +const ( + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + iexportVersionGenerics = 2 + iexportVersionGo1_18 = 2 + + iexportVersionCurrent = 2 +) + +type ident struct { + pkg string + name string +} + const predeclReserved = 32 type itag uint64 @@ -56,6 +72,9 @@ const ( signatureType structType interfaceType + typeParamType + instanceType + unionType ) // iImportData imports a package from the serialized package data @@ -63,7 +82,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, dataReader *bufio.Reader, path string) (pkg *types.Package, err error) { - const currentVersion = 1 + const currentVersion = iexportVersionCurrent version := int64(-1) defer func() { if e := recover(); e != nil { @@ -79,7 +98,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea version = int64(r.uint64()) switch version { - case currentVersion, 0: + case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: default: errorf("unknown iexport format version %d", version) } @@ -95,8 +114,9 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea declData := data[sLen:] p := iimporter{ - ipath: path, - version: int(version), + exportVersion: version, + ipath: path, + version: int(version), stringData: stringData, stringCache: make(map[uint64]string), @@ -105,12 +125,16 @@ 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, - 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 @@ -172,16 +196,18 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea } type iimporter struct { - ipath string - version int + exportVersion int64 + ipath string + version int stringData []byte 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 @@ -229,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 } @@ -241,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 @@ -271,17 +315,26 @@ func (r *importReader) obj(name string) { r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) - case 'F': - sig := r.signature(nil) - + case 'F', 'G': + var tparams []*types.TypeParam + if tag == 'G' { + tparams = r.tparamList() + } + sig := r.signature(nil, nil, tparams) r.declare(types.NewFunc(pos, r.currPkg, name, sig)) - case 'T': + case 'T', 'U': // 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) + // 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) @@ -291,12 +344,57 @@ 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(recv.Type()).TypeArgs() + var rparams []*types.TypeParam + if targs.Len() > 0 { + rparams = make([]*types.TypeParam, targs.Len()) + for i := range rparams { + rparams[i], _ = targs.At(i).(*types.TypeParam) + } + } + msig := r.signature(recv, rparams, nil) named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) } } + 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") + } + // 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") + } + 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} + r.p.tparamIndex[id] = t + + 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() @@ -313,6 +411,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: @@ -502,7 +604,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() @@ -542,13 +644,56 @@ 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) } typ := types.NewInterfaceType(methods, embeddeds) r.p.interfaceList = append(r.p.interfaceList, typ) return typ + + case typeParamType: + 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 instanceType: + 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 *Context + 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) } } @@ -556,11 +701,23 @@ 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 { + 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 { @@ -605,3 +762,13 @@ 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 +} diff --git a/src/go/internal/gcimporter/support.go b/src/go/internal/gcimporter/support.go index b8bb14dc490e2a1a47e24adc60be69304e7414a3..61d1b46a680361724a9b8d14b2bae1ffc3886ef6 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...)) } @@ -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 ( @@ -121,7 +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/internal/gcimporter/testdata/exports.go b/src/go/internal/gcimporter/testdata/exports.go index 8ba3242102779d2917640f48f9178a75f503ff3b..3d5a8c9e39fe13507ae3061f4bf778337c825fb5 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 ( @@ -47,7 +50,7 @@ type ( _ *T10 } T11 map[int]string - T12 interface{} + T12 any T13 interface { m1() m2(int) float32 @@ -62,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 } @@ -83,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/internal/gcimporter/testdata/generics.go b/src/go/internal/gcimporter/testdata/generics.go new file mode 100644 index 0000000000000000000000000000000000000000..00bf04000fa06c717f8bad1ab238dd83a8047ebe --- /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 diff --git a/src/go/internal/typeparams/common.go b/src/go/internal/typeparams/common.go index 47b8f7cf02f30dc9d09f4d10bfab082ddd4f1b17..9b82e6061a5509e161ddde04ce0f2b969b6d2ba3 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/internal/typeparams/notypeparams.go b/src/go/internal/typeparams/notypeparams.go deleted file mode 100644 index 2ceafaac1c356d95958c92b727f7756fb858d044..0000000000000000000000000000000000000000 --- 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 871e95d9984d7ad8bc54b01464233609323d65f6..3f84f2f0d05afd28b9d10b8b146e09deee2ef505 100644 --- a/src/go/internal/typeparams/typeparams.go +++ b/src/go/internal/typeparams/typeparams.go @@ -2,68 +2,53 @@ // 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 ( - "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.IndexListExpr{ + 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 -} - -func IsListExpr(n ast.Node) bool { - _, ok := n.(*ast.ListExpr) - return ok +// 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 the IndexListExpr below. + *ast.IndexListExpr } -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)) +func UnpackIndexExpr(n ast.Node) *IndexExpr { + switch e := n.(type) { + case *ast.IndexExpr: + return &IndexExpr{e, &ast.IndexListExpr{ + X: e.X, + Lbrack: e.Lbrack, + Indices: []ast.Expr{e.Index}, + Rbrack: e.Rbrack, + }} + case *ast.IndexListExpr: + return &IndexExpr{e, e} } + return nil } diff --git a/src/go/parser/error_test.go b/src/go/parser/error_test.go index f4f0a5240ac801e71ce64c7e868025afb97780b4..bedfc265b58f53e16b063adc5fd939297f2e50cf 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 @@ -151,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 { @@ -186,16 +189,17 @@ 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") { + mode |= typeparams.DisallowParsing } - } else { - mode |= typeparams.DisallowParsing + if *traceErrs { + mode |= Trace + } + checkErrors(t, filepath.Join(testdata, name), nil, mode, true) } - checkErrors(t, filepath.Join(testdata, name), nil, mode, true) - } + }) } } diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go index 85486d2f4b465ddd7638bdb10f691e215788c1a8..e4f8c281ea734e80feac4111581fb6a72f7f9c5f 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 f10c8650afd0bf15461f712a8694e03bd02f7ab3..e456e2930e3fa2a06b26538af22035b8ea8aa5bb 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -76,14 +76,13 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mod p.next() } -func (p *parser) parseTypeParams() bool { - return typeparams.Enabled && 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 -func (p *parser) printTrace(a ...interface{}) { +func (p *parser) printTrace(a ...any) { const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " const n = len(dots) pos := p.file.Position(p.pos) @@ -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) } @@ -526,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) { @@ -558,7 +561,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,19 +591,19 @@ 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()} } // 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 { @@ -711,8 +714,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 +724,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 +744,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 +777,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 +816,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 +854,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 +870,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 +922,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 +940,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 +995,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,21 +1004,26 @@ 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. _, 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, + TypeParams: tparams, + Params: params, + Results: results, + } } else { // embedded instantiated type // TODO(rfindley) should resolve all identifiers in x. 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) { @@ -990,7 +1034,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 @@ -1006,16 +1050,60 @@ 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) } } - 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(x ast.Expr) ast.Expr { + if p.trace { + defer un(trace(p, "EmbeddedElem")) + } + 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 = x + t.Y = p.embeddedTerm() + x = t + } + return x +} + +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 { @@ -1025,22 +1113,39 @@ 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 { - // 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}) + +parseElements: + for { + switch { + case p.tok == token.IDENT: + f := p.parseMethodSpec() + 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.allowGenerics(): + typ := p.embeddedElem(nil) + p.expectSemi() + comment := p.lineComment + list = append(list, &ast.Field{Type: typ, Comment: comment}) + case p.allowGenerics(): + if t := p.tryIdentOrType(); t != nil { + typ := p.embeddedElem(t) + p.expectSemi() + comment := p.lineComment + list = append(list, &ast.Field{Type: typ, Comment: comment}) + } 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) @@ -1095,13 +1200,12 @@ 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")) } opening := p.expect(token.LBRACK) - p.exprLev++ var list []ast.Expr for p.tok != token.RBRACK && p.tok != token.EOF { @@ -1115,23 +1219,30 @@ 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 { 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 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: @@ -1372,13 +1483,13 @@ 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()} } // 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 { @@ -1480,6 +1591,7 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr { panic("unreachable") case *ast.SelectorExpr: case *ast.IndexExpr: + case *ast.IndexListExpr: case *ast.SliceExpr: case *ast.TypeAssertExpr: // If t.Type == nil we have a type assertion of the form @@ -1525,12 +1637,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: @@ -1566,18 +1680,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: + 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") @@ -1585,7 +1699,7 @@ func (p *parser) parsePrimaryExpr() (x ast.Expr) { } x = p.parseLiteralValue(x) default: - return + return x } } } @@ -1656,7 +1770,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) { @@ -1667,19 +1781,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)} } } @@ -1692,7 +1808,7 @@ func (p *parser) parseExpr() ast.Expr { defer un(trace(p, "Expression")) } - return p.parseBinaryExpr(token.LowestPrec + 1) + return p.parseBinaryExpr(nil, token.LowestPrec+1) } func (p *parser) parseRhs() ast.Expr { @@ -2415,13 +2531,19 @@ 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) - typeparams.Set(spec, &ast.FieldList{Opening: openPos, List: list, Closing: closePos}) - // Type alias cannot have type parameters. Accept them for robustness but complain. +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} + // 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() @@ -2435,34 +2557,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 [T any] - p.exprLev++ - x := p.parseExpr() - p.exprLev-- - if name0, _ := x.(*ast.Ident); p.parseTypeParams() && name0 != nil && p.tok != token.RBRACK { + // array type or generic type: [name0... + name0 := p.parseIdent() + + // 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.parseBinaryExpr(lhs, token.LowestPrec+1) + p.exprLev-- + if x == name0 && p.tok != token.RBRACK { + x = nil + } + } + + if x == nil { // 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. - p.expect(token.RBRACK) - elt := p.parseType() - spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: x, Elt: elt} + 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 @@ -2528,10 +2658,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 @@ -2539,7 +2670,7 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { body = p.parseBody() p.expectSemi() } - } else { + default: p.expectSemi() } @@ -2548,13 +2679,13 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { Recv: recv, Name: ident, Type: &ast.FuncType{ - Func: pos, - Params: params, - Results: results, + Func: pos, + TypeParams: 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 cf92c7e4f571ef089e4992a29af0805281a61e41..910ca0689c7ec48b0eb6240c111e7e2be9dc8312 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" ) @@ -68,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: @@ -116,14 +115,8 @@ 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 { - // "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 @@ -189,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 { @@ -455,10 +447,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.TypeParams != nil { r.openScope(spec.Pos()) defer r.closeScope() - r.walkTParams(tparams) + r.walkTParams(spec.TypeParams) } ast.Walk(r, spec.Type) } @@ -474,8 +466,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.TypeParams != nil { + r.walkTParams(n.Type.TypeParams) // TODO(rFindley): need to address receiver type parameters. } @@ -500,7 +492,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) @@ -539,9 +531,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/parser/resolver_test.go b/src/go/parser/resolver_test.go index 625c009c914d8342eebcbfbe2649f2ed786ac44d..0c06c592d5fea1e91785163ac186840f49d5c6ae 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 67fef15665583db4e4a1ba7aad93a081b8c9bfc9..90a4ec9ecd0473d3806f183cf0805b455216ec5d 100644 --- a/src/go/parser/short_test.go +++ b/src/go/parser/short_test.go @@ -119,11 +119,11 @@ 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]() }`, + `package p; type T[P any /* ERROR "expected ']'" */ ] = T0`, } func TestValid(t *testing.T) { @@ -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) } @@ -200,10 +197,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)`, @@ -242,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" */()`, @@ -266,9 +264,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/parser/testdata/interface.go2 b/src/go/parser/testdata/interface.go2 new file mode 100644 index 0000000000000000000000000000000000000000..2ed9339c5204d6525b57bf9961bef8ae954c2d99 --- /dev/null +++ b/src/go/parser/testdata/interface.go2 @@ -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. + +// This file contains test cases for interfaces containing +// constraint elements. + +package p + +type _ interface { + m() + ~int + ~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 _ 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 +} diff --git a/src/go/parser/testdata/issue49174.go2 b/src/go/parser/testdata/issue49174.go2 new file mode 100644 index 0000000000000000000000000000000000000000..77c195083ff044d0c383a4c994a9d2488887d0da --- /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 0000000000000000000000000000000000000000..a5ad30f14c8e2f1b52b25a4d91adc21e9e6741be --- /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 diff --git a/src/go/parser/testdata/linalg.go2 b/src/go/parser/testdata/linalg.go2 index fba0d02eb2fe045370515aaed3b35e0cf8709594..7ccb19c08d3f1ff9dfde94113b618a6c3c627197 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 0ffecd69b5b8a49985b57de39b340d335e865201..8c243afda7eb396dca137458f74a44ce7f2d66ab 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/parser/testdata/typeset.go2 b/src/go/parser/testdata/typeset.go2 new file mode 100644 index 0000000000000000000000000000000000000000..aa18e8ccff05ac07b37af58f6086007fb910a1e8 --- /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/nodes.go b/src/go/printer/nodes.go index 913281ea6c14b7b13ef6e95f9233a1c808e518b1..19d4ab6663d3d0f067a33cef99a375995d2dcfe9 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.TypeParams != nil { + p.parameters(sig.TypeParams, true) } if sig.Params != nil { p.parameters(sig.Params, false) @@ -472,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) @@ -569,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) @@ -871,17 +848,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.IndexListExpr: + // 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: @@ -1052,7 +1027,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" @@ -1635,8 +1610,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.TypeParams != nil { + p.parameters(s.TypeParams, true) } if n == 1 { p.print(blank) diff --git a/src/go/printer/printer.go b/src/go/printer/printer.go index ba61f782267ad8ed27ab5b2252f06bdf70cc5252..e4679b0021d91e8edce40b0731c05257b43a8425 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...) @@ -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 @@ -881,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 @@ -1078,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 { @@ -1312,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) @@ -1368,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 } @@ -1377,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)) } @@ -1386,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/printer_test.go b/src/go/printer/printer_test.go index 20c97b8c08173065e23a2be9795b90beb904201f..ff8be4ae97a75ff5a1f1b645009ca13858188caa 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/printer/testdata/generics.golden b/src/go/printer/testdata/generics.golden index cc7fbbe1d8360403db9181d0303e7df12a18780b..3d95eda5b2ac4a56ce79d7837f0766e42d3fe6e0 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,9 +35,6 @@ func _() { _ = []T[P]{} } -// properly format one-line 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 f4571ad33693cb260dd3c0afb4420eba1ac11cf4..746dfdd2358ba987efc0847035ad6f759151e07f 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,7 +32,6 @@ func _() { _ = []T[P]{} } -// properly format one-line 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/parser.go b/src/go/printer/testdata/parser.go index fc2812adee0c3f6eaa2b363f3d2eeecb3248f50a..7e8379739c6dc88469fff323bfe095d6b14ba7bd 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 f08e28cdd6b72b35da5b669a0592b88c6e012c53..23d8db9d1ccdf76a1f45fff6bd586d74bf78bc68 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...)) } @@ -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 db123c32e01d59e9d46fa6429efcefb9fc60bdff..de45e16606052ac6af07fe4b01868d5819685331 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/position.go b/src/go/token/position.go index 0d7982c67059374be2c291fd3bd312b7a3e950d8..ce4af039237ce6f3cb12005e8f34fe8430ad04a5 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 diff --git a/src/go/token/serialize.go b/src/go/token/serialize.go index d0ea34517a442fd25ac11751179147d1ea6fd074..ffb69908b91f2c679a60ecc198593c10d52ed6c0 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 4e925adb6f26406df05ae62582ab866e1b95c8be..4aa0b0da2600fce8093e15e069aec183d0f18c1c 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/token/token.go b/src/go/token/token.go index 96a1079ec37c4668969721700df0a682087c00f9..d22e575661a2df95726266b65c512fbdda7c5838 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. diff --git a/src/go/types/api.go b/src/go/types/api.go index 8c0d9d22bf26aa671f6bf65c7676dc2bf806a78a..c4d81c1491e526b73bee1341f826428048145aa5 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 @@ -60,6 +62,15 @@ 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 + Err error +} + +func (e *ArgumentError) Error() string { return e.Err.Error() } +func (e *ArgumentError) Unwrap() error { return e.Err } + // An Importer resolves import paths to Packages. // // CAUTION: This interface does not support the import of locally @@ -101,12 +112,16 @@ 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 + // 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 // 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. @@ -160,7 +175,115 @@ func srcimporter_setUsesCgo(conf *Config) { conf.go115UsesCgo = true } -// The Info struct is found in api_notypeparams.go and api_typeparams.go. +// 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. + // + // 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 + // 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). + // 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 +} // TypeOf returns the type of expression e, or nil if not found. // Precondition: the Types, Uses and Defs maps are populated. @@ -252,11 +375,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 []Type - 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 @@ -317,18 +442,26 @@ 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. // 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/api_notypeparams.go b/src/go/types/api_notypeparams.go deleted file mode 100644 index 9f7cb7eccf266ef78b7df7375ba21f0525f82b0d..0000000000000000000000000000000000000000 --- 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_test.go b/src/go/types/api_test.go index f964c656f93f9dc97cfdf3ae8ac4e80c93aaced5..1ee9806fd0ad3852a31c66a4280f5994603fdc89 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" @@ -27,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 @@ -152,6 +157,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< 0 { - check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context) + if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { + 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 @@ -84,10 +85,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 } @@ -229,14 +238,89 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { return x.typ } -// 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()) +// 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) + 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 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 for _, obj := range lhs { + obj.used = true // avoid declared but not used errors if obj.typ == nil { obj.typ = Typ[Invalid] } @@ -247,16 +331,32 @@ 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 } - 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 } context := "assignment" - if returnPos.IsValid() { + if returnStmt != nil { context = "return statement" } @@ -285,7 +385,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 } @@ -364,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/basic.go b/src/go/types/basic.go new file mode 100644 index 0000000000000000000000000000000000000000..215923f6573a560f422a2201b5330d6fe853094b --- /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/builtins.go b/src/go/types/builtins.go index 2a2d54da88227a60bcb6f5c3dfbf019db61faed4..828220f257a934ad1d685d7622e5632a5195431a 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 { @@ -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, _ := structuralType(S).(*Slice); s != nil { T = s.elem } else { check.invalidArg(x, _InvalidAppend, "%s is not a slice", x) @@ -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 @@ -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 @@ -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 = arrayPtrDeref(under(x.typ)); t := typ.(type) { case *Basic: if isString(t) && id == _Len { if x.mode == constant_ { @@ -179,9 +179,12 @@ 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 *Interface: + if !isTypeParam(x.typ) { + break + } + if t.typeSet().underIs(func(t Type) bool { + switch t := arrayPtrDeref(t).(type) { case *Basic: if isString(t) && id == _Len { return true @@ -217,19 +220,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: @@ -286,14 +293,16 @@ 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 } // 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(!isTypeParam(typ)) + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -326,33 +335,26 @@ 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, _ := structuralType(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 + 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) return } - if !check.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 } @@ -363,25 +365,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, _InvalidDelete, "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: @@ -410,8 +427,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(!isTypeParam(typ)) + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -460,39 +479,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 := optype(t).(type) { - case *Slice: - m = 2 - case *Map, *Chan: - m = 1 - case *_Sum: - return t.is(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 structuralType(T).(type) { + case *Slice: + min = 2 + case *Map, *Chan: + min = 1 + case nil: + 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) 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 } @@ -612,19 +613,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 @@ -644,7 +648,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) @@ -662,30 +666,52 @@ 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) + // 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- + // 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 @@ -694,7 +720,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 @@ -744,7 +770,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 } @@ -757,6 +783,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 u := under(t).(type) { + case *Array: + return hasVarSize(u.elem) + case *Struct: + for _, f := range u.fields { + if hasVarSize(f.typ) { + return true + } + } + case *Interface: + return isTypeParam(t) + case *Named, *Union: + 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 @@ -765,13 +810,16 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // 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 rtypes []Type - if !tp.Bound().is(func(x Type) bool { - if r := f(x); r != nil { - rtypes = append(rtypes, r) + var terms []*Term + 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 } return false @@ -779,11 +827,12 @@ 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 - tsum := _NewSum(rtypes) - ptyp.bound = &Interface{types: tsum, allMethods: markComplete, allTypes: tsum} + // 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 + ptyp.index = tp.index return ptyp } @@ -807,12 +856,11 @@ 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 { + if a, _ := under(p.base).(*Array); a != nil { return a } } diff --git a/src/go/types/builtins_test.go b/src/go/types/builtins_test.go index 11de9a1ac1a45d17bba26ed2f41bdb7499015858..edcd7e7724a1aaf12802594ed6a8b29985eef771 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) 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) 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) 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/call.go b/src/go/types/call.go index 631ea426c6bbf42e5fe613e4936942a2e253d055..4156d56d9ff8dd3c9a10b85f811321079c26454c 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -16,76 +16,98 @@ 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) { + if !check.allowVersion(check.pkg, 1, 18) { + check.softErrorf(inNode(ix.Orig, ix.Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later") + } + + 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) + got, want := len(targs), sig.TypeParams().Len() if got > want { - check.errorf(xlist[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 = inst + x.expr = ix.Orig return } - // if we don't have enough type arguments, try type inference - inferred := false - if got < want { - targs = check.infer(inst, sig.tparams, 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 - x.expr = inst + x.expr = ix.Orig return } got = len(targs) - inferred = true } 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(xlist)) - for i, x := range xlist { - poslist[i] = x.Pos() - } - // instantiate function signature - 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) - } + 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 x.mode = value - x.expr = inst + x.expr = ix.Orig +} + +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()) + + 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.bestContext(nil)).(*Signature) + 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(xlist) { + pos = xlist[i].Pos() + } + check.softErrorf(atPos(pos), _InvalidTypeArg, "%s", err) + } else { + check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist) + } + + return inst } 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) + check.exprOrType(x, call.Fun, true) } + // x.typ may be generic switch x.mode { case invalid: @@ -95,6 +117,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 { @@ -107,10 +133,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 { - check.completeInterface(token.NoPos, t) - if t._IsConstraint() { - check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T) + 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 } } @@ -124,6 +149,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 @@ -137,9 +163,11 @@ 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) + // a type parameter may be "called" if all types have the same signature + sig, _ := structuralType(x.typ).(*Signature) if sig == nil { check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) x.mode = invalid @@ -148,9 +176,10 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { } // evaluate type arguments, if any + var xlist []ast.Expr var targs []Type - if inst != nil { - xlist := typeparams.UnpackExpr(inst.Index) + if ix != nil { + xlist = ix.Indices targs = check.typeList(xlist) if targs == nil { check.use(call.Args...) @@ -161,9 +190,9 @@ func (check *Checker) callExpr(x *operand, call *ast.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.TypeParams().Len() if got > want { - check.errorf(xlist[want], _Todo, "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 @@ -173,7 +202,13 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // evaluate arguments args, _ := check.exprList(call.Args, false) - sig = check.arguments(call, sig, targs, args) + isGeneric := sig.TypeParams().Len() > 0 + 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. + check.recordTypeAndValue(call.Fun, value, sig, nil) + } // determine result switch sig.results.Len() { @@ -195,7 +230,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.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ) { x.mode = invalid } @@ -224,7 +259,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 @@ -246,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 @@ -315,42 +350,65 @@ 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 } // infer type arguments and instantiate signature if necessary - if len(sig.tparams) > 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) + if sig.TypeParams().Len() > 0 { + if !check.allowVersion(check.pkg, 1, 18) { + switch call.Fun.(type) { + case *ast.IndexExpr, *ast.IndexListExpr: + ix := typeparams.UnpackIndexExpr(call.Fun) + check.softErrorf(inNode(call.Fun, ix.Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later") + default: + check.softErrorf(inNode(call, call.Lparen), _UnsupportedFeature, "implicit function instantiation requires go1.18 or later") + } + } + targs := check.infer(call, sig.TypeParams().list(), targs, sigParams, args) if targs == nil { return // error already reported } // compute result signature - rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) - assert(rsig.tparams == nil) // signature is not generic anymore - check.recordInferred(call, targs, rsig) + rsig = check.instantiateSignature(call.Pos(), sig, targs, xlist) + assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore + 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 // 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.TypeParams().list(), targs), nil).(*Tuple) } else { sigParams = rsig.params } } // 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 @@ -464,14 +522,12 @@ 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 } - 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: @@ -481,13 +537,12 @@ 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". - switch obj := tpar.Bound().obj.(type) { - case 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) - 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) @@ -501,7 +556,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 } } @@ -514,54 +569,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 len(sig.rparams) > 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.rparams, 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.rparams, targs)) - 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 { @@ -575,17 +582,37 @@ 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. 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, - params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "_", x.typ)}, params...)...), + params: NewTuple(params...), results: sig.results, variadic: sig.variadic, } @@ -687,7 +714,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) } } } @@ -719,17 +746,9 @@ 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 } } } - -// 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/chan.go b/src/go/types/chan.go new file mode 100644 index 0000000000000000000000000000000000000000..1f7b72be309c868c450151bdbf7100e70244f884 --- /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/check.go b/src/go/types/check.go index a923c3c612124f21f6baa59cec4967ee5084a271..2dd38e2e1e406cd94b40b01151bb6d2b04914bfa 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 @@ -41,22 +45,24 @@ 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) 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 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 } @@ -73,7 +79,29 @@ type importKey struct { // A dotImportKey describes a dot-imported object in the given scope. type dotImportKey struct { scope *Scope - obj Object + 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 ...any) { + 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 []any } // A Checker maintains the state of the type checker. @@ -82,14 +110,14 @@ 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 - version version // accepted language version - 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 // 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 @@ -104,19 +132,22 @@ 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 + 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 + 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 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. - // 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 @@ -147,8 +178,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. @@ -179,21 +214,20 @@ 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{ conf: conf, + ctxt: conf.Context, fset: fset, pkg: pkg, Info: info, version: version, objMap: make(map[Object]*declInfo), impMap: make(map[importKey]*Package), - posMap: make(map[*Interface][]token.Pos), - typMap: make(map[string]*Named), } } @@ -266,6 +300,8 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.processDelayed(0) // incl. all functions + check.expandDefTypes() + check.initOrder() if !check.conf.DisableUnusedImportCheck { @@ -274,8 +310,9 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.recordUntyped() - if check.Info != nil { - sanitizeInfo(check.Info) + if check.firstErr == nil { + // TODO(mdempsky): Ensure monomorph is safe when errors exist. + check.monomorph() } check.pkg.complete = true @@ -285,6 +322,9 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.dotImportMap = nil check.pkgPathMap = nil check.seenPkgMap = nil + check.recvTParamMap = nil + check.defTypes = nil + check.ctxt = nil // TODO(rFindley) There's more memory we should release at this point. @@ -300,12 +340,40 @@ 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] } +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 @@ -355,9 +423,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} @@ -408,12 +476,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 := getInferred(check.Info); m != nil { - m[call] = _Inferred{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/check_test.go b/src/go/types/check_test.go index f83abf11ce2e22623cb1ff266ec0b2c4a2f6557f..e296d13be9150b9546e85cb00ff7e1a9d7d6fa0c 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 ( @@ -34,6 +31,7 @@ import ( "go/parser" "go/scanner" "go/token" + "internal/buildcfg" "internal/testenv" "os" "path/filepath" @@ -53,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, @@ -202,20 +200,35 @@ func asGoVersion(s string) string { return "" } -func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string, srcs [][]byte, manual bool, imp Importer) { +// 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, + "issue49705.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 strings.HasSuffix(filenames[0], ".go2") && !typeparams.Enabled { - t.Skip("type params are not enabled") + 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") && typeparams.Enabled { + + if strings.HasSuffix(filenames[0], ".go1") { + // TODO(rfindley): re-enable this test by using GoVersion. t.Skip("type params are enabled") } mode := parser.AllErrors - if !strings.HasSuffix(filenames[0], ".go2") { + if !strings.HasSuffix(filenames[0], ".go2") && !manual { mode |= typeparams.DisallowParsing } @@ -228,6 +241,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) } @@ -243,7 +257,7 @@ func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string, // 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 { @@ -303,29 +317,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, nil) + testFiles(t, nil, []string{"longconst.go"}, [][]byte{[]byte(src)}, false, nil) } // TestIndexRepresentability tests that constant index operands must @@ -333,32 +366,25 @@ 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, 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\"" - checkFiles(t, nil, "", []string{"issue46453.go"}, [][]byte{[]byte(src)}, false, nil) + testFiles(t, &StdSizes{4, 4}, []string{"index.go"}, [][]byte{[]byte(src)}, false, nil) } func TestIssue47243_TypedRHS(t *testing.T) { // The RHS of the shift expression below overflows uint on 32bit platforms, // but this is OK as it is explicitly typed. const src = "package issue47243\n\nvar a uint64; var _ = a << uint64(4294967296)" // uint64(1<<32) - checkFiles(t, &StdSizes{4, 4}, "", []string{"p.go"}, [][]byte{[]byte(src)}, false, nil) + testFiles(t, &StdSizes{4, 4}, []string{"p.go"}, [][]byte{[]byte(src)}, false, nil) } -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 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) } -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) @@ -368,28 +394,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) @@ -398,5 +434,5 @@ func testPkg(t *testing.T, filenames []string, goVersion string, manual bool) { } srcs[i] = src } - checkFiles(t, nil, goVersion, filenames, srcs, manual, nil) + testFiles(t, nil, filenames, srcs, manual, nil) } diff --git a/src/go/types/context.go b/src/go/types/context.go new file mode 100644 index 0000000000000000000000000000000000000000..ff4bf89f3cb0076abca2a199c2288bee980276a9 --- /dev/null +++ b/src/go/types/context.go @@ -0,0 +1,123 @@ +// Copyright 2021 The Go Authors. 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" + "fmt" + "strconv" + "strings" + "sync" +) + +// 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 Context struct { + 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 { + orig Type + targs []Type + instance Type // = orig[targs] +} + +// NewContext creates a new Context. +func NewContext() *Context { + return &Context{ + typeMap: make(map[string][]ctxtEntry), + originIDs: make(map[Type]int), + } +} + +// 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(orig != nil) + var buf bytes.Buffer + + h := newTypeHasher(&buf, ctxt) + 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. + h.typeList(targs) + } + + return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4 +} + +// lookup returns an existing instantiation of orig with targs, if it exists. +// Otherwise, it returns nil. +func (ctxt *Context) lookup(h string, orig Type, targs []Type) Type { + ctxt.mu.Lock() + defer ctxt.mu.Unlock() + + for _, e := range ctxt.typeMap[h] { + 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.instance)) + } + } + + 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, orig Type, targs []Type, inst Type) Type { + assert(inst != nil) + + ctxt.mu.Lock() + defer ctxt.mu.Unlock() + + for _, e := range ctxt.typeMap[h] { + 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", inst, e.instance)) + } + } + + ctxt.typeMap[h] = append(ctxt.typeMap[h], ctxtEntry{ + orig: orig, + targs: targs, + instance: inst, + }) + + return inst +} + +// 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.originIDs[t] + if !ok { + id = ctxt.nextID + ctxt.originIDs[t] = id + ctxt.nextID++ + } + return id +} diff --git a/src/go/types/context_test.go b/src/go/types/context_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ec3005020220683d7cc83fcd6ad45479438d7240 --- /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/conversions.go b/src/go/types/conversions.go index ad6d3eef1027a839d0c0dea3e87172cde7ef8c02..a5b359e5394c39148002209533df65e8cbb1bae8 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -16,33 +16,71 @@ import ( func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ - var ok bool - var reason string - switch { - case constArg && isConstType(T): - // constant conversion - switch t := asBasic(T); { - case representableConst(x.val, check, t, &x.val): - ok = true + constConvertibleTo := func(T Type, val *constant.Value) bool { + switch t, _ := under(T).(*Basic); { + 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 } - case x.convertibleTo(check, T, &reason): + 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 = 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) + 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): // non-constant conversion - x.mode = value ok = true + x.mode = value } 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 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 @@ -60,9 +98,9 @@ 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) && isString(T) { + } else if isInteger(x.typ) && allString(T) { final = x.typ } check.updateExprType(x.expr, final, true) @@ -81,104 +119,168 @@ 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 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 check.identicalIgnoreTags(Vu, Tu) { + Vp, _ := V.(*TypeParam) + Tp, _ := T.(*TypeParam) + if IdenticalIgnoreTags(Vu, Tu) && Vp == nil && Tp == nil { return true } - // "x's type and T are unnamed pointer types and their pointer base types - // have identical underlying types if tags are ignored" + // "V and T are unnamed pointer types and their pointer base types + // 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 check.identicalIgnoreTags(under(V.base), under(T.base)) { + if IdenticalIgnoreTags(under(V.base), under(T.base)) && !isTypeParam(V.base) && !isTypeParam(T.base) { return true } } } - // "x's type and T are both integer or floating point types" - if isIntegerOrFloat(V) && isIntegerOrFloat(T) { + // "V and T are both integer or floating point types" + if isIntegerOrFloat(Vu) && isIntegerOrFloat(Tu) { return true } - // "x's type and T are both complex types" - if isComplex(V) && isComplex(T) { + // "V and T are both complex types" + if isComplex(Vu) && isComplex(Tu) { return true } - // "x is an integer or a slice of bytes or runes and T is a string type" - if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { + // "V is an integer or a slice of bytes or runes and T is a string type" + if (isInteger(Vu) || isBytesOrRunes(Vu)) && isString(Tu) { return true } - // "x is a string and T is a slice of bytes or runes" - if isString(V) && isBytesOrRunes(Tu) { + // "V is a string and T is a slice of bytes or runes" + 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 } - // "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 { - if a := asArray(p.Elem()); a != nil { - if check.identical(s.Elem(), a.Elem()) { + 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) { 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" } } } } } + // optimization: if we don't have type parameters, we're done + if Vp == nil && Tp == nil { + return false + } + + errorf := func(format string, args ...any) { + 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 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 + } + 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 } 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? - // (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/decl.go b/src/go/types/decl.go index 9211febc6da1620a43e9867af2f37c149a6f0753..2c51329be93b04bae5a017354428e3e45241ef87 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" ) @@ -51,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 { @@ -66,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(nil, 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 @@ -118,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 @@ -130,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 @@ -150,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 @@ -172,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, } @@ -204,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] @@ -222,13 +227,23 @@ func (check *Checker) cycle(obj Object) (isCycle 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 @@ -256,31 +271,36 @@ func (check *Checker) cycle(obj Object) (isCycle 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 isCycle { + if !valid { check.trace(obj.Pos(), "=> error: cycle is invalid") } }() } - // 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 false - } + 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 false // cycle is permitted + // 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) - - return true + return false } type typeInfo uint @@ -309,6 +329,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 { @@ -317,6 +344,17 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: + // 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 { @@ -333,25 +371,23 @@ 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 { 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:]) t.info = invalid - return t.info + t.underlying = Typ[Invalid] + return invalid } } - panic("internal error: cycle start not found") + panic("cycle start not found") } return t.info - - case *instance: - return check.validType(t.expand(), path) } return valid @@ -566,172 +602,85 @@ 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 + check.initVars(lhs, []ast.Expr{init}, nil) } -func (n *Named) setUnderlying(typ Type) { - if n != nil { - n.underlying = typ +// 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.IsMethodSet() } 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, _UnsupportedFeature, "using type constraint %s requires go1.18 or later", rhs) + } + }).describef(obj, "validType(%s)", obj.Name()) alias := tdecl.Assign.IsValid() - if alias && typeparams.Get(tdecl) != nil { + 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), _BadDecl, "generic type cannot be alias") 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) - - } else { - // defined type declaration + rhs = check.varType(tdecl.Type) + obj.typ = rhs + return + } - named := check.newNamed(obj, nil, nil) - def.setUnderlying(named) - obj.typ = named // make sure recursive type declarations terminate + // 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 tdecl.TypeParams != nil { + check.openScope(tdecl, "type parameters") + defer check.closeScope() + check.collectTypeParams(&named.tparams, tdecl.TypeParams) + } - // determine underlying type of named - named.orig = check.definedType(tdecl.Type, named) + // determine underlying type of 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.origin 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] } -} - -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 + // Disallow a lone type parameter as the RHS of a type declaration (issue #45639). + // 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] } +} +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 // list (so we can have mutually recursive parameterized interfaces). @@ -739,53 +688,90 @@ 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 - } + // 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) + + // 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 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 + defer func() { + check.inTParamList = false + }() 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 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. + // TODO(rfindley) we should be able to rely on f.Type != nil at this point + if f.Type != nil { + bound := check.bound(f.Type) + bounds = append(bounds, bound) + posns = append(posns, f.Type) for i := range f.Names { - setBoundAt(index+i, bound) + tparams[index+i].bound = bound } - } else if bound != Typ[Invalid] { - check.errorf(f.Type, _Todo, "%s is not an interface", bound) } - - next: index += len(f.Names) } - return + 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") + } + } + for _, tpar := range tparams { + tpar.iface() // compute type set + } + }) } -func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) []*TypeName { +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 { + 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) +} + +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 { - tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil) - 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 + tname := NewTypeName(name.Pos(), check.pkg, name.Name, nil) + 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) } @@ -813,9 +799,10 @@ 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 { - if t, _ := base.underlying.(*Struct); t != nil { + u := base.under() + if t, _ := u.(*Struct); t != nil { for _, fld := range t.fields { if fld.name != "_" { assert(mset.insert(fld) == nil) @@ -851,6 +838,7 @@ func (check *Checker) collectMethods(obj *TypeName) { } if base != nil { + base.resolve(nil) // TODO(mdempsky): Probably unnecessary. base.methods = append(base.methods, m) } } @@ -877,6 +865,10 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) { check.funcType(sig, fdecl.Recv, fdecl.Type) obj.color_ = saved + if fdecl.Type.TypeParams.NumFields() > 0 && fdecl.Body == nil { + check.softErrorf(fdecl.Name, _BadDecl, "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/errorcodes.go b/src/go/types/errorcodes.go index 3d24da7b533cf89d5851a204dd8c373b2567d3dc..b3796e89194bfd18862c92b8a2cef97c9a431501 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, @@ -884,7 +875,7 @@ const ( // context in which it is used. // // Example: - // var _ = 1 + "" + // var _ = 1 + new(int) _InvalidUntypedConversion // _BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument @@ -1310,7 +1301,103 @@ const ( // var _ = unsafe.Slice(&x, uint64(1) << 63) _InvalidUnsafeSlice - // _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 + // 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 + + // _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. + // + // 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. + // + // Example: + // 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 ) diff --git a/src/go/types/errorcodes_test.go b/src/go/types/errorcodes_test.go index 5da1cdadfc69144f20a408ea043948db62129b4f..629eac4912d3e2770e557902d6c79b90fde0b5d9 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/errors.go b/src/go/types/errors.go index 226310641733ae833e91e63064ec6a8db71ea469..81c62a82f0e4412ccf42ef2a56d49eb33247c895 100644 --- a/src/go/types/errors.go +++ b/src/go/types/errors.go @@ -62,40 +62,46 @@ 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 ...any) string { for i, arg := range args { switch a := arg.(type) { 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) + 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, debug) } args[i] = arg } 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), - 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...)) +func (check *Checker) dump(format string, args ...any) { + fmt.Println(sprintf(check.fset, check.qualifier, true, format, args...)) } func (check *Checker) err(err error) { @@ -164,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) } @@ -173,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...) } @@ -236,7 +242,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: @@ -259,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 fdbe07cae0b4892387fce5287adb71e964a1efd9..942a9fdd4c2579fe7d2572e5cf900671dfdeb1df 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/eval.go b/src/go/types/eval.go index 51259604c984c5d6d74274e9341de8349ba866b5..c8bb005eb6d4a13d638a8aa2e8b32176411c38d1 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/eval_test.go b/src/go/types/eval_test.go index 41d3a61b89528ed7e8c4445585982f8efc593bd0..b0745c16d9729b84b5e26853d7623ed94892ba7a 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 */ @@ -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) { @@ -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/example_test.go b/src/go/types/example_test.go index 32a25a41176159264c28ab7943aceb200b56712f..270256748645a9d7d6380df4d17cbb2d45f08dc0 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/expr.go b/src/go/types/expr.go index 58962e777bc9541ec549a0c0de0035187f0331ac..452e9ab598ab8651f7eab9763744c570176b3c50 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, } } @@ -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, under(x.typ).(*Basic)) return } @@ -114,9 +116,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: @@ -144,6 +144,15 @@ 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 { + if tpar, _ := typ.(*TypeParam); tpar != nil { + return tpar.underIs(f) + } + return f(under(typ)) +} + // 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 +173,26 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { return case token.ARROW: - typ := asChan(x.typ) - if typ == nil { + 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 typ.dir == SendOnly { + 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 = typ.elem + x.typ = ch.elem check.hasCallOrRecv = true return } @@ -536,7 +552,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 } @@ -549,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 } @@ -582,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, target.Underlying()) + t := target + if !isTypeParam(target) { + t = safeUnderlying(target) + } + check.invalidConversion(code, x, t) x.mode = invalid return } @@ -603,7 +623,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 } @@ -622,10 +641,10 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return x.typ, nil, 0 } - switch t := optype(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 } @@ -661,19 +680,23 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const default: return nil, nil, _InvalidUntypedConversion } - case *_Sum: - ok := t.is(func(t Type) bool { - 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 - } case *Interface: + if isTypeParam(target) { + if !u.typeSet().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 + } + 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 @@ -682,8 +705,7 @@ 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() { + if !u.Empty() { return nil, nil, _InvalidUntypedConversion } return Default(x.typ), nil, 0 @@ -714,7 +736,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() } @@ -765,7 +787,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 { @@ -802,8 +824,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 @@ -891,7 +913,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 @@ -905,19 +927,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, } } @@ -943,14 +965,35 @@ 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 + // TODO(gri) make canMix more efficient - called for each binary operation + canMix := func(x, y *operand) bool { + if IsInterface(x.typ) && !isTypeParam(x.typ) || IsInterface(y.typ) && !isTypeParam(y.typ) { + return true + } + if allBoolean(x.typ) != allBoolean(y.typ) { + return false + } + if allString(x.typ) != allString(y.typ) { + return false + } + if x.isNil() && !hasNil(y.typ) { + return false + } + if y.isNil() && !hasNil(x.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) { @@ -958,7 +1001,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] { @@ -966,7 +1009,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, "mismatched types %s and %s", 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 @@ -979,7 +1026,7 @@ 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 @@ -1031,8 +1078,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++ @@ -1043,11 +1092,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, _WrongTypeArgCount, "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. // @@ -1146,7 +1224,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 @@ -1154,8 +1236,14 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error } - switch utyp := optype(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. + if utyp.fields == nil { + check.error(e, _InvalidDeclCycle, "illegal cycle in type declaration") + goto Error + } if len(e.Elts) == 0 { break } @@ -1266,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 { @@ -1282,9 +1370,9 @@ 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 check.identical(vtyp, x.typ) { + if Identical(vtyp, x.typ) { duplicate = true break } @@ -1326,16 +1414,17 @@ 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 case *ast.SelectorExpr: check.selector(x, e) - case *ast.IndexExpr: - if check.indexExpr(x, e) { - check.funcInst(x, e) + case *ast.IndexExpr, *ast.IndexListExpr: + ix := typeparams.UnpackIndexExpr(e) + if check.indexExpr(x, ix) { + check.funcInst(x, ix) } if x.mode == invalid { goto Error @@ -1352,12 +1441,16 @@ 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) 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 @@ -1377,20 +1470,31 @@ 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 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, _InvalidIndirection, "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: @@ -1425,12 +1529,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 @@ -1443,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) @@ -1475,7 +1574,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) @@ -1491,14 +1590,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 { buf.WriteString(", ") } @@ -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 51102881c9f188f7021bda97b44697f0e8b6005f..27cd532c97c2715a3de8941774e37f15a36cfefe 100644 --- a/src/go/types/exprstring_test.go +++ b/src/go/types/exprstring_test.go @@ -27,6 +27,33 @@ 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{~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"), diff --git a/src/go/types/gotype.go b/src/go/types/gotype.go index ca1d42c14d5aec3d543529ace321d4f9fd54ca17..5d27bb7a077f9bf7e692c35ab8ece3877ec04dc3 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 @@ -180,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 77954d2f8b934dbbbcaa5633031c2317623ea68e..7d0f58ea40b5992200c9a6855832660ba0f8f677 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/index.go b/src/go/types/index.go index 2ba3475f897107817d16c75730d28319ab3915b5..db4732c8e00e466ee5e6e53f646802a952d2b1aa 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -15,33 +15,42 @@ 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, e *typeparams.IndexExpr) (isFuncInst bool) { + check.exprOrType(x, e.X, true) + // x may be generic switch x.mode { case invalid: - check.use(typeparams.UnpackExpr(e.Index)...) + check.use(e.Indices...) return false case typexpr: // type instantiation x.mode = invalid - x.typ = check.varType(e) + // TODO(gri) here we re-evaluate e.X - try to avoid this + x.typ = check.varType(e.Orig) if x.typ != Typ[Invalid] { x.mode = typexpr } return false case value: - if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 { + if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } } + // x should not be generic at this point, but be safe and check + check.nonGeneric(x) + if x.mode == invalid { + return false + } + + // 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 @@ -64,7 +73,7 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) 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 @@ -80,7 +89,7 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) index := check.singleIndex(e) if index == nil { x.mode = invalid - return + return false } var key operand check.expr(&key, index) @@ -88,102 +97,101 @@ 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 - return + x.expr = e.Orig + return false - case *_Sum: - // A sum type can be indexed if all of the sum's types - // support indexing and have the same index and element - // type. Special rules apply for maps in the sum 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 { - var e Type - switch t := under(t).(type) { + case *Interface: + if !isTypeParam(x.typ) { + break + } + // 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 := asArray(t.base); t != nil { + if t, _ := under(t.base).(*Array); t != nil { + l = t.len e = t.elem } case *Slice: e = t.elem case *Map: - // If there are multiple maps in the sum 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) { - return false - } - tkey = t.key + k = 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) { + if e == nil { return false } - telem = e + 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 }) { - // 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 key != 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") + 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 - - // If there are only maps, we are done. - if nmaps == len(typ.types) { - 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 = elem + x.expr = e + return false } - x.typ = telem + + // no maps + valid = true + x.mode = mode + x.typ = elem } } if !valid { check.invalidOp(x, _NonIndexableOperand, "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) @@ -206,11 +214,20 @@ 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 := structuralString(x.typ).(type) { + case nil: + check.invalidOp(x, _NonSliceableOperand, "cannot slice %s: %s has no structural type", x, x.typ) + x.mode = invalid + return + case *Basic: - if isString(typ) { + 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 } @@ -220,36 +237,31 @@ 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 isUntyped(x.typ) { 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, _ := under(u.base).(*Array); u != nil { valid = true - length = typ.len - x.typ = &Slice{elem: typ.elem} + length = u.len + x.typ = &Slice{elem: u.elem} } case *Slice: valid = true // x.typ doesn't change - - case *_Sum, *_TypeParam: - check.errorf(x, 0, "generic slice expressions not yet implemented") - x.mode = invalid - return } if !valid { @@ -298,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 } } @@ -311,23 +327,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. @@ -375,7 +384,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/infer.go b/src/go/types/infer.go index 5d49351e1f043475332fad124e73efc5b4e2f6a5..a5088f27050bf35fffbd2afbc534697d9ffc7885 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -8,6 +8,7 @@ package types import ( + "fmt" "go/token" "strings" ) @@ -26,8 +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. -// -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) (result []Type) { if debug { defer func() { assert(result == nil || len(result) == len(tparams)) @@ -59,7 +59,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, 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(posn, tparams, targs) if targs == nil || index < 0 { return targs } @@ -82,18 +82,18 @@ 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) - params = check.subst(token.NoPos, params, smap).(*Tuple) + params = check.subst(token.NoPos, params, smap, nil).(*Tuple) } // --- 2 --- // 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. @@ -104,9 +104,6 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, 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 { @@ -121,17 +118,21 @@ 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, _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) + 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, 0, "%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) } } @@ -173,7 +174,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, 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(posn, tparams, targs) if targs == nil || index < 0 { return targs } @@ -189,7 +190,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 @@ -209,7 +210,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, } // Again, follow up with constraint type inference. - targs, index = check.inferB(tparams, targs, report) + targs, index = check.inferB(posn, tparams, targs) if targs == nil || index < 0 { return targs } @@ -217,24 +218,22 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, 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.name, tpar.pos, targs) - } + check.errorf(posn, _CannotInferTypeArgs, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos) 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 +242,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 +260,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) { @@ -302,9 +301,6 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } } - case *_Sum: - return w.isParameterizedList(t.types) - 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 @@ -316,24 +312,15 @@ 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.isParameterizedList(unpackType(t.allTypes)) } - - return t.iterate(func(t *Interface) bool { - for _, m := range t.methods { - if w.isParameterized(m.typ) { - return true - } - } - return w.isParameterizedList(unpackType(t.types)) - }, nil) + return tset.is(func(t *term) bool { + return t != nil && w.isParameterized(t.typ) + }) case *Map: return w.isParameterized(t.key) || w.isParameterized(t.elem) @@ -342,14 +329,11 @@ 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.list()) - case *_TypeParam: + case *TypeParam: // 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) + return tparamIndex(w.tparams, t) >= 0 default: unreachable() @@ -358,7 +342,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 @@ -375,12 +359,12 @@ func (w *tpWalker) isParameterizedList(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(posn positioner, 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(check, false) + u := newUnifier(false) u.x.init(tparams) u.y = u.x // type parameters between LHS and RHS of unification are identical @@ -391,24 +375,28 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty } } - // 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.typ.(*_TypeParam) - sbound := check.structuralType(typ.bound) + sbound := structuralType(tpar) if sbound != nil { - if !u.unify(typ, sbound) { - if report { - check.errorf(tpar, _Todo, "%s does not match %s", tpar, sbound) - } + // 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(tpar, sbound) { + // TODO(gri) improve error message by providing the type arguments + // which we know already + check.errorf(posn, _InvalidTypeArg, "%s does not match %s", tpar, sbound) return nil, 0 } } } // 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 + // 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 // remaining type parameters by substituting the type parameters in this type list // until nothing changes anymore. @@ -419,6 +407,34 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty } } + // 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. @@ -437,7 +453,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++ @@ -468,15 +484,97 @@ 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 { - check.completeInterface(token.NoPos, iface) - types := unpackType(iface.allTypes) - if len(types) == 1 { - return types[0] +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: + // 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) } - return nil + + 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) } - return constraint } diff --git a/src/go/types/initorder.go b/src/go/types/initorder.go index 77a739c7c14e34c5c951e77195cfcb970a748954..1118b58f7bac2c7e7ba1fdc61143b8ea19c98e1d 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 } } @@ -284,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 new file mode 100644 index 0000000000000000000000000000000000000000..e8748975c9150398521e29f4680ccc7fc6473748 --- /dev/null +++ b/src/go/types/instantiate.go @@ -0,0 +1,267 @@ +// Copyright 2021 The Go 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 implements instantiation of generic types +// through substitution of type parameters by type arguments. + +package types + +import ( + "errors" + "fmt" + "go/token" +) + +// 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-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 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. +// +// 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 := 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 nil, &ArgumentError{i, 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 +// 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) (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: + 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) + } + res = named + + case *Signature: + tparams := orig.TypeParams() + if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { + return Typ[Invalid] + } + if tparams.Len() == 0 { + return orig // nothing to do (minor optimization) + } + 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 == orig { + copy := *sig + sig = © + } + // After instantiating a generic signature, it is not generic + // anymore; we need to set tparams to nil. + sig.tparams = nil + 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) + } + + return res +} + +// 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, ntparams, ntargs int) bool { + if ntargs != ntparams { + // TODO(gri) provide better error message + if check != nil { + 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)) + } + return true +} + +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 { + // 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 +} + +// 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 + } + + errorf := func(format string, args ...any) error { + return errors.New(sprintf(nil, qf, false, format, args...)) + } + + Ti, _ := Tu.(*Interface) + if Ti == nil { + return errorf("%s is not an interface", T) + } + + // 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) + + // 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 + + // No type with non-empty type set satisfies the empty type set. + if Ti.typeSet().IsEmpty() { + return errorf("cannot implement %s (empty type set)", T) + } + + // If T is comparable, V must be comparable. + // TODO(gri) the error messages could be better, here + if Ti.IsComparable() && !Comparable(V) { + if Vi != nil && Vi.Empty() { + return errorf("empty interface %s does not implement %s", V, T) + } + return errorf("%s does not implement comparable", V) + } + + // V must implement T (methods) + // - check only if we have methods + if Ti.NumMethods() > 0 { + 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 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 implement %s: wrong method signature\n\tgot %s\n\twant %s", + V, T, wrong, m, + ) + } + return errorf("%s does not implement %s (missing method %s)", V, T, m.name) + } + } + + // V must also be in the set of types of T, if any. + // Constraints with empty type sets were already excluded above. + if !Ti.typeSet().hasTerms() { + return nil // nothing to do + } + + // 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 implement %s", V, T) + } + return nil + } + + // Otherwise, V's type must be included in the iface type set. + 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/instantiate_test.go b/src/go/types/instantiate_test.go new file mode 100644 index 0000000000000000000000000000000000000000..281c8bbcad85116f477853c909fec1e23cb69b82 --- /dev/null +++ b/src/go/types/instantiate_test.go @@ -0,0 +1,253 @@ +// Copyright 2021 The Go Authors. 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/token" + . "go/types" + "strings" + "testing" +) + +func TestInstantiateEquality(t *testing.T) { + emptySignature := NewSignatureType(nil, nil, nil, nil, nil, false) + 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, + }, + { + // 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]}, + "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, + }, + } + + 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() + + 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 := pkgForMode(".", src, nil, 0) + if err != nil { + t.Fatal(err) + } + pkg2, err := pkgForMode(".", src, nil, 0) + if err != nil { + t.Fatal(err) + } + + // We consider T1 and T2 to be distinct types, so their instances should not + // be deduplicated by the context. + T1 := pkg1.Scope().Lookup("T").Type().(*Named) + T2 := pkg2.Scope().Lookup("T").Type().(*Named) + + ctxt := NewContext() + res1, err := Instantiate(ctxt, T1, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + res2, err := Instantiate(ctxt, 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) + } +} + +func TestMethodInstantiation(t *testing.T) { + const prefix = `package 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 := pkgForMode(".", src, nil, 0) + 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 = `package p + +type T[P any] struct{} + +func (T[P]) m() {} + +var _ T[int] +` + pkg, err := pkgForMode(".", src, nil, 0) + 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/interface.go b/src/go/types/interface.go new file mode 100644 index 0000000000000000000000000000000000000000..1ff90157804366acac2503a1996781b9468433ea --- /dev/null +++ b/src/go/types/interface.go @@ -0,0 +1,225 @@ +// Copyright 2021 The Go Authors. 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 + +// 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 + 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 +} + +// typeSet returns the type set for interface 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} + +// 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. +// +// 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 + } + + // 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 +} + +// 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) } + +// 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().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().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 +// form other types. The interface must not contain duplicate methods or a +// panic occurs. Complete returns the receiver. +// +// Interface types that have been completed are safe for concurrent use. +func (t *Interface) Complete() *Interface { + if !t.complete { + t.complete = true + } + t.typeSet() // checks if t.tset is already set + 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) { + 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 { + addEmbedded(f.Type.Pos(), parseUnion(check, f.Type)) + continue + } + // f.Name != nil + + // 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 + } + + 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 ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TypeParams != nil { + at = ftyp.TypeParams + } + check.errorf(at, _InvalidMethodTypeParams, "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) + } + + // 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 + + if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 { + // empty interface + ityp.tset = &topTypeSet + return + } + + // sort for API stability + sortMethods(ityp.methods) + // (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 will use + // this computed type set and won't need to pass in a *Checker. + // + // 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 + }).describef(iface, "compute type set for %s", ityp) +} diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go index 519e19953645d8e8c4f97d0058cd29ebdb9ffdc3..51995af30afd39f7c174abaa1d61dfc9421277bb 100644 --- a/src/go/types/issues_test.go +++ b/src/go/types/issues_test.go @@ -634,7 +634,7 @@ var _ T = template /* ERROR cannot use.*text/template.* as T value */.Template{} } imp := importHelper{pkg: a, fallback: importer.Default()} - checkFiles(t, nil, "", []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, imp) - checkFiles(t, nil, "", []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp) - checkFiles(t, nil, "", []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp) + testFiles(t, nil, []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, imp) + testFiles(t, nil, []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp) + testFiles(t, nil, []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp) } diff --git a/src/go/types/labels.go b/src/go/types/labels.go index 8cf6e63645e9f123386bc7cd879a591c76382d13..f3b7f211f37f25d46efec69975f501942e3a9118 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 9c7bfd4bb97da8db276c633874c8dda8186dffda..c787601a06512ae0644f1c4651a8625e26417126 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -6,7 +6,15 @@ package types -import "go/token" +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 +// 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 @@ -35,19 +43,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 @@ -55,9 +50,9 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package // 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, _ := t.underlying.(*Pointer); p != nil { - obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name) + 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 } @@ -65,7 +60,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 +68,11 @@ 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. +// +// 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! - // This function and NewMethodSet should be kept in sync. if name == "_" { return // blank fields/methods are never found @@ -85,9 +81,10 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack 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 + if isPtr { + if _, ok := under(typ).(*Interface); ok { + return + } } // Start with typ as single entry at shallowest depth. @@ -107,13 +104,13 @@ 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 // 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 @@ -128,6 +125,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack 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 @@ -140,14 +138,8 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack 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 @@ -185,9 +177,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 { @@ -197,10 +187,8 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack indirect = e.indirect } - 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 { + case *TypeParam: + 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 { @@ -221,7 +209,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack // 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 } @@ -229,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 @@ -246,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 } @@ -254,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 { @@ -266,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 } } @@ -306,40 +294,40 @@ 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) + 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) 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 } + // 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.TypeParams().Len() != mtyp.TypeParams().Len() { return m, f } + if ftyp.TypeParams().Len() > 0 { + panic("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 // 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.x.init(ftyp.tparams) + u := newUnifier(true) + u.x.init(ftyp.TypeParams().list()) if !u.unify(ftyp, mtyp) { return m, f } @@ -349,17 +337,20 @@ 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) + 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 { + // methods may not have a fully set up signature yet + if check != nil { + check.objDecl(obj, nil) + } return m, obj.(*Func) } } @@ -367,10 +358,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 } @@ -382,28 +369,11 @@ 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.TypeParams().Len() != mtyp.TypeParams().Len() { return m, f } - - // 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 && 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 - // 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) { - return - } - ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.rparams, Vn.targs)).(*Signature) + if ftyp.TypeParams().Len() > 0 { + panic("method with type parameters") } // If the methods have type parameters we don't care whether they @@ -411,8 +381,8 @@ 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.x.init(ftyp.tparams) + u := newUnifier(true) + u.x.init(ftyp.RecvTypeParams().list()) if !u.unify(ftyp, mtyp) { return m, f } @@ -421,6 +391,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) && !isTypeParam(T) { + if isInterfacePtr(V) { + r = fmt.Sprintf("(%s is pointer to interface, not interface)", V) + } + } else if isInterfacePtr(T) && !isTypeParam(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) && !isTypeParam(T) +} + // 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. @@ -432,7 +455,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) @@ -442,6 +465,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 @@ -450,8 +480,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/map.go b/src/go/types/map.go new file mode 100644 index 0000000000000000000000000000000000000000..01e13b214e966412debe21f1f64e2d35d65abc66 --- /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/methodset.go b/src/go/types/methodset.go index ae8011a2eeef92f8246631d13cf24d1cc5780504..e17be7c41af748b53e9fac3cb7bbd0e18422a4f5 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 @@ -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 } } @@ -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) + case *TypeParam: + mset = mset.add(t.iface().typeSet().methods, e.index, true, e.multiples) } } @@ -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 { @@ -237,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 } @@ -249,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/methodset_test.go b/src/go/types/methodset_test.go index 4a373fa2c4ff9846a46826a88a63b8c85b1522db..73a8442f21417de6c3c3f01019551b2ae825fc0d 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" ) @@ -47,12 +46,15 @@ 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. - "type C interface{ f() }; func g[T C]() { type Y T; var a Y; _ = a }": {}, + // 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 }": {}, } check := func(src string, methods []method, generic bool) { @@ -101,9 +103,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/mono.go b/src/go/types/mono.go new file mode 100644 index 0000000000000000000000000000000000000000..84e1e971b67471d3adb8976ab6fe98bb1b9dfbdb --- /dev/null +++ b/src/go/types/mono.go @@ -0,0 +1,336 @@ +// Copyright 2021 The Go Authors. 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" +) + +// 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 token.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? + + 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] + 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 + } + } +} + +// 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, xlist []ast.Expr) { + for i, tpar := range tparams { + pos := pos + if i < len(xlist) { + pos = xlist[i].Pos() + } + 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, 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() < 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, 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 token.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/go/types/mono_test.go b/src/go/types/mono_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5df3d493f8a4fcb31c09bfd2b5ef73949bded9ae --- /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[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/go/types/named.go b/src/go/types/named.go new file mode 100644 index 0000000000000000000000000000000000000000..82a053dd0d2d344dcbc1cda52db410a89524618f --- /dev/null +++ b/src/go/types/named.go @@ -0,0 +1,349 @@ +// 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" +) + +// 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 + 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 + + // resolver may be provided to lazily resolve type parameters, underlying, and methods. + resolver func(*Context, *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. +// 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("underlying type must not be *Named") + } + return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) +} + +func (t *Named) resolve(ctxt *Context) *Named { + if t.resolver == nil { + return t + } + + t.once.Do(func() { + // 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 + // also make the API more future-proof towards further extensions + // (like SetTypeParams). + t.tparams, t.underlying, t.methods = t.resolver(ctxt, t) + t.fromRHS = t.underlying // for cycle detection + }) + 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 *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 + } + if obj.typ == nil { + obj.typ = typ + } + // Ensure that typ is always expanded and sanity-checked. + if check != nil { + check.defTypes = append(check.defTypes, typ) + } + return typ +} + +// 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 +} + +// 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. + +// 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.resolve(nil).tparams } + +// SetTypeParams sets the type parameters of the named type t. +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.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.resolve(nil).methods[i] } + +// SetUnderlying sets the underlying type and marks t as complete. +func (t *Named) SetUnderlying(underlying Type) { + if underlying == nil { + panic("underlying type must not be nil") + } + if _, ok := underlying.(*Named); ok { + panic("underlying type must not be *Named") + } + t.resolve(nil).underlying = underlying +} + +// AddMethod adds method m unless it is already in the method list. +func (t *Named) AddMethod(m *Func) { + 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.resolve(nil).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. +// +// 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() + + // If the underlying type of a defined type is not a defined + // (incl. instance) type, then that is the desired underlying + // type. + var n1 *Named + switch u1 := u.(type) { + case nil: + // After expansion via Underlying(), we should never encounter a nil + // underlying. + panic("nil underlying") + default: + // common case + return u + case *Named: + // handled below + n1 = u1 + } + + if n0.check == nil { + panic("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 + n := n0 + + seen := make(map[*Named]int) // types that need their underlying resolved + var path []Object // objects encountered, for cycle reporting + +loop: + for { + 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 { + // 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("imported type with unresolved underlying type") + } + n.underlying = u + } + + return u +} + +func (n *Named) setUnderlying(typ Type) { + if n != nil { + n.underlying = typ + } +} + +// bestContext returns the best available context. In order of preference: +// - the given ctxt, if 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 { + if check.ctxt == nil { + check.ctxt = NewContext() + } + return check.ctxt + } + 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(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 + + 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. + ctxt = check.bestContext(ctxt) + 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) + + smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) + underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt) + + 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(ctxt, m) + } + } + } + if check != nil { + check.later(completeMethods) + } else { + completeMethods() + } + + return n.orig.tparams, underlying, methods +} + +func (check *Checker) completeMethod(ctxt *Context, 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, ctxt).(*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 m.hasPtrRecv() { + rtyp = NewPointer(rbase) + } else { + rtyp = rbase + } + 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 +// 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.underlying + } + return typ.Underlying() +} diff --git a/src/go/types/object.go b/src/go/types/object.go index 50346ec6919407e41e730b09c849a324938b18de..cf05384a87ed6d3cf2f77119de64e70c36c34442 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -230,6 +230,26 @@ 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, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { + obj := NewTypeName(pos, pkg, name, nil) + + resolve := func(_ *Context, 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 +} + // IsAlias reports whether obj is an alias name for a type. func (obj *TypeName) IsAlias() bool { switch t := obj.typ.(type) { @@ -249,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 } @@ -297,7 +319,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; use hasPtrRecv() to read } // NewFunc returns a new function with the given signature, representing @@ -308,7 +331,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 @@ -320,8 +343,29 @@ 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. +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. @@ -370,6 +414,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 { @@ -415,19 +462,34 @@ 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 + 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) } } + // 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 2b6057bd934bca19cfa0f40062d6b8bb63fdd744..47c7fcd349c3863d43138fb8e22ec4eb1532e4d8 100644 --- a/src/go/types/object_test.go +++ b/src/go/types/object_test.go @@ -2,13 +2,17 @@ // 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" + "internal/testenv" + "strings" "testing" + + . "go/types" ) func TestIsAlias(t *testing.T) { @@ -22,7 +26,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") } } @@ -30,19 +34,22 @@ 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 }{ - {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) } @@ -84,3 +91,80 @@ 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 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}"}, + {"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 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) { + 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().LookupParent(names[0], token.NoPos) + 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/operand.go b/src/go/types/operand.go index 6463728cec6a37b9308fa8853663104deaa2ed90..06ecbf14102efc9482d27ae2f9c69f0d28f77c31 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 @@ -159,16 +164,17 @@ 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: + if isGeneric(x.typ) { + intro = " of parameterized type " + } else { intro = " of type " } buf.WriteString(intro) WriteType(&buf, x.typ, qf) + if tpar, _ := x.typ.(*TypeParam); tpar != nil { + buf.WriteString(" constrained by ") + WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here + } } else { buf.WriteString(" with invalid type") } @@ -234,46 +240,62 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er V := x.typ // x's type is identical to T - if check.identical(V, T) { + if Identical(V, T) { return true, 0 } - Vu := optype(V) - Tu := optype(T) + Vu := under(V) + Tu := under(T) + Vp, _ := V.(*TypeParam) + Tp, _ := T.(*TypeParam) // 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 { - // TODO(gri) this could probably be more efficient - ok, _ := x.assignableTo(check, t, reason) - return ok + 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 + } + // 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 check.identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { + // 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 - if Ti, ok := Tu.(*Interface); ok { + // T is an interface type and x implements T and T is not a type parameter + 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 wrongType != nil { - if check.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 @@ -281,14 +303,90 @@ 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 && Vp == 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 + // 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) { - return !isNamed(V) || !isNamed(T), _InvalidChanAssign + if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) { + return !hasName(V) || !hasName(T), _InvalidChanAssign + } + } + + // optimization: if we don't have type parameters, we're done + if Vp == nil && Tp == nil { + return false, _IncompatibleAssign + } + + errorf := func(format string, args ...any) { + if check != nil && reason != nil { + msg := check.sprintf(format, args...) + if *reason != "" { + msg += "\n\t" + *reason + } + *reason = msg } } + // 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 to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true + }) + 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 := 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 (in %s) to %s", V.typ, Vp, T) + return false + } + return true + }) + return ok, code + } + return false, _IncompatibleAssign } diff --git a/src/go/types/pointer.go b/src/go/types/pointer.go new file mode 100644 index 0000000000000000000000000000000000000000..6352ee57e2c832ca0e3eea4aa2106a9aeba42675 --- /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/predicates.go b/src/go/types/predicates.go index 7bb026414f8c36366b47cf164236662dbe5e9dc9..22ccdd7744db6951a825a02aecf5c35f5b05902e 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -6,84 +6,100 @@ 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 { - switch typ.(type) { - case *Basic, *Named, *_TypeParam, *instance: - return true - } - return false +import "go/token" + +// 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 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) } +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., +// 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 } -// 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.tparams != nil && named.targs == nil +// 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(structuralType(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) } +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(structuralType(t), info). +func allBasic(t Type, info BasicInfo) bool { + if tpar, _ := t.(*TypeParam); tpar != nil { + return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) + } + return isBasic(t, info) } -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) }) +// 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 } -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 list 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 +// 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()! - // 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 + // set up. Must not call under()! + 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 isOrdered(typ Type) bool { return is(typ, IsOrdered) } +// IsInterface reports whether t is an interface type. +func IsInterface(t Type) bool { + _, ok := under(t).(*Interface) + return ok +} -func isConstType(typ Type) bool { - // Type parameters are never const types. - t, _ := under(typ).(*Basic) - return t != nil && t.info&IsConstType != 0 +// isTypeParam reports whether t is a type parameter. +func isTypeParam(t Type) bool { + _, ok := t.(*TypeParam) + return ok } -// IsInterface reports whether typ is an interface type. -func IsInterface(typ Type) bool { - return asInterface(typ) != nil +// 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. @@ -100,24 +116,12 @@ 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), - // T is comparable if it has the == method. Otherwise, - // the underlying type "wins". For instance - // - // interface{ comparable; type []byte } - // - // is not comparable because []byte is not comparable. - 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 return t.kind != UntypedNil - case *Pointer, *Interface, *Chan: + case *Pointer, *Chan: return true case *Struct: for _, f := range t.fields { @@ -128,42 +132,27 @@ 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 { - return comparable(t, seen) - } - return t.is(pred) - case *_TypeParam: - return t.Bound()._IsComparable() + case *Interface: + return !isTypeParam(T) || t.IsComparable() } return false } -// hasNil reports whether a type includes the nil value. -func hasNil(typ Type) bool { - switch t := optype(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 - case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: + return u.kind == UnsafePointer + case *Slice, *Pointer, *Signature, *Map, *Chan: return true - case *_Sum: - return t.is(hasNil) + case *Interface: + return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool { + return u != nil && hasNil(u) + }) } 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 @@ -175,11 +164,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 { - // types must be expanded for comparison - x = expandf(x) - y = expandf(y) - +func identical(x, y Type, cmpTags bool, p *ifacePair) bool { if x == y { return true } @@ -199,13 +184,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: @@ -220,7 +205,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 } } @@ -231,7 +216,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: @@ -242,7 +227,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 } } @@ -252,57 +237,79 @@ func (check *Checker) identical0(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 && - check.identicalTParams(x.tparams, y.tparams, cmpTags, p) && - check.identical0(x.params, y.params, cmpTags, p) && - check.identical0(x.results, y.results, cmpTags, p) + y, _ := y.(*Signature) + if y == nil { + return false } - 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 - // 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) { - // 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) { - continue L // x is in y.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, 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 } - return false // x is not in y.types } - return true + + 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) + 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: + // // 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 { - // 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) + xset := x.typeSet() + yset := y.typeSet() + if !xset.terms.equal(yset.terms) { + return false } - a := x.allMethods - b := y.allMethods + 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 @@ -339,7 +346,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 } } @@ -350,37 +357,50 @@ 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: // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { + xargs := x.TypeArgs().list() + yargs := y.TypeArgs().list() + + 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. 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: - // 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 nil: // avoid a crash in case of nil type @@ -391,25 +411,28 @@ 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 { - if len(x) != len(y) { +// 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, x := range x { - y := y[i] - if !check.identical0(x.typ.(*_TypeParam).bound, y.typ.(*_TypeParam).bound, cmpTags, p) { + + for i, xa := range xargs { + if !Identical(xa, yargs[i]) { return false } } - return true + + return Identical(xorig, yorig) } // 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] @@ -425,5 +448,5 @@ func Default(typ Type) Type { return Typ[String] } } - return typ + return t } diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 114647a2fffecb937bd785c3d85e3467626499a4..7a2dcbffbb17e172de42d720a1adb38f9d4bd253 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 } @@ -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 } } } @@ -377,12 +381,15 @@ func (check *Checker) collectObjects() { check.declarePkgObj(name, obj, di) } case typeDecl: + if d.spec.TypeParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) { + 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}) 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 { @@ -394,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.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 { // TODO(rFindley) Should this be a hard error? @@ -431,6 +439,10 @@ 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], _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 // object map so that we can handle them like regular functions (if the // receiver is invalid); also we need their fdecl info when associating @@ -443,8 +455,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) @@ -470,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) } } @@ -499,10 +512,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.IndexListExpr: + 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,9 +525,9 @@ 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) + 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/sanitize.go b/src/go/types/sanitize.go deleted file mode 100644 index 727ec173eac81a4077be56e5f1a1affe9372e88b..0000000000000000000000000000000000000000 --- 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 := getInferred(info) - 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, *bottom, *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 *_Sum: - s.typeList(t.types) - - 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 { - t.allTypes = allTypes - } - - 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") - } - if orig := s.typ(t.orig); orig != t.orig { - t.orig = 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/scope.go b/src/go/types/scope.go index 26c28d1c4e3c46437d8640b893137ef3b0ccdcef..010727eb722a7bf81756e9ff17aa8e02a949f07b 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 @@ -22,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 @@ -31,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 } @@ -66,7 +69,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 +84,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 +98,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 +139,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 +219,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 +237,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/self_test.go b/src/go/types/self_test.go index 262dc7b97abe931c49dc916681ed98b62befd745..a1af85f27b03609eecc61b71417e81afefbd8dc4 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) } } @@ -41,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) { diff --git a/src/go/types/signature.go b/src/go/types/signature.go new file mode 100644 index 0000000000000000000000000000000000000000..8f89e931fbb61d5b8583f30200a7f91678ba746c --- /dev/null +++ b/src/go/types/signature.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 types + +import ( + "go/ast" + "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 *TypeParamList // receiver type parameters from left to right, or nil + tparams *TypeParamList // type parameters from left to right, or nil + 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 + 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 +// 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 { + panic("variadic function must have at least one parameter") + } + if _, ok := params.At(n - 1).typ.(*Slice); !ok { + panic("variadic parameter must be of unnamed slice type") + } + } + 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 +// 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 } + +// TypeParams returns the type parameters of signature s, or nil. +func (s *Signature) TypeParams() *TypeParamList { return s.tparams } + +// RecvTypeParams returns the receiver type parameters of signature s, or nil. +func (s *Signature) RecvTypeParams() *TypeParamList { return s.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 (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") + check.scope.isFunc = true + check.recordScope(ftyp, check.scope) + sig.scope = check.scope + defer check.closeScope() + + 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 { + 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.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.recvTParamMap == nil { + check.recvTParamMap = make(map[*ast.Ident]*TypeParam) + } + check.recvTParamMap[p] = tpar + } + } + // determine receiver type to get its type parameters + // and the respective type parameter bounds + 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 + // again when we type-check the signature. + // TODO(gri) maybe the receiver should be marked as invalid instead? + if recv, _ := check.genericType(rname, nil).(*Named); recv != nil { + recvTParams = recv.TypeParams().list() + } + } + // provide type parameter bounds + // - only do this if we have the right number (otherwise an error is reported elsewhere) + if sig.RecvTypeParams().Len() == len(recvTParams) { + // We have a list of *TypeNames but we need a list of Types. + 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() { + bound := recvTParams[i].bound + // bound is (possibly) parameterized in the context of the + // receiver type declaration. Substitute parameters for the + // current context. + tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil) + } + } + } + } + + if ftyp.TypeParams != nil { + 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.) + if recvPar != nil { + check.errorf(ftyp.TypeParams, _InvalidMethodTypeParams, "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, 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) + }) + + 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) + + // 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 rtyp != Typ[Invalid] { + var err string + switch T := rtyp.(type) { + case *Named: + 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 { + 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 + // 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 { + // 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 + } + return true + }) + } + 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 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. +func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) { + if list == nil { + return + } + + var named, anonymous bool + for i, field := range list.List { + ftype := field.Type + 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 +} diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 5a9d07ca41802a9edbf292a9b0f0d738e86d268f..69571d1159d0674854a49a52b087cec260d45f26 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}, @@ -25,30 +25,29 @@ func TestSizeof(t *testing.T) { {Struct{}, 24, 48}, {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, - {Signature{}, 44, 88}, - {_Sum{}, 12, 24}, - {Interface{}, 60, 120}, + {Signature{}, 28, 56}, + {Union{}, 16, 32}, + {Interface{}, 44, 88}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 64, 128}, - {_TypeParam{}, 28, 48}, - {instance{}, 44, 88}, - {bottom{}, 0, 0}, - {top{}, 0, 0}, + {Named{}, 68, 128}, + {TypeParam{}, 28, 48}, + {term{}, 12, 24}, // Objects {PkgName{}, 48, 88}, {Const{}, 48, 88}, {TypeName{}, 40, 72}, {Var{}, 44, 80}, - {Func{}, 44, 80}, + {Func{}, 48, 88}, {Label{}, 44, 80}, {Builtin{}, 44, 80}, {Nil{}, 40, 72}, // Misc - {Scope{}, 40, 80}, + {Scope{}, 44, 88}, {Package{}, 40, 80}, + {_TypeSet{}, 28, 56}, } for _, test := range tests { got := reflect.TypeOf(test.val).Size() diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index 67052bb816e0935167cd0e204731a247e2a6a50b..dd4b78969f6844d8674f10201149331ac4c13ecb 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." @@ -67,12 +67,17 @@ func (s *StdSizes) Alignof(T Type) int64 { case *Slice, *Interface: // Multiword data structures are effectively structs // in which each element has size WordSize. + // 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. 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 +123,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 +153,13 @@ 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 *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() } return s.WordSize // catch-all } @@ -241,7 +249,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/slice.go b/src/go/types/slice.go new file mode 100644 index 0000000000000000000000000000000000000000..debdd81586cce0fb39c4df553250f8b952c286bb --- /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/stdlib_test.go b/src/go/types/stdlib_test.go index d86a77a110f7a7f9f68083e2c8d1545b6c6adfd9..5e5e09562ac5a7f0b74ba95eb8b7eca633a7e46b 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) } @@ -167,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 ) } @@ -195,6 +196,10 @@ 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 + "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 ) } @@ -291,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) @@ -301,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 47f6dcfbd1ce8f6f5b25f0da36a2ef144afb1feb..8621d2800a54ac8edb3c0306b4889b1d7eb64a45 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 { @@ -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, @@ -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) @@ -65,7 +60,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) } @@ -178,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 @@ -197,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 @@ -231,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 @@ -264,7 +260,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 @@ -275,24 +271,38 @@ 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) 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 { - 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 @@ -307,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 @@ -340,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 { @@ -360,25 +411,27 @@ 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) + u := structuralType(ch.typ) + if u == nil { + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to %s: no structural type", &ch) return } - - if tch.dir == RecvOnly { - check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to receive-only type %s", tch) + uch, _ := u.(*Chan) + if uch == nil { + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-channel %s", &ch) return } - - check.assignment(&x, tch.elem, "send") + 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 @@ -397,7 +450,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 } @@ -466,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") @@ -513,7 +566,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) @@ -632,12 +685,16 @@ 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) return } - check.ordinaryType(&x, xtyp) check.multipleDefaults(s.Body.List) @@ -746,7 +803,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") } } @@ -774,20 +831,28 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { // determine key/value types var key, val Type if x.mode != invalid { - 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 + // 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 = 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) + // 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 } } @@ -872,71 +937,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) { - switch typ := typ.(type) { +// 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, "" - case *Pointer: - if typ := asArray(typ.base); typ != nil { - 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 = "send-only channel" - } - return typ.elem, Typ[Invalid], msg - case *_Sum: - first := true - var key, val Type - var msg string - typ.is(func(t Type) bool { - k, v, m := rangeKeyVal(under(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 + return typ.elem, Typ[Invalid] } - return nil, nil, "" + return } diff --git a/src/go/types/struct.go b/src/go/types/struct.go new file mode 100644 index 0000000000000000000000000000000000000000..d6c56341f05e12fa0f09ddaed742f8d833b39afb --- /dev/null +++ b/src/go/types/struct.go @@ -0,0 +1,217 @@ +// Copyright 2021 The Go Authors. 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" +) + +// ---------------------------------------------------------------------------- +// API + +// A Struct represents a struct type. +type Struct struct { + 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 +} + +// 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") + } + s := &Struct{fields: fields, tags: tags} + s.markComplete() + return s +} + +// 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 (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 + } + + // 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 { + check.invalidAST(f.Type, "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 u := under(t).(type) { + case *Basic: + if t == Typ[Invalid] { + // error was reported before + return + } + // unsafe.Pointer is treated like a regular pointer + 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 *Interface: + 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 + } + if isPtr { + check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") + } + } + }).describef(embeddedPos, "check embedded type %s", embeddedTyp) + } + } + + styp.fields = fields + styp.tags = tags + styp.markComplete() +} + +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) + case *ast.IndexListExpr: + 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/subst.go b/src/go/types/subst.go index 931375f1f2b9873304975e85b5eb78991273e002..169540365b69b2472264a24f29d88b888099ce90 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -2,218 +2,43 @@ // 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 -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 -} +import "go/token" + +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(map[*_TypeParam]Type, len(tpars)) + proj := make(substMap, 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] = targs[i] } - return &substMap{targs, proj} + return proj } -func (m *substMap) String() string { - return fmt.Sprintf("%s", m.proj) +func (m substMap) empty() bool { + return len(m) == 0 } -func (m *substMap) empty() bool { - return len(m.proj) == 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 } -func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist []token.Pos) (res Type) { - 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 = 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: - check.dump("%v: cannot instantiate %v", pos, typ) - unreachable() // only defined types and (defined) functions can be generic - } - - // 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 len(tparams) == 0 { - return typ // nothing to do (minor optimization) - } - - smap := makeSubstMap(tparams, targs) - - // 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 - } - } - - // targ's underlying type must also be one of the interface types listed, if any - if iface.allTypes == nil { - continue // 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) - 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 - } - } - 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(atPos(pos), _Todo, "%s does not satisfy %s (%s or %s not found in %s)", targ, tpar.bound, targ, under(targ), iface.allTypes) - break - } - } - - return check.subst(pos, typ, smap) -} - -// 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. -func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap) 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 the incoming 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 } @@ -222,20 +47,25 @@ 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) } // general case - subst := subster{check, pos, make(map[Type]Type), smap} + subst := subster{ + pos: pos, + smap: smap, + check: check, + ctxt: check.bestContext(ctxt), + } return subst.typ(typ) } type subster struct { - check *Checker pos token.Pos - cache map[Type]Type - smap *substMap + smap substMap + check *Checker // nil if called via Instantiate + ctxt *Context } func (subst *subster) typ(typ Type) Type { @@ -244,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, *bottom, *top: + case *Basic: // nothing to do case *Array: @@ -261,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: @@ -282,10 +114,9 @@ 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? - tparams: t.tparams, - scope: t.scope, + // TODO(rFindley) why can't we nil out tparams here, rather than in instantiate? + tparams: t.tparams, + // instantiated signatures have a nil scope recv: recv, params: params, results: results, @@ -293,26 +124,20 @@ func (subst *subster) typ(typ Type) Type { } } - case *_Sum: - types, copied := subst.typeList(t.types) + case *Union: + terms, copied := subst.termlist(t.terms) 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) + // 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: 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} - subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement - subst.check.completeInterface(token.NoPos, iface) + if mcopied || ecopied { + iface := &Interface{methods: methods, embeddeds: embeddeds, implicit: t.implicit, complete: t.complete} return iface } @@ -330,85 +155,81 @@ 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, ...any) {} + if subst.check != nil && trace { + subst.check.indent++ + defer func() { + subst.check.indent-- + }() + dump = func(format string, args ...any) { subst.check.trace(subst.pos, format, args...) } } - if t.tparams == nil { + // 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 - - if len(t.targs) > 0 { - // already instantiated - dump(">>> %s already instantiated", t) - 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. - 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, len(t.tparams)) - copy(newTargs, t.targs) - } - newTargs[i] = newTarg + var newTArgs []Type + if t.targs.Len() != t.orig.TypeParams().Len() { + return Typ[Invalid] // error reported elsewhere + } + + // 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.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.orig.TypeParams().Len()) + copy(newTArgs, t.targs.list()) } + 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 := subst.ctxt.instanceHash(t.orig, newTArgs) dump(">>> new type hash: %s", h) - if named, found := subst.check.typMap[h]; found { + if named := subst.ctxt.lookup(h, t.orig, newTArgs); named != nil { dump(">>> found %s", named) - subst.cache[t] = named return named } - // 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.targs = newTargs - subst.check.typMap[h] = named - subst.cache[t] = named - - // 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) + // 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.ctxt) + return subst.check.instance(subst.pos, t.orig, newTArgs, subst.ctxt) - return named + // 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. - case *_TypeParam: + 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") } @@ -416,37 +237,6 @@ func (subst *subster) typ(typ Type) Type { return typ } -// TODO(gri) Eventually, this should be more sophisticated. -// It won't work correctly for locally declared types. -func instantiatedHash(typ *Named, targs []Type) string { - var buf bytes.Buffer - writeTypeName(&buf, typ.obj, nil) - buf.WriteByte('[') - writeTypeList(&buf, targs, nil, nil) - buf.WriteByte(']') - - // 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++ - } - } - - 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. @@ -541,3 +331,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] = NewTerm(t.tilde, u) + } + } + return +} diff --git a/src/go/types/termlist.go b/src/go/types/termlist.go new file mode 100644 index 0000000000000000000000000000000000000000..c4ab0e037e300aed0c173eb476e945e97877f630 --- /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 + +// 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, +// 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 + } + 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 0000000000000000000000000000000000000000..dddca7a68201d609b4219c9ab0e2f663596f3031 --- /dev/null +++ b/src/go/types/termlist_test.go @@ -0,0 +1,313 @@ +// Copyright 2021 The Go Authors. 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.ReplaceAll(s, " ", "") + names := strings.Split(s, "∪") + r := make(termlist, len(names)) + for i, n := range names { + r[i] = testTerm(n) + } + return r +} + +func TestTermlistAll(t *testing.T) { + if !allTermlist.isAll() { + t.Errorf("allTermlist is not the set of all types") + } +} + +func TestTermlistString(t *testing.T) { + for _, want := range []string{ + "∅", + "𝓤", + "int", + "~int", + "myInt", + "∅ ∪ ∅", + "𝓤 ∪ 𝓤", + "∅ ∪ 𝓤 ∪ int", + "∅ ∪ 𝓤 ∪ int ∪ myInt", + } { + 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, + "∅ ∪ ∅ ∪ myInt": false, + "𝓤": false, + "𝓤 ∪ int": false, + "𝓤 ∪ myInt ∪ ∅": false, + } { + xl := maketl(test) + got := xl.isEmpty() + if got != want { + t.Errorf("(%v).isEmpty() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistIsAll(t *testing.T) { + for test, want := range map[string]bool{ + "∅": false, + "∅ ∪ ∅": false, + "int ∪ ~string": false, + "~int ∪ myInt": false, + "∅ ∪ ∅ ∪ 𝓤": true, + "𝓤": true, + "𝓤 ∪ int": true, + "myInt ∪ 𝓤": true, + } { + xl := maketl(test) + got := xl.isAll() + if got != want { + t.Errorf("(%v).isAll() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistNorm(t *testing.T) { + for _, test := range []struct { + xl, want string + }{ + {"∅", "∅"}, + {"∅ ∪ ∅", "∅"}, + {"∅ ∪ 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() + if got.String() != test.want { + t.Errorf("(%v).norm() = %v; want %v", xl, got, test.want) + } + } +} + +func TestTermlistSingleType(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", + "myInt": "myInt", + "~int": "int", + "~int ∪ string": "nil", + "~int ∪ myInt": "int", + "∅ ∪ int": "int", + "∅ ∪ ~int": "int", + "∅ ∪ ~int ∪ string": "nil", + } { + xl := maketl(test) + got := tstring(xl.singleType()) + if got != want { + t.Errorf("(%v).singleType() == %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", "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) + 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", "∅"}, + {"∅", "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) + 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}, + {"𝓤 ∪ myInt", "string ∪ 𝓤", true}, + {"int ∪ ~string", "string ∪ int", false}, + {"~int ∪ string", "string ∪ myInt", 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", "myInt", true}, + {"int ∪ string", "string", true}, + {"~int ∪ string", "int", true}, + {"~int ∪ string", "myInt", true}, + {"~int ∪ myInt ∪ ∅", "myInt", true}, + {"myInt ∪ ∅ ∪ 𝓤", "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}, + {"𝓤", "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 ∪ ∅ ∪ 𝓤", "myInt", 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", "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}, + {"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) + got := xl.subsetOf(yl) + if got != test.want { + t.Errorf("(%v).subsetOf(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index 3918d836b5277a8a71d46380b441b1a29d409bd7..c1accff016a8a54b4a393085e872bf665deae1b9 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -6,48 +6,269 @@ package builtins -type Bmc interface { - type map[rune]string, chan int +import "unsafe" + +// 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) } -type Bms interface { - type map[string]int, []int +func _[T C5[X], X any](ch T) { + close(ch) } -type Bcs interface { - type chan bool, []float64 +// copy + +func _[T any](x, y T) { + copy(x /* ERROR copy expects slice arguments */ , y) } -type Bss interface { - type []int, []string +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 /* ERROR different element types */ , x3) } -func _[T any] () { - _ = make(T /* ERROR invalid argument */ ) - _ = make(T /* ERROR invalid argument */ , 10) - _ = make(T /* ERROR invalid argument */ , 10, 20) +func _[T ~[]E, E any](x T, y []E) { + copy(x, y) + copy(x /* ERROR different element types */ , "foo") } -func _[T Bmc] () { - _ = make(T) - _ = make(T, 10) - _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20) +func _[T ~string](x []byte, y T) { + copy(x, y) + copy(y /* ERROR expects slice arguments */ , x) } -func _[T Bms] () { - _ = make /* ERROR expects 2 arguments */ (T) - _ = make(T, 10) - _ = make /* ERROR expects 2 arguments */ (T, 10, 20) +func _[T ~[]byte|~string](x T, y []byte) { + copy(x /* ERROR expects slice arguments */ , y) + copy(y, x) } -func _[T Bcs] () { - _ = make /* ERROR expects 2 arguments */ (T) - _ = make(T, 10) - _ = make /* ERROR expects 2 arguments */ (T, 10, 20) +type L0 []int +type L1 []int + +func _[T L0 | L1](x, y T) { + copy(x, y) } -func _[T Bss] () { - _ = make /* ERROR expects 2 or 3 arguments */ (T) - _ = make(T, 10) - _ = make(T, 10, 20) +// 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 myChan chan int + +func _[ + S1 ~[]int, + S2 ~[]int | ~chan int, + + M1 ~map[string]int, + M2 ~map[string]int | ~chan int, + + C1 ~chan int, + C2 ~chan int | ~chan string, + C3 chan int | myChan, // single underlying type +]() { + 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 S2: 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 M2: 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 C2: no structural type */ ) + _ = make(C3) +} + +// 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/check/builtins.src b/src/go/types/testdata/check/builtins.src index 370752891407beef0f7d828a128144617c4796c9..7fd6a4b03297ba2385f4e62ba4aecd450834c337 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/testdata/check/compliterals.go2 b/src/go/types/testdata/check/compliterals.go2 new file mode 100644 index 0000000000000000000000000000000000000000..60eac97a3f2084ef2e58302f79ecd25bc7c19211 --- /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}} +} diff --git a/src/go/types/testdata/check/const0.src b/src/go/types/testdata/check/const0.src index 5608b1549ba8d7774c2463fa9faab3702673f061..3cffdf904c87feb265ee5b1293d07be185e17372 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/cycles.src b/src/go/types/testdata/check/cycles.src index 218b4cad6abe6b4fdf6eb57d3f9c07f8274d078d..27b6111822948bc0556afdd8096903f8eb0c92bc 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/testdata/check/cycles4.src b/src/go/types/testdata/check/cycles4.src index 445babca68bc3db73a1cc192f366480171fbc659..924aabf475f9640cdfa6da8834fa9a8db6aa0a2b 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/testdata/check/decls0.src b/src/go/types/testdata/check/decls0.src index 5ad8f53f65ab20b5e21b753119df153a67bd206b..18f0d32e1b4a5a878c65a5e8253b12cd8a54a8a5 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" @@ -146,7 +146,7 @@ type ( m1(I5) } I6 interface { - S0 /* ERROR "not an interface" */ + S0 /* ERROR "non-interface type S0" */ } I7 interface { I1 @@ -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 { diff --git a/src/go/types/testdata/check/decls1.src b/src/go/types/testdata/check/decls1.src index f4d2eaba91150a5c82780e536716e21ab09f43ef..6fe349b0b2fda71f7c6369ed4f139b6bc4737496 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/errors.src b/src/go/types/testdata/check/errors.src index ff929217c4c865ae18f8b918ee720762f15cf3cc..7cdc5fb5fff3115d7255059a9e2713e78a188a93 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/expr1.src b/src/go/types/testdata/check/expr1.src index 4ead815158f61e2dbbb91dec8e7feabef4a3923c..42b95fbb37bec2810aaff3a75b73d2e2ca79b8fc 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 0c959e8011944f0ce42b89bc193e448628bc762f..8757fd9e487f3c7d1aac003b87cc04beb9dba87f 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 @@ -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 diff --git a/src/go/types/testdata/check/expr3.src b/src/go/types/testdata/check/expr3.src index 0525a5a33ae09012954ff7aa7c8b0d1e89733356..b8f96dc6113e51ed739dc5fc1bd0db0f1e84253f 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 @@ -103,14 +103,14 @@ 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] _ = 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 @@ -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) @@ -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/tinference.go2 b/src/go/types/testdata/check/funcinference.go2 similarity index 53% rename from src/go/types/testdata/check/tinference.go2 rename to src/go/types/testdata/check/funcinference.go2 index 31338b33ad652fd5dd51917be1653088e18065d9..f04b76ca1a9812edf2237fc1aef2c647b960e9f2 100644 --- a/src/go/types/testdata/check/tinference.go2 +++ b/src/go/types/testdata/check/funcinference.go2 @@ -2,45 +2,43 @@ // 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{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") + f("a", nil, nil, nil) + f0("a", nil, nil, nil) } -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)) + f(int(0), new(int)) + f1(int(0), new(int)) } -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 _() { - 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{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,26 +46,24 @@ 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 { panic(0) } 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 { panic(0) } func _() { x := f6(struct{f []string}{}) 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{type A}]() +func f7[A interface{*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,14 +79,14 @@ var _ = Double(MySlice{1}) type Setter[B any] interface { Set(string) - type *B + ~*B } 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/issues.go2 b/src/go/types/testdata/check/issues.go2 index 8994164eacf5f9cd4bf2838b2b47442c2bc3ae6e..371856eea34333b2fa3c414b88a3543c977a21e2 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -24,55 +24,46 @@ 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. -// 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() 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]() } // 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{type uint}] struct{} +type T1[P interface{~uint}] struct{} func _[P any]() { - _ = T1[P /* ERROR P has no type constraints */ ]{} + _ = T1[P /* ERROR empty interface P does not implement interface{~uint} */ ]{} } // This is the original (simplified) program causing the same issue. type Unsigned interface { - type uint + ~uint } type T2[U Unsigned] struct { @@ -83,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 empty interface U does not implement Unsigned */ ] { + return T2[U /* ERROR empty interface U does not implement Unsigned */ ]{} } func _() { @@ -154,16 +145,16 @@ 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 // 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{type int, uint, float32}](v T1) T2 { +func convert[T1, T2 interface{~int | ~uint | ~float32}](v T1) T2 { return T2(v) } @@ -175,12 +166,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 +180,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 { +// 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{type int}](x T) { +func _[T interface{~int}](x T) { type myint int var _ int = int(x) var _ T = 42 @@ -210,38 +201,45 @@ 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() } -// We must compare against the underlying type of type list entries +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 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. -type sliceOf[E any] interface{ type []E } +type sliceOf[E any] interface{ ~[]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{}](s S, t ...T2) S { panic(0) } var f func() var cancelSlice []context.CancelFunc @@ -249,7 +247,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/issues.src b/src/go/types/testdata/check/issues.src index 55fe220337f47fba7342b0cb324ffc1c6301792b..88ce452959845dd77e2ba9ccfac917dcfcf8df26 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" @@ -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/linalg.go2 b/src/go/types/testdata/check/linalg.go2 index 0d27603a5837a2747922d9c1e52802b840ca8c4e..f02e773dbeeeebbafde08ab38ac4cef93f11897a 100644 --- a/src/go/types/testdata/check/linalg.go2 +++ b/src/go/types/testdata/check/linalg.go2 @@ -4,15 +4,13 @@ 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 { - 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,42 +40,43 @@ 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 -} - -// 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 + ~complex64 | ~complex128 } -// 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/main.go2 b/src/go/types/testdata/check/main.go2 index 65e9aa29629faefa5b78c5a4eaaab98239b9e304..fb567a07d085a32493b7126995a13b1a0a39962f 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/map2.go2 b/src/go/types/testdata/check/map2.go2 index 2833445662de813d6d3eeed95978c8342316b29f..e13bf33feda9edb1f87910f9bda04d4f7908bd9e 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/stmt0.src b/src/go/types/testdata/check/stmt0.src index 76b6e70d63bacd703871aedfc02778196a7b5e6a..c7a718de70e50286ef53d68f0888b5b8a1b68ce8 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() { @@ -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< 0 { x0 = x[0] @@ -118,9 +118,9 @@ func max[T interface{ type 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 b4f3369aa0c2560ca5b8821dc6a949055ba19aee..ffa30ee2cb03407c528399fb0a1b3daf60480360 100644 --- a/src/go/types/testdata/examples/inference.go2 +++ b/src/go/types/testdata/examples/inference.go2 @@ -7,10 +7,10 @@ package p type Ordered interface { - type int, float64, string + ~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{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. @@ -97,5 +97,28 @@ 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 + +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/testdata/examples/methods.go2 b/src/go/types/testdata/examples/methods.go2 index 76c6539e1b7e7de019b7031025274eee082be8d7..1d76d553dcc44a1b57f2f983edefa404c39ab534 100644 --- a/src/go/types/testdata/examples/methods.go2 +++ b/src/go/types/testdata/examples/methods.go2 @@ -94,3 +94,19 @@ func (_ T2[_, _, _]) _() int { return 42 } type T0 struct{} func (T0) _() {} func (T1[A]) _() {} + +// 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/operations.go2 b/src/go/types/testdata/examples/operations.go2 new file mode 100644 index 0000000000000000000000000000000000000000..18e4d6080c59f0307c55e94bf389e4109eb88a7f --- /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 +} diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 59c8804ad279597f3e3e0ce80bd5e05ad2d79b00..33642fa42fd071cf8a181b0d308423e11bf4fec9 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. @@ -113,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 { @@ -161,31 +162,42 @@ 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(); type 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 +//} + +// 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 @@ -208,19 +220,19 @@ 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]]() -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 @@ -238,11 +250,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 */ ) @@ -270,10 +282,10 @@ 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 { type int, float64 }]() { +func _[T interface {~int|~float64}]() { // not valid const _ = T /* ERROR not constant */ (0) const _ T /* ERROR invalid constant type T */ = 1 @@ -284,3 +296,26 @@ func _[T interface { type 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}, {}} +} + +// 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/testdata/examples/typesets.go2 b/src/go/types/testdata/examples/typesets.go2 new file mode 100644 index 0000000000000000000000000000000000000000..cf01072d8cb06003ea8a8e7a0a5a19fd86c716ff --- /dev/null +++ b/src/go/types/testdata/examples/typesets.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. + +// 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 */ ]() {} + +// 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/testdata/fixedbugs/issue28251.src b/src/go/types/testdata/fixedbugs/issue28251.src index cd79e0e8b5d299e905628654369e8df0db5477fe..ef5e61df47f2c5e332a5db29e82f24bccadbd5e0 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 */ () } diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index a13ed13ce5f3dbf5df418a8296b76f4523ec71e2..2de2f4378aac0a8206b0ec2d99fd8eab719bbc26 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -31,13 +31,14 @@ type x7[A any] struct{ foo7 } func main7() { var _ foo7 = x7[int]{} } // crash 8 -type foo8[A any] interface { type 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 { type foo9 /* ERROR interface contains type constraints */ [A] } -func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [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 */ @@ -49,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() } @@ -57,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 _ */ ]) @@ -73,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 @@ -84,8 +86,11 @@ 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 -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/issue39680.go2 b/src/go/types/testdata/fixedbugs/issue39680.go2 index 9bc26f35461345eb2f0d5728ba39fe793774723d..e56bc3547582d190f110b6f70a231e9e38012572 100644 --- a/src/go/types/testdata/fixedbugs/issue39680.go2 +++ b/src/go/types/testdata/fixedbugs/issue39680.go2 @@ -4,16 +4,19 @@ package p +// Embedding stand-alone type parameters is not permitted for now. Disabled. + +/* 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) { @@ -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/issue39693.go2 b/src/go/types/testdata/fixedbugs/issue39693.go2 index 316ab1982e89cf3635b1b1b16b3356f70a4d2b4f..ec7641902a12f3549eca15af28fda8a8ae808ebc 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/issue39699.go2 b/src/go/types/testdata/fixedbugs/issue39699.go2 index 75491e7e26f00cd5b1d0ce771d471724ae7cdf9e..72f83997c2460a5496556cb1d294b9e260550c5d 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/issue39711.go2 b/src/go/types/testdata/fixedbugs/issue39711.go2 index df621a4c1730db66648dd23c898a1238bdfce332..d85fa03fc433bc77d34c4e16f4fbb923cfee8d32 100644 --- a/src/go/types/testdata/fixedbugs/issue39711.go2 +++ b/src/go/types/testdata/fixedbugs/issue39711.go2 @@ -4,8 +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 { - 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 term 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 55464e6b7759f09016050e541868a72b50e1dca1..00885238e69c9a26ce5ef6f44539c0cba86152b1 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{ ~int }, B A /* ERROR cannot use a type parameter as constraint */ ]() {} diff --git a/src/go/types/testdata/fixedbugs/issue39725.go2 b/src/go/types/testdata/fixedbugs/issue39725.go2 index e19b6770bfe4bd21462434f97ace29659a02c4ed..62dc45a59601eecc43e0b23fd09123cf00fbf57d 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/issue39754.go2 b/src/go/types/testdata/fixedbugs/issue39754.go2 index 4b4420d9973aaf5e579d98016e181023f0b25325..9edd239d7d97c2e3e00bd6031327f180939494b0 100644 --- a/src/go/types/testdata/fixedbugs/issue39754.go2 +++ b/src/go/types/testdata/fixedbugs/issue39754.go2 @@ -16,9 +16,6 @@ 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]] - // 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[int, Optional[int], Optional /* ERROR does not implement Box */ [string]] + _ = f[int, Optional[int], Optional /* ERROR Optional.* does not implement Box.* */ [string]] } diff --git a/src/go/types/testdata/fixedbugs/issue39755.go2 b/src/go/types/testdata/fixedbugs/issue39755.go2 index b7ab68818e9587897e7f916730644a3dc1f0af8b..257b73a2fbeff15a934f4daf4798952578bad9d5 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/issue39768.go2 b/src/go/types/testdata/fixedbugs/issue39768.go2 index abac141d7f08dd359a26ba18c36b696d7970d40a..696d9d9beef9d2f9961456e1ddf3ed6f31c51889 100644 --- a/src/go/types/testdata/fixedbugs/issue39768.go2 +++ b/src/go/types/testdata/fixedbugs/issue39768.go2 @@ -4,17 +4,18 @@ package p -type T[P any] P -type A = T -var x A[int] -var _ A /* ERROR cannot use generic type */ - -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 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/issue39938.go2 b/src/go/types/testdata/fixedbugs/issue39938.go2 index 76e7e369ca12bb6718272a2de41dfc7f6617d848..114646786d5b74324413b74cbbca0c211f3c6cb2 100644 --- a/src/go/types/testdata/fixedbugs/issue39938.go2 +++ b/src/go/types/testdata/fixedbugs/issue39938.go2 @@ -3,19 +3,21 @@ // 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 -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 } +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/issue39948.go2 b/src/go/types/testdata/fixedbugs/issue39948.go2 index c2b460902cc643b5537834e489f3213f551fe6f7..e38e57268d63d1fd00012274bd8ea23bc2a7c7df 100644 --- a/src/go/types/testdata/fixedbugs/issue39948.go2 +++ b/src/go/types/testdata/fixedbugs/issue39948.go2 @@ -5,5 +5,5 @@ 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/issue39976.go2 b/src/go/types/testdata/fixedbugs/issue39976.go2 index 3db4eae0123930db81b5ff193e58ff802678878a..d703da90a2176a3e975f5a62cad5cf5b3f665faf 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 8948d61caa477fff40ac7f773946d0377df734e4..5f81fcbfaa7236bfcdd58114ac74847f9e709555 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 f587691e3d746a58bc22a2bfd6d9382230859d3c..66130c0a558ebaef7ec875d3072a818a65b16ff3 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/issue40301.go2 b/src/go/types/testdata/fixedbugs/issue40301.go2 index 5d97855f8a172ff414ae86c5112b500059a3142b..c78f9a1fa040892e7ebec27753100db2867752b2 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) } diff --git a/src/go/types/testdata/fixedbugs/issue40684.go2 b/src/go/types/testdata/fixedbugs/issue40684.go2 index 0269c3a62ce6d0d10d92f0f2cb4e0ce8e82129cf..63a058d039d93448f745ec2ecc1d091dae93da13 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/issue40789.go2 b/src/go/types/testdata/fixedbugs/issue40789.go2 new file mode 100644 index 0000000000000000000000000000000000000000..9eea4ad60a6647380606f70fd998febab618db8c --- /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/testdata/fixedbugs/issue41124.go2 b/src/go/types/testdata/fixedbugs/issue41124.go2 index 61f766bcbd7891ef16f8ca6396349e1ff43159f6..7f55ba85a6b42d4580a030337e5bba3e1da71713 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 Zero, Succ +type Nat /* ERROR cycle */ interface { + Zero|Succ } 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. @@ -22,7 +22,7 @@ type I1 interface { } type I2 interface { - type int + ~int } type I3 interface { @@ -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{} @@ -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/issue42758.go2 b/src/go/types/testdata/fixedbugs/issue42758.go2 index 698cb8a16bad26194a40f5893e7a1d493b30083c..dd66e9648b56326f364b4ade15b459a506a5bb9d 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{}){ @@ -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/testdata/fixedbugs/issue43527.go2 b/src/go/types/testdata/fixedbugs/issue43527.go2 new file mode 100644 index 0000000000000000000000000000000000000000..e4bcee51fe5f90420af7c385a53e748f485a4edc --- /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/testdata/fixedbugs/issue43671.go2 b/src/go/types/testdata/fixedbugs/issue43671.go2 new file mode 100644 index 0000000000000000000000000000000000000000..46ac51ebdd2df27b2007ce66c953b460e693c4e8 --- /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 ch .* no structural type +} + +func _[T C0](ch T) { + <-ch // ERROR cannot receive from non-channel ch +} + +func _[T C1](ch T) { + <-ch +} + +func _[T C2](ch T) { + <-ch +} + +func _[T C3](ch T) { + <-ch // ERROR cannot receive from ch .* no structural 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 +} diff --git a/src/go/types/testdata/fixedbugs/issue45548.go2 b/src/go/types/testdata/fixedbugs/issue45548.go2 index b1e42497e8586c500d11985f0df6c70249927949..b8ba0ad4a70915b4edaca42bb24ca60f1088a2bd 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/issue45550.go2 b/src/go/types/testdata/fixedbugs/issue45550.go2 new file mode 100644 index 0000000000000000000000000000000000000000..3eeaca0957a9bd54ee9dfcdd253e68d6a37f3fd9 --- /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 /* ERROR illegal cycle */ [T interface{ struct{ Builder[T] } }] struct{} +type myBuilder struct { + Builder[myBuilder] +} diff --git a/src/go/types/testdata/fixedbugs/issue45635.go2 b/src/go/types/testdata/fixedbugs/issue45635.go2 index 3e2cceca2d43b007e9f11bda908ab50ba588b281..fc50797b17ca76929275a00ff343e0b25484bb72 100644 --- a/src/go/types/testdata/fixedbugs/issue45635.go2 +++ b/src/go/types/testdata/fixedbugs/issue45635.go2 @@ -10,10 +10,10 @@ 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 { - type 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/testdata/fixedbugs/issue45639.go2 b/src/go/types/testdata/fixedbugs/issue45639.go2 new file mode 100644 index 0000000000000000000000000000000000000000..80148fe4819862f4761eb439da062e735204aa20 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue45639.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 + +// 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/issue45920.go2 b/src/go/types/testdata/fixedbugs/issue45920.go2 new file mode 100644 index 0000000000000000000000000000000000000000..a0e2d0c970e50233835113ff55f6c43f9dd40485 --- /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 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 implement chan int\|chan<- int */ (ch) } +func _(ch chan<- int) { f2(ch) } diff --git a/src/go/types/testdata/fixedbugs/issue45985.go2 b/src/go/types/testdata/fixedbugs/issue45985.go2 index 550b9c6712768cb9950fd398a366ab1b3677a7d4..9a0f5e36970058c347a5f312609f6821c208be59 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 "type S = S does not match" */ interface{ type []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/testdata/fixedbugs/issue46090.go2 b/src/go/types/testdata/fixedbugs/issue46090.go2 new file mode 100644 index 0000000000000000000000000000000000000000..81b31974c8dc0207e0833d51c845b978ce26cef4 --- /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/testdata/fixedbugs/issue46275.go2 b/src/go/types/testdata/fixedbugs/issue46275.go2 new file mode 100644 index 0000000000000000000000000000000000000000..0ebde31c8e909c204eb586ea3ab4fdeb5cf15182 --- /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 +} + diff --git a/src/go/types/testdata/fixedbugs/issue46461.go2 b/src/go/types/testdata/fixedbugs/issue46461.go2 new file mode 100644 index 0000000000000000000000000000000000000000..4432402a300e9a4cec961fa762d81d0b6317c6d0 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue46461.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 + +// test case 1 +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 /* ERROR illegal cycle */ [T interface{ A[T] }] interface{} + +// test case 3 +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/issue47031.go2 b/src/go/types/testdata/fixedbugs/issue47031.go2 new file mode 100644 index 0000000000000000000000000000000000000000..b184f9b5b7dfbf7255d9bd6587fb78acce371fb6 --- /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/testdata/fixedbugs/issue47115.go2 b/src/go/types/testdata/fixedbugs/issue47115.go2 new file mode 100644 index 0000000000000000000000000000000000000000..f71e06c9b23739599cc1eff6513a013f7aa27bae --- /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 ch .* no structural type */ 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 cannot send to ch .* no structural type */ 0 +} + +func _[T C4](ch T) { + ch <- 0 +} + +func _[T C5[X], X any](ch T, x X) { + ch <- x +} diff --git a/src/go/types/testdata/fixedbugs/issue47127.go2 b/src/go/types/testdata/fixedbugs/issue47127.go2 new file mode 100644 index 0000000000000000000000000000000000000000..108d600a38a6c9ce9075ca792ab7abf4077f1d8e --- /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/testdata/fixedbugs/issue47411.go2 b/src/go/types/testdata/fixedbugs/issue47411.go2 new file mode 100644 index 0000000000000000000000000000000000000000..d6c34be8dba4874c56ad7566ede166bc504e7a8c --- /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 implement comparable */ ()] + _ = f[R /* ERROR empty interface R does not implement comparable */ ] + + _ = g[int] + _ = g[P /* ERROR P does not implement interface{interface{comparable; ~int\|~string} */ ] + _ = g[Q] + _ = 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/go/types/testdata/fixedbugs/issue47747.go2 b/src/go/types/testdata/fixedbugs/issue47747.go2 new file mode 100644 index 0000000000000000000000000000000000000000..6a2e787bf99848bc662654db7b6dd97b55bcec93 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47747.go2 @@ -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 p + +// 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) { + 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) +} + +// 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 + +// 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/src/go/types/testdata/fixedbugs/issue47796.go2 b/src/go/types/testdata/fixedbugs/issue47796.go2 new file mode 100644 index 0000000000000000000000000000000000000000..6667ba4fec08551412c380b4cc0a34d413625ca6 --- /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 /* 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 /* 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 /* ERROR illegal cycle */ [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 /* ERROR illegal cycle */ [a Eq[a]] interface { + Equal(that a) bool +} diff --git a/src/go/types/testdata/fixedbugs/issue47818.go2 b/src/go/types/testdata/fixedbugs/issue47818.go2 new file mode 100644 index 0000000000000000000000000000000000000000..2631118baed94a7f8163693a3f928c95c080a778 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47818.go2 @@ -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. + +// Parser accepts type parameters but the type checker +// needs to report any operations that are not permitted +// before Go 1.18. + +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 +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 /* 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]{} + _ = 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 +) + +type Ordered constraints /* ERROR using type constraint constraints\.Ordered requires go1\.18 or later */ .Ordered diff --git a/src/go/types/testdata/fixedbugs/issue47887.go2 b/src/go/types/testdata/fixedbugs/issue47887.go2 new file mode 100644 index 0000000000000000000000000000000000000000..4c4fc2fda8f8a3140ae9f9b540eb5b7a0781f2e2 --- /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/testdata/fixedbugs/issue47968.go2 b/src/go/types/testdata/fixedbugs/issue47968.go2 new file mode 100644 index 0000000000000000000000000000000000000000..711e50a55a1d5eeb9661ff259a03ea78618dd82e --- /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 // ERROR cannot use generic type + +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 diff --git a/src/go/types/testdata/fixedbugs/issue48008.go2 b/src/go/types/testdata/fixedbugs/issue48008.go2 new file mode 100644 index 0000000000000000000000000000000000000000..6c14c78e4c9cfc3a56bf285c8af9a1f929f8fa27 --- /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 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 */ }: + 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/testdata/fixedbugs/issue48018.go2 b/src/go/types/testdata/fixedbugs/issue48018.go2 new file mode 100644 index 0000000000000000000000000000000000000000..e6ccc6b9be703584177333b01e0d9afc780e7a9d --- /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) +} diff --git a/src/go/types/testdata/fixedbugs/issue48048.go2 b/src/go/types/testdata/fixedbugs/issue48048.go2 new file mode 100644 index 0000000000000000000000000000000000000000..f4013306215ec3aaeb69ff6855132784178e72bd --- /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 diff --git a/src/go/types/testdata/fixedbugs/issue48082.src b/src/go/types/testdata/fixedbugs/issue48082.src new file mode 100644 index 0000000000000000000000000000000000000000..5395154978ebe1864ab02ced4fe56b57110da8db --- /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 */ diff --git a/src/go/types/testdata/fixedbugs/issue48083.go2 b/src/go/types/testdata/fixedbugs/issue48083.go2 new file mode 100644 index 0000000000000000000000000000000000000000..3dae51415df0a2178ca9c2b2206c2dc58f0cda27 --- /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/testdata/fixedbugs/issue48136.go2 b/src/go/types/testdata/fixedbugs/issue48136.go2 new file mode 100644 index 0000000000000000000000000000000000000000..b87f84ae642d68973a1eb1788e8c41f4731c636d --- /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 */ () +} diff --git a/src/go/types/testdata/fixedbugs/issue48234.go2 b/src/go/types/testdata/fixedbugs/issue48234.go2 new file mode 100644 index 0000000000000000000000000000000000000000..e069930c42d99c3caa36a9acff90d60cf6031fa4 --- /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/testdata/fixedbugs/issue48472.go2 b/src/go/types/testdata/fixedbugs/issue48472.go2 new file mode 100644 index 0000000000000000000000000000000000000000..2d908f4c8b56c7c6ab799080a5c863bfd5a234d5 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48472.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 + +func g() { + var s string + 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 +} diff --git a/src/go/types/testdata/fixedbugs/issue48529.go2 b/src/go/types/testdata/fixedbugs/issue48529.go2 new file mode 100644 index 0000000000000000000000000000000000000000..a3653fa19c09618b6565c51df29555b756549d17 --- /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 /* ERROR illegal cycle */ [U interface{ M() T[U, int] }] int + +type X int + +func (X) M() T[X] { return 0 } diff --git a/src/go/types/testdata/fixedbugs/issue48582.go2 b/src/go/types/testdata/fixedbugs/issue48582.go2 new file mode 100644 index 0000000000000000000000000000000000000000..c12091be7902f460ee8e3022a94e151f69faeab5 --- /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 +} diff --git a/src/go/types/testdata/fixedbugs/issue48619.go2 b/src/go/types/testdata/fixedbugs/issue48619.go2 new file mode 100644 index 0000000000000000000000000000000000000000..870bacd0bd25ab2d368906d091c66e3db1235e39 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48619.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. + +// 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 */) +} + +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 0000000000000000000000000000000000000000..52863d446b6bdf2e805c30b0b383e5592f2ffbda --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48656.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. + +// This issue is still open. + +package 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 0000000000000000000000000000000000000000..2d9e6a5f3ddab0d32b5a6163fd112ebb1f1ad6ee --- /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/testdata/fixedbugs/issue48703.go2 b/src/go/types/testdata/fixedbugs/issue48703.go2 new file mode 100644 index 0000000000000000000000000000000000000000..8a32c1ecf22a3c375abc3ae1f9b5ddf3f85abcb4 --- /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/issue48819.src b/src/go/types/testdata/fixedbugs/issue48819.src new file mode 100644 index 0000000000000000000000000000000000000000..9262110ea09e71e96c3494186beaba6c6c5f4db5 --- /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/testdata/fixedbugs/issue48827.go2 b/src/go/types/testdata/fixedbugs/issue48827.go2 new file mode 100644 index 0000000000000000000000000000000000000000..aa1d12aaf5c638ae107cd6105a486ce85d73c4b4 --- /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/testdata/fixedbugs/issue48951.go2 b/src/go/types/testdata/fixedbugs/issue48951.go2 new file mode 100644 index 0000000000000000000000000000000000000000..cf02cc130aa6cb44089d3abedf05734ea6fd0d42 --- /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] } +) diff --git a/src/go/types/testdata/fixedbugs/issue48974.go2 b/src/go/types/testdata/fixedbugs/issue48974.go2 new file mode 100644 index 0000000000000000000000000000000000000000..d8ff7c8cf46d1b957f72bd8c1a856f693a30c9c3 --- /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 /* ERROR instantiation cycle */ 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() {} diff --git a/src/go/types/testdata/fixedbugs/issue49003.go b/src/go/types/testdata/fixedbugs/issue49003.go new file mode 100644 index 0000000000000000000000000000000000000000..ece1a27bb927f4bdf9b14a8674bca0e3488b6dff --- /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 diff --git a/src/go/types/testdata/fixedbugs/issue49043.go2 b/src/go/types/testdata/fixedbugs/issue49043.go2 new file mode 100644 index 0000000000000000000000000000000000000000..c37b0f126783f6f0e3fc8ab5d0c088e9d96e0ecf --- /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] +) diff --git a/src/go/types/testdata/fixedbugs/issue49179.go2 b/src/go/types/testdata/fixedbugs/issue49179.go2 new file mode 100644 index 0000000000000000000000000000000000000000..d4c8a897c65a4004a6dacbdc836846aca99b43ca --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49179.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 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 +} + +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\] \(possibly missing ~ for \[\]int in constraint SliceConstraint\[int\]\) */, int](s, nil) +} diff --git a/src/go/types/testdata/fixedbugs/issue49242.go2 b/src/go/types/testdata/fixedbugs/issue49242.go2 new file mode 100644 index 0000000000000000000000000000000000000000..524a0cbae364ad110ace20437441a1c39e7f6575 --- /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/fixedbugs/issue49247.go2 b/src/go/types/testdata/fixedbugs/issue49247.go2 new file mode 100644 index 0000000000000000000000000000000000000000..3f25e0ee35526adb7fa4d3edf398e1e6006f3daa --- /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/issue49276.go2 b/src/go/types/testdata/fixedbugs/issue49276.go2 new file mode 100644 index 0000000000000000000000000000000000000000..8839087b50671221dd56a6b05dad3bfa199ef33a --- /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 +} diff --git a/src/go/types/testdata/fixedbugs/issue49296.go2 b/src/go/types/testdata/fixedbugs/issue49296.go2 new file mode 100644 index 0000000000000000000000000000000000000000..0ad71ef4b2adb677f00ec677cb92a94536fdb1f3 --- /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 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/fixedbugs/issue49439.go2 b/src/go/types/testdata/fixedbugs/issue49439.go2 new file mode 100644 index 0000000000000000000000000000000000000000..6cc838b3b30104c299e86b74ad604282dbb9b8c4 --- /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{} diff --git a/src/go/types/testdata/fixedbugs/issue49579.go2 b/src/go/types/testdata/fixedbugs/issue49579.go2 new file mode 100644 index 0000000000000000000000000000000000000000..9e20ae5468db76e8604dcd93cea7c74f05480c8d --- /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) {} diff --git a/src/go/types/testdata/fixedbugs/issue49592.go2 b/src/go/types/testdata/fixedbugs/issue49592.go2 new file mode 100644 index 0000000000000000000000000000000000000000..846deaa89aac62bf1d7b404ca8e78d01965587f9 --- /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/src/go/types/testdata/fixedbugs/issue49705.go2 b/src/go/types/testdata/fixedbugs/issue49705.go2 new file mode 100644 index 0000000000000000000000000000000000000000..2b991b872211af0466e433ae7aecd699d78ff52d --- /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 +} diff --git a/src/go/types/testdata/fixedbugs/issue49739.go2 b/src/go/types/testdata/fixedbugs/issue49739.go2 new file mode 100644 index 0000000000000000000000000000000000000000..46b1e71a3b95cfb43cfd760524c89d4054738b9c --- /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/testdata/fixedbugs/issue49864.go2 b/src/go/types/testdata/fixedbugs/issue49864.go2 new file mode 100644 index 0000000000000000000000000000000000000000..0437e74a643fab57fdd6bd1c26bbd295c3e4764c --- /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 */ ) +} diff --git a/src/go/types/testdata/manual.go2 b/src/go/types/testdata/manual.go2 new file mode 100644 index 0000000000000000000000000000000000000000..25e6f22f94b7336cd60ae59e226f047856476e01 --- /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 + diff --git a/src/go/types/testdata/spec/assignability.go2 b/src/go/types/testdata/spec/assignability.go2 new file mode 100644 index 0000000000000000000000000000000000000000..d5f6ab4419a1aa7d5cac671477e9f417659ae7a6 --- /dev/null +++ b/src/go/types/testdata/spec/assignability.go2 @@ -0,0 +1,266 @@ +// Copyright 2021 The Go Authors. 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 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 + 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 named type" +// (here a named type is a type with a name) +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 // 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 /* 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 // 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. +func _[TP Interface](X TP) { + b = nil // ERROR cannot use nil + a = nil // ERROR cannot use nil + l = nil + s = nil // ERROR cannot use nil + p = nil + f = nil + i = nil + m = nil + c = nil + d = nil // ERROR cannot use nil + + B = nil // ERROR cannot use nil + A = nil // ERROR cannot use nil + L = nil + S = nil // ERROR cannot use nil + P = nil + F = nil + I = nil + M = nil + C = 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" +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/spec/conversions.go2 b/src/go/types/testdata/spec/conversions.go2 new file mode 100644 index 0000000000000000000000000000000000000000..e54403cea9d6820cec2e294bafc80b307a77e856 --- /dev/null +++ b/src/go/types/testdata/spec/conversions.go2 @@ -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 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 +} + +// 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 + +// "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 +} diff --git a/src/go/types/tuple.go b/src/go/types/tuple.go new file mode 100644 index 0000000000000000000000000000000000000000..e85c5aa81bef566c2af58fbb0d1b144dce537147 --- /dev/null +++ b/src/go/types/tuple.go @@ -0,0 +1,34 @@ +// 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} + } + 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 2660ce4408c1b640f67bf517ca72d3819055907e..3acb19c41240fcf5713c72f81c50b1b467026d03 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -4,983 +4,123 @@ package types -import ( - "fmt" - "go/token" - "sync/atomic" -) - // A Type represents a type of Go. // All types implement the Type interface. 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 } -// 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 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 -} - -// 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 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 } - -// 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 - } +// 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 { + if t, _ := t.(*Named); t != nil { + return t.under() } - return true -} - -// 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) - 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) + return t.Underlying() } -// 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 sum := asSum(typ); sum != nil { - return sum.types +// 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) } - 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 { - return false // we must have at least one type! (was bug) - } - for _, t := range unpackType(t.allTypes) { - if !pred(t) { + var su Type + if tpar.underIs(func(u Type) bool { + if u == nil { return false } - } - return true -} - -// 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) - -// 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. -// -// 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. -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 (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 { - 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) - sortTypes(embeddeds) - - typ.methods = methods - typ.embeddeds = embeddeds - 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. -// 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") - } -} - -// 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] } - -// 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) -} - -// _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) -} - -// _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) -} - -// _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) -} - -// 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. -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 + if su != nil { + u = match(su, u) + if u == nil { + return false } } - } - return false -} - -// 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() - if t.allTypes == nil { + // su == nil || match(su, u) != nil + su = u return true + }) { + return su } - types := unpackType(t.allTypes) - return includes(types, typ) || includes(types, under(typ)) + return nil } -// Complete computes the interface's method 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. -func (t *Interface) Complete() *Interface { - // TODO(gri) consolidate this method with Checker.completeInterface - if t.allMethods != nil { - return t +// 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 } - 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)) + var su Type + hasString := false + if tpar.underIs(func(u Type) bool { + if u == nil { + return false } - } - - 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 + if isString(u) { + u = NewSlice(universeByte) + hasString = true } - etyp.Complete() - for _, m := range etyp.allMethods { - addMethod(m, false) + if su != nil { + u = match(su, u) + if u == nil { + return 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) + // su == nil || match(su, u) != nil + su = u + return true + }) { + if hasString { + return Typ[String] } + return su } - - if methods != nil { - sortMethods(methods) - t.allMethods = methods - } - t.allTypes = allTypes - - return t -} - -// 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 } - -// 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) - 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 -} - -// 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, underlying, methods) + return nil } -func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func) *Named { - typ := &Named{check: check, obj: obj, orig: underlying, underlying: underlying, methods: methods} - 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") +// 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 } - typ.check = nil - }) - } - return typ -} - -// Obj returns the type name for the named type t. -func (t *Named) Obj() *TypeName { return t.obj } - -// 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.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. -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) } - -// 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] } - -// 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.underlying = underlying -} - -// AddMethod adds method m unless it is already in the method list. -func (t *Named) AddMethod(m *Func) { - 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 - obj *TypeName // corresponding type name - index int // parameter index - 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} - if obj.typ == nil { - obj.typ = typ - } - return typ -} - -func (t *_TypeParam) Bound() *Interface { - iface := asInterface(t.bound) - // 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. - t.check.completeInterface(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 -// 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 - // 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.Bound().allTypes; u != nil && u != typ { - // u != typ and u is a type parameter => under(u) != typ, so this is ok - return under(u) - } - return theTop - } - 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 } - -// 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. -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 *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 } -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. -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 *_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) } -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. -// 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 *Sum? - if n := asNamed(t); n != nil { - return n.under() } - return t -} - -// 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 asArray(t Type) *Array { - op, _ := optype(t).(*Array) - return op -} - -func asSlice(t Type) *Slice { - op, _ := optype(t).(*Slice) - return op -} - -func asStruct(t Type) *Struct { - op, _ := optype(t).(*Struct) - return op -} - -func asPointer(t Type) *Pointer { - op, _ := optype(t).(*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 -} - -func asSum(t Type) *_Sum { - op, _ := optype(t).(*_Sum) - return op -} - -func asInterface(t Type) *Interface { - op, _ := optype(t).(*Interface) - return op -} - -func asMap(t Type) *Map { - op, _ := optype(t).(*Map) - return op -} - -func asChan(t Type) *Chan { - op, _ := optype(t).(*Chan) - return op -} - -// If the argument to asNamed and asTypeParam is of the respective types -// (possibly after expanding an instance type), these methods return that type. -// Otherwise the result is nil. - -func asNamed(t Type) *Named { - e, _ := expand(t).(*Named) - return e -} - -func asTypeParam(t Type) *_TypeParam { - u, _ := under(t).(*_TypeParam) - return u + // types are different + return nil } diff --git a/src/go/types/typelists.go b/src/go/types/typelists.go new file mode 100644 index 0000000000000000000000000000000000000000..aea19e946dd5779f941ac546ee1b27b59c3eedca --- /dev/null +++ b/src/go/types/typelists.go @@ -0,0 +1,80 @@ +// Copyright 2021 The Go Authors. 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" + +// 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 *TypeParamList) Len() int { return len(l.list()) } + +// At returns the i'th type parameter in the list. +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 +// TypeParamList instead. +func (l *TypeParamList) 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 +} + +func (l *TypeList) String() string { + if l == nil || len(l.types) == 0 { + return "[]" + } + var buf bytes.Buffer + newTypeWriter(&buf, nil).typeList(l.types) + return buf.String() +} + +// ---------------------------------------------------------------------------- +// Implementation + +func bindTParams(list []*TypeParam) *TypeParamList { + 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 &TypeParamList{tparams: list} +} diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go new file mode 100644 index 0000000000000000000000000000000000000000..03ba9be55c564d669ae8ba33bd0c2add2bfb5415 --- /dev/null +++ b/src/go/types/typeparam.go @@ -0,0 +1,163 @@ +// 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 // 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 +// 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. +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: constraint} + 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 +} + +// 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 +} + +// 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 { + return t.bound +} + +// 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 { + return t.iface() +} + +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 + + // 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: + if isTypeParam(bound) { + // error is reported in Checker.collectTypeParams + return &emptyInterface + } + ityp = u + } + + // If we don't have an interface, wrap constraint into an implicit interface. + if ityp == nil { + ityp = NewInterfaceType(nil, []Type{bound}) + ityp.implicit = true + t.bound = ityp // update t.bound for next time (optimization) + } + + // 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 +} + +// 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. +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/types_test.go b/src/go/types/types_test.go deleted file mode 100644 index 25cd9966282861ebf71827819813f0e9b44908d0..0000000000000000000000000000000000000000 --- a/src/go/types/types_test.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 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) { - config.goVersion = goVersion -} diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go new file mode 100644 index 0000000000000000000000000000000000000000..d39483f2549642d72254872e028bbf6246c259a3 --- /dev/null +++ b/src/go/types/typeset.go @@ -0,0 +1,399 @@ +// Copyright 2021 The Go Authors. 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" + "fmt" + "go/token" + "sort" +) + +// ---------------------------------------------------------------------------- +// API + +// 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 + terms termlist // type terms of the type set +} + +// IsEmpty reports whether type set s is the empty set. +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() } + +// 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 { + if s.terms.isAll() { + return s.comparable + } + return s.is(func(t *term) bool { + return t != nil && Comparable(t.typ) + }) +} + +// 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 { + return !s.comparable && len(s.methods) == 0 +} + +// 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 { + switch { + case s.IsEmpty(): + return "∅" + case s.IsAll(): + return "𝓤" + } + + hasMethods := len(s.methods) > 0 + hasTerms := s.hasTerms() + + var buf bytes.Buffer + buf.WriteByte('{') + if s.comparable { + buf.WriteString("comparable") + if hasMethods || hasTerms { + buf.WriteString("; ") + } + } + for i, m := range s.methods { + if i > 0 { + buf.WriteString("; ") + } + buf.WriteString(m.String()) + } + if hasMethods && hasTerms { + buf.WriteString("; ") + } + if hasTerms { + buf.WriteString(s.terms.String()) + } + buf.WriteString("}") + return buf.String() +} + +// ---------------------------------------------------------------------------- +// Implementation + +// hasTerms reports whether the type set has specific type terms. +func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } + +// 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. +// 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. +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 + +// 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 !s.hasTerms() { + return f(nil) + } + for _, t := range s.terms { + assert(t.typ != nil) + if !f(t) { + return false + } + } + 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 !s.hasTerms() { + return f(nil) + } + for _, t := range s.terms { + assert(t.typ != nil) + // x == under(x) for ~x terms + u := t.typ + 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{terms: allTermlist} + +// computeInterfaceTypeSet may be called with check == nil. +func computeInterfaceTypeSet(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 = &_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 + // 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 allTerms = allTermlist + 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 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) { + check.errorf(atPos(pos), _UnsupportedFeature, "embedding constraint interface %s requires go1.18 or later", typ) + continue + } + if tset.comparable { + ityp.tset.comparable = true + } + for _, m := range tset.methods { + addMethod(pos, m, false) // use embedding position pos rather than m.pos + } + terms = tset.terms + case *Union: + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(atPos(pos), _InvalidIfaceEmbed, "embedding interface element %s requires go1.18 or later", u) + continue + } + tset := computeUnionTypeSet(check, pos, u) + if tset == &invalidTypeSet { + continue // ignore invalid unions + } + terms = tset.terms + default: + if u == Typ[Invalid] { + continue + } + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(atPos(pos), _InvalidIfaceEmbed, "embedding non-interface type %s requires go1.18 or later", typ) + continue + } + terms = termlist{{false, typ}} + } + // 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) + + // 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.terms = allTerms + + return ityp.tset +} + +func sortMethods(list []*Func) { + sort.Sort(byUniqueMethodName(list)) +} + +func assertSortedMethods(list []*Func) { + if !debug { + panic("assertSortedMethods called outside debug mode") + } + if !sort.IsSorted(byUniqueMethodName(list)) { + panic("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] } + +// 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 + } + + // avoid infinite recursion (see also computeInterfaceTypeSet) + utyp.tset = new(_TypeSet) + + var allTerms termlist + for _, t := range utyp.terms { + var terms termlist + 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, 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)} + } + // 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), _InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) + } + utyp.tset = &invalidTypeSet + return utyp.tset + } + } + utyp.tset.terms = allTerms + + return utyp.tset +} diff --git a/src/go/types/typeset_test.go b/src/go/types/typeset_test.go new file mode 100644 index 0000000000000000000000000000000000000000..1c0eeceb8c31ad0bd8c3053f76899cb5af09fcc5 --- /dev/null +++ b/src/go/types/typeset_test.go @@ -0,0 +1,81 @@ +// Copyright 2021 The Go Authors. 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/parser" + "go/token" + "testing" +) + +func TestInvalidTypeSet(t *testing.T) { + if !invalidTypeSet.IsEmpty() { + t.Error("invalidTypeSet is not empty") + } +} + +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 diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index fe27f0f276c30e5127b2a0d61c1145b56b1105cf..cf86f9f72086fee21a669bd135a7cf404fe8d664 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -10,6 +10,9 @@ import ( "bytes" "fmt" "go/token" + "sort" + "strconv" + "strings" "unicode/utf8" ) @@ -40,33 +43,18 @@ 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. 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() } @@ -74,172 +62,190 @@ 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) +} + +// 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) +} + +type typeWriter struct { + 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, nil, false} +} + +func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter { + assert(ctxt != nil) + return &typeWriter{buf, make(map[Type]bool), nil, ctxt, nil, false} } -// instanceMarker is the prefix for an instantiated type -// in "non-evaluated" instance 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 +func (w *typeWriter) byte(b byte) { + if w.ctxt != 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.ctxt != nil { + panic(msg) + } + w.buf.WriteString("<" + msg + ">") +} + +func (w *typeWriter) typ(typ Type) { + if w.seen[typ] { + w.error("cycle to " + goTypeName(typ)) + return } - visited = append(visited, typ) + w.seen[typ] = true + defer delete(w.seen, typ) switch t := typ.(type) { case nil: - buf.WriteString("") + w.error("nil") 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 } } - - if gcCompatibilityMode { - // forget the alias names - switch t.kind { - case Byte: - t = Typ[Uint8] - case Rune: - t = Typ[Int32] - } - } - buf.WriteString(t.name) + w.string(t.name) case *Array: - fmt.Fprintf(buf, "[%d]", t.len) - writeType(buf, t.elem, qf, visited) + w.byte('[') + w.string(strconv.FormatInt(t.len, 10)) + w.byte(']') + 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.byte(';') } // 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.byte(' ') + // TODO(rfindley) If tag contains blanks, replacing them with '#' + // in Context.TypeHash may produce another tag + // accidentally. + w.string(strconv.Quote(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) - - case *_Sum: - for i, t := range t.types { + w.string("func") + w.signature(t) + + case *Union: + // Unions only appear as (syntactic) embedded elements + // in interfaces and syntactically cannot be empty. + if t.Len() == 0 { + w.error("empty union") + break + } + for i, t := range t.terms { if i > 0 { - buf.WriteString(", ") + w.byte('|') + } + if t.tilde { + w.byte('~') } - writeType(buf, t, qf, visited) + w.typ(t.typ) } 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) - for i, m := range t.allMethods { - if i > 0 { - buf.WriteString("; ") - } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - if !empty && t.allTypes != nil { - buf.WriteString("; ") - } - if t.allTypes != nil { - buf.WriteString("type ") - writeType(buf, t.allTypes, qf, visited) + 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]) + break } + // Something's wrong with the implicit interface. + // Print it as such and continue. + w.string("/* implicit */ ") + } + w.string("interface{") + first := true + if w.ctxt != nil { + w.typeSet(t.typeSet()) } else { - // print explicit interface methods and embedded types - for i, m := range t.methods { - if i > 0 { - buf.WriteString("; ") + for _, m := range t.methods { + if !first { + w.byte(';') } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false + first = false + w.string(m.name) + w.signature(m.typ.(*Signature)) } - 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("; ") - } - for i, typ := range t.embeddeds { - if i > 0 { - buf.WriteString("; ") + for _, typ := range t.embeddeds { + if !first { + w.byte(';') } - writeType(buf, typ, qf, visited) - empty = false - } - } - if t.allMethods == nil || len(t.methods) > len(t.allMethods) { - if !empty { - buf.WriteByte(' ') + first = false + w.typ(typ) } - buf.WriteString("/* incomplete */") } - 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 @@ -256,158 +262,187 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case RecvOnly: s = "<-chan " default: - panic("unreachable") + w.error("unknown channel direction") } - 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: - writeTypeName(buf, t.obj, qf) + // 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 - buf.WriteByte('[') - writeTypeList(buf, t.targs, qf, visited) - buf.WriteByte(']') - } else if t.tparams != nil { + w.typeList(t.targs.list()) + } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TypeParams // parameterized type - writeTParamList(buf, t.tparams, qf, visited) + w.tParamList(t.TypeParams().list()) } - case *_TypeParam: - s := "?" - if t.obj != nil { - s = t.obj.name + case *TypeParam: + if t.obj == nil { + w.error("unnamed type parameter") + break + } + 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)) + } } - 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 *bottom: - buf.WriteString("⊥") - - case *top: - buf.WriteString("⊤") default: // For externally defined implementations of Type. - buf.WriteString(t.String()) + // Note: In this case cycles won't be caught. + w.string(t.String()) } } -func writeTypeList(buf *bytes.Buffer, list []Type, qf Qualifier, visited []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 { if i > 0 { - buf.WriteString(", ") + w.byte(',') } - writeType(buf, typ, qf, visited) + w.typ(typ) } + w.byte(']') } -func writeTParamList(buf *bytes.Buffer, list []*TypeName, 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, 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 + 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. + if tpar == nil { + w.error("nil type parameter") + continue } if i > 0 { - if b != prev { - // type bound changed - write previous one before advancing - buf.WriteByte(' ') - writeType(buf, prev, qf, visited) + if tpar.bound != prev { + // bound changed - write previous one before advancing + w.byte(' ') + w.typ(prev) } - buf.WriteString(", ") - } - prev = b - - if t, _ := p.typ.(*_TypeParam); t != nil { - writeType(buf, t, qf, visited) - } else { - buf.WriteString(p.name) + w.byte(',') } + prev = tpar.bound + w.typ(tpar) } 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) { - s := "" - if obj != nil { - if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) - } - // TODO(gri): function-local named types should be displayed - // differently from named types at package level to avoid - // ambiguity. - s = obj.name +func (w *typeWriter) typeName(obj *TypeName) { + if obj.pkg != nil { + writePackage(w.buf, obj.pkg, w.qf) } - buf.WriteString(s) + w.string(obj.name) } -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.byte(',') } - if v.name != "" { - buf.WriteString(v.name) - buf.WriteByte(' ') + // parameter names are ignored for type identity and thus type hashes + if w.ctxt == nil && v.name != "" { + 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: // append(s, "foo"...) leads to signature func([]byte, string...) - if t := asBasic(typ); t == nil || t.kind != String { - panic("internal error: string type expected") + if t, _ := under(typ).(*Basic); t == nil || t.kind != String { + w.error("expected string type") + continue } - 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, -// 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) { - writeSignature(buf, sig, qf, make([]Type, 0, 8)) -} - -func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { - if sig.tparams != nil { - writeTParamList(buf, sig.tparams, qf, visited) +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()) } - writeTuple(buf, sig.params, sig.variadic, qf, visited) + w.tuple(sig.params, sig.variadic) n := sig.results.Len() if n == 0 { @@ -415,15 +450,15 @@ func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []T return } - buf.WriteByte(' ') - if n == 1 && sig.results.vars[0].name == "" { - // single unnamed result - writeType(buf, sig.results.vars[0].typ, qf, visited) + w.byte(' ') + 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 } // 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/typestring_test.go b/src/go/types/typestring_test.go index b16529dc64155cc306d1233d30b5d3d921dbf764..14ab9b6002a5185eed4bebfea937a27841e7992b 100644 --- a/src/go/types/typestring_test.go +++ b/src/go/types/typestring_test.go @@ -95,10 +95,8 @@ var independentTestTypes = []testEntry{ dup("interface{}"), dup("interface{m()}"), dup(`interface{String() string; m(int) float32}`), - - // TODO(rFindley) uncomment this once this AST is accepted, and add more test - // cases. - // dup(`interface{type int, float32, complex128}`), + dup("interface{int|float32|complex128}"), + dup("interface{int|~float32|~complex128}"), // maps dup("map[string]int"), @@ -135,65 +133,18 @@ 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) } } } -func TestIncompleteInterfaces(t *testing.T) { - 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) diff --git a/src/go/types/typeterm.go b/src/go/types/typeterm.go new file mode 100644 index 0000000000000000000000000000000000000000..6b6782100084f66aa1ea9add9c35e2910b05d17c --- /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 + +// 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 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 { + 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 !Identical(ux, uy) +} diff --git a/src/go/types/typeterm_test.go b/src/go/types/typeterm_test.go new file mode 100644 index 0000000000000000000000000000000000000000..27f132a1d249a2df23599acbd51123680399d2fa --- /dev/null +++ b/src/go/types/typeterm_test.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 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, + "𝓤": {}, + "int": {false, Typ[Int]}, + "~int": {true, Typ[Int]}, + "string": {false, Typ[String]}, + "~string": {true, Typ[String]}, + "myInt": {false, myInt}, +} + +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", + "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]) + 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 ∅", + "∅ 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]) + 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 ∅", + "∅ 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]) + 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", + "~int myInt T", + "string int F", + "~string int F", + "myInt 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", + "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]) + 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 myInt T", + "~int ~string T", + "~int myInt F", + "string myInt T", + "~string myInt 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) + } + } +} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 1738d864a6573965f9bf5cf626b9b9a48fdb60ec..b961f7c47fcc6df91ab49946903057156723c3fb 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -11,9 +11,6 @@ import ( "go/ast" "go/constant" "go/internal/typeparams" - "go/token" - "sort" - "strconv" "strings" ) @@ -29,13 +26,27 @@ 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 { + switch obj { + case nil: if e.Name == "_" { - check.errorf(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.recvTParamMap. + if tpar := check.recvTParamMap[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) } 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 // avoid follow-on errors + } } check.recordUse(e, obj) @@ -58,7 +69,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 } @@ -125,41 +136,32 @@ 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. + // 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 := 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) - return - } - if t._IsComparable() { - check.softErrorf(pos, _Todo, "interface is (or embeds) comparable") + 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 { + check.softErrorf(e, _MisplacedConstraintIface, "interface is (or embeds) comparable") + } else { + check.softErrorf(e, _MisplacedConstraintIface, "interface contains type constraints") + } } } }) -} -// 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 } @@ -172,20 +174,22 @@ 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) 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] } @@ -194,205 +198,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 { @@ -412,9 +217,7 @@ 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 = T.Underlying() + under = safeUnderlying(T) } if T == under { check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T)) @@ -462,13 +265,12 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { check.errorf(&x, _NotAType, "%s is not a type", &x) } - case *ast.IndexExpr: - if typeparams.Enabled { - exprs := typeparams.UnpackExpr(e.Index) - return check.instantiatedType(e.X, exprs, def) + case *ast.IndexExpr, *ast.IndexListExpr: + ix := typeparams.UnpackIndexExpr(e) + if !check.allowVersion(check.pkg, 1, 18) { + check.softErrorf(inNode(e, ix.Lbrack), _UnsupportedFeature, "type instantiation requires go1.18 or later") } - check.errorf(e0, _NotAType, "%s is not a type", e0) - check.use(e.X) + return check.instantiatedType(ix, def) case *ast.ParenExpr: // Generic types must be instantiated before they can be used in any form. @@ -476,18 +278,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 @@ -503,6 +307,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 @@ -538,7 +343,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) @@ -577,80 +382,114 @@ 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) +func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (res Type) { + pos := ix.X.Pos() + if trace { + 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(pos, "=> %s", res) + }() } - 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? - if b == Typ[Invalid] { - return b // error already reported + var reason string + gtyp := check.genericType(ix.X, &reason) + if reason != "" { + check.invalidOp(ix.Orig, _NotAGenericType, "%s (%s)", ix.Orig, reason) } - base := asNamed(b) - if base == nil { - unreachable() // should have been caught by genericType + if gtyp == Typ[Invalid] { + return gtyp // error already reported } - // create a new type instance rather than instantiate the type - // TODO(gri) should do argument number check here rather than - // when instantiating the type? - typ := new(instance) - def.setUnderlying(typ) - - typ.check = check - typ.pos = x.Pos() - typ.base = base + orig, _ := gtyp.(*Named) + if orig == nil { + panic(fmt.Sprintf("%v: cannot instantiate %v", ix.Pos(), gtyp)) + } - // evaluate arguments (always) - typ.targs = check.typeList(targs) - if typ.targs == nil { + // evaluate arguments + targs := check.typeList(ix.Indices) + 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(targs)) - for i, arg := range targs { - typ.poslist[i] = arg.Pos() + // create the instance + ctxt := check.bestContext(nil) + h := ctxt.instanceHash(orig, targs) + // targs may be incomplete, and require inference. In any case we should de-duplicate. + 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 + // for each instantiated type in the source. + 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 = ctxt.update(h, orig, targs, inst).(*Named) + } + def.setUnderlying(inst) + + inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { + tparams := orig.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(ix.Orig, tparams, targs, nil, nil) + if len(inferred) > len(targs) { + inst.targs = newTypeList(inferred) + } + } + + check.recordInstance(ix.Orig, inferred, inst) + return expandNamed(ctxt, n, pos) } - // make sure we check instantiation works at least once - // and that the resulting type is valid + // orig.tparams may not be set up, so we need to do expansion later. check.later(func() { - t := typ.expand() - check.validType(t, 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(ctxt) + // Since check is non-nil, we can still mutate inst. Unpinning the resolver + // frees some memory. + inst.resolver = 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 := ix.Pos() + 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(), ix.Indices) + } + } + + check.validType(inst, nil) }) - return typ + return inst } // arrayLength type-checks the array length expression e // 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_ { @@ -659,6 +498,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) { @@ -670,6 +510,7 @@ func (check *Checker) arrayLength(e ast.Expr) int64 { } } } + check.errorf(&x, _InvalidArrayLen, "array length %s must be integer", &x) return -1 } @@ -689,518 +530,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 -} - -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) 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 { - 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 -} - -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 -} diff --git a/src/go/types/unify.go b/src/go/types/unify.go index db06e21cf724fd11330e33f0c91ffe03ce09138a..5dcb35f6ecaec759b0b53ae631892b523e261668 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -8,8 +8,7 @@ package types import ( "bytes" - "go/token" - "sort" + "fmt" ) // The unifier maintains two separate sets of type parameters x and y @@ -38,7 +37,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 @@ -49,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 @@ -64,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 @@ -78,29 +76,30 @@ type tparamsList struct { // String returns a string representation for a tparamsList. For debugging. func (d *tparamsList) String() string { var buf bytes.Buffer - buf.WriteByte('[') - for i, tname := range d.tparams { + w := newTypeWriter(&buf, nil) + w.byte('[') + for i, tpar := range d.tparams { if i > 0 { - buf.WriteString(", ") + w.string(", ") } - writeType(&buf, tname.typ, 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() } // 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 @@ -109,7 +108,7 @@ func (d *tparamsList) init(tparams []*TypeName) { // 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,13 +132,18 @@ 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. 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 @@ -148,10 +152,23 @@ 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.j +func tparamIndex(list []*TypeParam, tpar *TypeParam) int { + // 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 } @@ -216,26 +233,20 @@ 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 { - // 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 // 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 - // want *Named types.) - switch { - case !isNamed(x) && y != nil && asNamed(y) != nil: - return u.nify(x, under(y), p) - case x != nil && asNamed(x) != nil && !isNamed(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) } } @@ -352,25 +363,18 @@ 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 *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 { - // 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) + xset := x.typeSet() + yset := y.typeSet() + if !xset.terms.equal(yset.terms) { + return false } - a := x.allMethods - b := y.allMethods + 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 @@ -402,8 +406,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] @@ -428,19 +432,18 @@ 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 - // } + // 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() + // 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 } } @@ -448,21 +451,17 @@ 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. return x == y - // case *instance: - // unreachable since types are expanded - case nil: // 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 diff --git a/src/go/types/union.go b/src/go/types/union.go new file mode 100644 index 0000000000000000000000000000000000000000..1437bd4624a19af627427b306f134839bbfe7ece --- /dev/null +++ b/src/go/types/union.go @@ -0,0 +1,160 @@ +// Copyright 2021 The Go Authors. 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 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 +} + +// 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) 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 + +// Avoid excessive type-checking times due to quadratic termlist operations. +const maxTermCount = 100 + +// 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) + if len(tlist) == 1 && !tilde { + // 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 // 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)) + } + + // 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 terms { + if t.typ == Typ[Invalid] { + continue + } + + u := under(t.typ) + f, _ := u.(*Interface) + if t.tilde { + if f != nil { + 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], _InvalidUnion, "invalid use of ~ (underlying type of %s is %s)", t.typ, u) + continue // don't report another error for 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(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], _InvalidUnion, "overlapping terms %s and %s", t, terms[j]) + } + } + }) + + u := &Union{terms, nil} + check.recordTypeAndValue(uexpr, typexpr, u, nil) + return u +} + +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 + } + typ = check.typ(x) + // Embedding stand-alone type parameters is not permitted (issue #47127). + // 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 +} + +// 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("empty or top union term") + } + } + if !(*term)(x).disjoint((*term)(y)) { + return i + } + } + 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) +} diff --git a/src/go/types/universe.go b/src/go/types/universe.go index d7feb2c609efa93829bc90bd9176d1d9a423bf94..edda56fc0dbf174998c970b2d901a394a5e51fbf 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 Object + universeByte Type // uint8 alias, but has name "byte" + universeRune Type // int32 alias, but has name "rune" + universeAny Object + universeError Type + universeComparable Object ) // Typ contains the predeclared *Basic types indexed by their @@ -79,20 +79,33 @@ 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.) - def(NewTypeName(token.NoPos, nil, "any", &emptyInterface)) + // type any = interface{} + // 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})) - // Error has a nil package in its qualified name since it is in no package + // type error interface{ Error() string } { + obj := NewTypeName(token.NoPos, nil, "error", nil) + obj.setColor(black) res := NewVar(token.NoPos, nil, "", Typ[String]) - sig := &Signature{results: NewTuple(res)} + sig := NewSignatureType(nil, nil, nil, nil, NewTuple(res), false) err := NewFunc(token.NoPos, nil, "Error", sig) - typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()} + 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) - def(NewTypeName(token.NoPos, nil, "error", typ)) + def(obj) + } + + // type comparable interface{ /* type set marked comparable */ } + { + obj := NewTypeName(token.NoPos, nil, "comparable", nil) + obj.setColor(black) + ityp := &Interface{nil, obj, nil, nil, nil, false, true, &_TypeSet{true, nil, allTermlist}} + NewNamed(obj, ityp, nil) + def(obj) } } @@ -202,33 +215,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).Complete() - - // 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,18 +224,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) - // "any" is only visible as constraint in a type parameter list - delete(Universe.elems, "any") + 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") } // Objects with names containing blanks are internal and not entered into @@ -263,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 @@ -281,6 +262,6 @@ func def(obj Object) { } } if scope.Insert(obj) != nil { - panic("internal error: double declaration") + panic("double declaration of predeclared identifier") } } diff --git a/src/hash/crc32/crc32_otherarch.go b/src/hash/crc32/crc32_otherarch.go index 936e5bf3e0c8dea18d52dda4505a32002edf3d17..762515257da3849a1da490399a711127fefa1495 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/crc32_ppc64le.s b/src/hash/crc32/crc32_ppc64le.s index 10d5dd61dbcb7791cb32377249c0bfaed77cc9fd..763d3270f30d264894acc9aa44c3c6b429cd33c9 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 diff --git a/src/hash/crc32/gen_const_ppc64le.go b/src/hash/crc32/gen_const_ppc64le.go index c98454c6850cf84290ee92233c5f911b525b2d61..2f15a60b50e3bed04f131ac7d48ed1201d63ffcb 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 ecaf4f9069416b14c27f28c49618a70e1315c110..cd70f97106d990f123addd6dd4b3124d7137c725 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/html/template/attr.go b/src/html/template/attr.go index 22922e6038b651196896976cfaccd56fe33fe34f..6c52211fede1d096f955a6bae656297bd5db8694 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/content.go b/src/html/template/content.go index 6ba87a955035abc49eb3136bdc2eee7537f5aba6..b104267177e1c9d44fdad6325b6a19f7e90bbbb8 100644 --- a/src/html/template/content.go +++ b/src/html/template/content.go @@ -112,16 +112,16 @@ 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 } - 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() @@ -135,12 +135,12 @@ 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 } 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() @@ -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 b7a39d4814b6f732132b857fd21249aba4f3f80c..497264ea329ccd1c6b8220979ba2adec30b6276a 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/context.go b/src/html/template/context.go index f7d4849928d98603a1db9162496362ef45378a26..aaa7d08359397c8fcb3b115561332553384f05b2 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/css.go b/src/html/template/css.go index eb92fc92b55ea65af2a45fe05b7496036d995356..890a0c6b227feb0f58f9a80aa40b5356ef47a840 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 0e527063ea62ae8e3a102fc520ffa52b85313abf..6bb5a2027f6776b68c7d9e6824903f80ad9b6214 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 8739735cb7bc0cdfe6fa4507cd28df47b73919f9..2b11526f52b6921bec06889fe1f99261c563ef45 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 { @@ -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 @@ -865,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...) } @@ -881,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 fbc84a75928b23077a2925598f472839c23b0fdd..58f3f271b7a5c39cb5ce8bc6e9f5edae7444393d 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 @@ -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}}` - 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 888587335de112cd5637f0bfe4e94d3213126c43..6cf710efabc4f49eba8152c4cff41993b42a2dd0 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}, @@ -567,6 +567,8 @@ var execTests = []execTest{ {"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true}, {"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true}, {"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"range []int break else", "{{range .SI}}-{{.}}-{{break}}NOTREACHED{{else}}EMPTY{{end}}", "-3-", tVal, true}, + {"range []int continue else", "{{range .SI}}-{{.}}-{{continue}}NOTREACHED{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true}, {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true}, {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true}, {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true}, @@ -738,7 +740,7 @@ func add(args ...int) int { return sum } -func echo(arg interface{}) interface{} { +func echo(arg any) any { return arg } @@ -757,7 +759,7 @@ func stringer(s fmt.Stringer) string { return s.String() } -func mapOfThree() interface{} { +func mapOfThree() any { return map[string]int{"three": 3} } @@ -1436,7 +1438,7 @@ func TestBlock(t *testing.T) { func TestEvalFieldErrors(t *testing.T) { tests := []struct { name, src string - value interface{} + value any want string }{ { @@ -1579,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 }, @@ -1608,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") }, @@ -1616,7 +1618,7 @@ func TestExecutePanicDuringCall(t *testing.T) { tests := []struct { name string input string - data interface{} + data any wantErr string }{ { @@ -1814,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 356b8298ae36df752fa9f70f67ab97d0c220f6e0..19bd0ccb204b1d57a50d58059762520d5faf228d 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 ea9c18346ba2632b6e04db61e565492b96975156..50523d00f167fd5686ca9ef2ae05d5a88b3d79ec 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 @@ -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() @@ -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 69312d36fdb361ec73b66a712840f902e778a962..7eba716f1b6648c2272213e9c6a1558108fd85a6 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 1f2c888bbea9d2d2d9bc6c51ab4fc74f0237f9f5..99a1091c771076e1700f06d2fa468383d06ac226 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 6f8185a4e90e69a0833c31b8aa4bffdc6ef5bc30..93905586a2f4159eb831ed78dab98fbbf493d99b 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 @@ -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 } @@ -58,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...) } @@ -67,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 @@ -143,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 75c354eba87de41a8d4a8d4c4fc4fe8a0822d685..a04f39cdff530a643d40fa007f76c81c5b6ceee0 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/color/palette/gen.go b/src/image/color/palette/gen.go index 7bb257d865ffa6bfa6ea15240efe916c41fc3695..be46c57020c58e1ac69f02e08ae85ea435e8094f 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/draw/bench_test.go b/src/image/draw/bench_test.go index 831fd958ba3ed3efb292c12ef09aea4f6bd58607..55d25b85963f422794923b6c10450372d4918aba 100644 --- a/src/image/draw/bench_test.go +++ b/src/image/draw/bench_test.go @@ -232,6 +232,18 @@ func BenchmarkGlyphOver(b *testing.B) { bench(b, color.RGBAModel, nil, color.AlphaModel, Over) } +func BenchmarkRGBAMaskOver(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) } diff --git a/src/image/draw/draw.go b/src/image/draw/draw.go index 13f6668293814e7b0c4d8e3271164c94d72eeb30..7dd18dfdb59a1b11ece550a1d2f3da58c4078022 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 { @@ -159,6 +160,17 @@ 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 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 } } } else { @@ -219,6 +231,88 @@ 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 + // 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 + } + } + } + + // 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. + var out color.RGBA64 sy := sp.Y + y0 - r.Min.Y my := mp.Y + y0 - r.Min.Y @@ -519,6 +613,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 @@ -536,6 +780,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 9c5a118400e095ebc3681a479e4e0c1448352a3e..3be93962ad738e2e4de88e5e9c57763e64c39f4b 100644 --- a/src/image/draw/draw_test.go +++ b/src/image/draw/draw_test.go @@ -13,6 +13,172 @@ 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 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 any = (*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 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 any = (*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() @@ -178,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}. @@ -188,13 +380,32 @@ 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}. // 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}}, + // 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}}, } func makeGolden(dst image.Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) image.Image { @@ -260,30 +471,45 @@ 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: + dst = convertToSlowerRGBA(dst) + case 2: + dst = convertToSlowestRGBA(dst) + } + + // 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 + } } } } diff --git a/src/image/internal/imageutil/gen.go b/src/image/internal/imageutil/gen.go index 38f41303fa747fa23b67f2306bc761eecde9ee28..65e1e30b64f700694b4276ef00fdfdec53ecace7 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 6508533f4440b3f2816c43593e4beee387a30030..688b6c99361339b07d95ad931d9aac9f0c307331 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/image/png/reader.go b/src/image/png/reader.go index 910520bd4b343037a2941494626cd00420f6533d..4c65038cb5bd534d147b212fefca158b5e4b1b92 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 diff --git a/src/index/suffixarray/gen.go b/src/index/suffixarray/gen.go index 3bc9b1e2aea4328551f95aa8da19c5f3ab83ac44..d6eb32e2aeefa318724befe041c973d7edfd50fc 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.go b/src/internal/abi/abi.go index aaff9cece35720aef56455742b2f4556ba1f98d8..11acac346fbbc6fa3ae3abdac726fc1d6898658e 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. @@ -16,6 +19,14 @@ import "unsafe" // 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 @@ -33,6 +44,44 @@ 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. +// +// 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) +} + // IntArgRegBitmap is a bitmap large enough to hold one bit per // integer argument/return register. type IntArgRegBitmap [(IntArgRegs + 7) / 8]uint8 @@ -65,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. @@ -74,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/abi/abi_amd64.go b/src/internal/abi/abi_amd64.go index aff71f6a58a9553a7bc7175dfb287cf13e907d8b..d3c567822311b162b2ff2be048361bb5ac1819eb 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_arm64.go b/src/internal/abi/abi_arm64.go new file mode 100644 index 0000000000000000000000000000000000000000..5c3dd6cbe2815ae73be8ea286490056ccba333b1 --- /dev/null +++ b/src/internal/abi/abi_arm64.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 goexperiment.regabireflect + +package abi + +const ( + // See abi_generic.go. + + // R0 - R15. + IntArgRegs = 16 + + // F0 - F15. + FloatArgRegs = 16 + + EffectiveFloatRegSize = 8 +) diff --git a/src/internal/abi/abi_generic.go b/src/internal/abi/abi_generic.go index 69400f930fb12b50b1df1a24a89aaa0e577d17b5..a36745f402c414cb01dc8b63921c3303777c7c09 100644 --- a/src/internal/abi/abi_generic.go +++ b/src/internal/abi/abi_generic.go @@ -2,8 +2,7 @@ // 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 package abi diff --git a/src/internal/abi/abi_ppc64x.go b/src/internal/abi/abi_ppc64x.go new file mode 100644 index 0000000000000000000000000000000000000000..d47271d1a18836e4c65068e3149a1bf630d97f61 --- /dev/null +++ b/src/internal/abi/abi_ppc64x.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 goexperiment.regabireflect && (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/cfg.go b/src/internal/buildcfg/cfg.go index 9fe7f211fb3024951e24ce2f0f6f66f9572f2fb0..68c10a282465887f1b3b5aa2fb3f436888e8cf40 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 0000000000000000000000000000000000000000..0123593317d4319bf94ee3c12d7a910a5c35c13d --- /dev/null +++ b/src/internal/buildcfg/cfg_test.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 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") + } + Error = nil + os.Setenv("GOAMD64", "1") + if goamd64(); Error == nil { + t.Errorf("Wrong parsing of GOAMD64=1") + } +} diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 9a60253aab9b1830815bf4b69ffd3fee32474974..a9b29d6718c5cf08220127a6dbf11057a84899d7 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -46,14 +46,17 @@ 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" && (goos == "android" || goos == "linux" || goos == "darwin" || goos == "windows") + regabiSupported := false + switch goarch { + case "amd64", "arm64", "ppc64le", "ppc64": + regabiSupported = true + } baseline = goexperiment.Flags{ RegabiWrappers: regabiSupported, - RegabiG: regabiSupported, RegabiReflect: regabiSupported, - RegabiDefer: regabiSupported, RegabiArgs: regabiSupported, + PacerRedesign: true, } // Start with the statically enabled set of experiments. @@ -78,9 +81,7 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment // do the right thing. names["regabi"] = func(v bool) { flags.RegabiWrappers = v - flags.RegabiG = v flags.RegabiReflect = v - flags.RegabiDefer = v flags.RegabiArgs = v } @@ -109,20 +110,20 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment } } - // regabi is only supported on amd64. - if goarch != "amd64" { - flags.RegabiWrappers = false - flags.RegabiG = false + // regabi is always enabled on amd64. + if goarch == "amd64" { + flags.RegabiWrappers = true + flags.RegabiReflect = true + flags.RegabiArgs = true + } + // regabi is only supported on amd64, arm64, ppc64 and ppc64le. + if !regabiSupported { flags.RegabiReflect = false - flags.RegabiDefer = false flags.RegabiArgs = false } // Check regabi dependencies. - if flags.RegabiG && !flags.RegabiWrappers { - err = fmt.Errorf("GOEXPERIMENT regabig requires regabiwrappers") - } - if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiG && flags.RegabiReflect && flags.RegabiDefer) { - err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabig,regabireflect,regabidefer") + if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) { + err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect") } return } @@ -162,7 +163,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 diff --git a/src/internal/bytealg/bytealg.go b/src/internal/bytealg/bytealg.go index 6b2b540acc8846ce1707641930e3d185690ab295..ebebce75fe484a0317be60a053c473726b944f72 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 0981983d20f313bd5fd2f750afe89b6aab61f8fc..27b660ccf7c526ac70be5f016695cb19238aa19c 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/compare_amd64.s b/src/internal/bytealg/compare_amd64.s index 8295acb03a184d17d28bae5f141d06a7de437a05..4ccaca5e87b23b397078d20ed8b413773469d2d5 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/compare_arm64.s b/src/internal/bytealg/compare_arm64.s index 56d56f241eb8696d2a22c6133148ce7f8625c933..5a80207258313dbb984be319d5818aa74498fcea 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/compare_generic.go b/src/internal/bytealg/compare_generic.go index 0690d0cf31c51e1a4d908af72fb1a783e03f6eb5..eaea168f2de738ef38a2cf4b1bd6bd26be995650 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_mips64x.s b/src/internal/bytealg/compare_mips64x.s index b472e510bce7a5872a210da038e7a820186f21e5..117a9ef631fd2b572eff3408fd8d27f0bacc98b9 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 dcc4916e567141bcd18cb07c3832f8cfa060a79f..857ac1338906f4bec64eb7b83242eb794d41ccbc 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_native.go b/src/internal/bytealg/compare_native.go index baa188ff7af553ffbcbbf66de34347f3b4134b7f..21ff8fe786d9bf54c5b81dc8cf2a6606be20b571 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/compare_ppc64x.s b/src/internal/bytealg/compare_ppc64x.s index 83444fa826008b1ed0de2fa053f05bd59935f6e5..2793e44e8be87204c92a6564942d62141aa4a54d 100644 --- a/src/internal/bytealg/compare_ppc64x.s +++ b/src/internal/bytealg/compare_ppc64x.s @@ -3,69 +3,103 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #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 +107,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 +202,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 +309,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/count_generic.go b/src/internal/bytealg/count_generic.go index 1891d29b24cb4a6646e4e85fb5263d44e0e2a655..932a7c584c1ae60517465e615feafd815c2e3e83 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 a19a6f8223fe9e495cda45dd9d775dc969e532ec..90189c9fe051bd12fd25b20993282ebf83e59744 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/count_ppc64x.s b/src/internal/bytealg/count_ppc64x.s index 94163cbd8a398d837d10a147a9c2b7d68e9ff26d..43d547bb8a7e21c06e01ab99486bddeb4bb9d042 100644 --- a/src/internal/bytealg/count_ppc64x.s +++ b/src/internal/bytealg/count_ppc64x.s @@ -3,29 +3,41 @@ // license that can be found in the LICENSE file. //go:build ppc64le || ppc64 -// +build ppc64le ppc64 #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 +106,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/equal_386.s b/src/internal/bytealg/equal_386.s index 87233635a927d35cd6018fa692f3081317575eca..58b3cbe3d07194b5eddd4a3ef2f0b5425d8cb485 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/bytealg/equal_amd64.s b/src/internal/bytealg/equal_amd64.s index 6f12d2a1690380d5e92326a96f775e799165b6e5..dd46e2e0fdfb0ea32485f4660ecfa66197b764db 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/internal/bytealg/equal_arm64.s b/src/internal/bytealg/equal_arm64.s index 01aa7b7b7aa8adbc0f1945a072e6c2a576c082fc..cf5cf54e5971a33223f909696503c1bace31baea 100644 --- a/src/internal/bytealg/equal_arm64.s +++ b/src/internal/bytealg/equal_arm64.s @@ -6,58 +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,$40-17 - MOVD a+0(FP), R3 - MOVD b+8(FP), R4 - CMP R3, R4 +TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-17 +#ifndef GOEXPERIMENT_regabiargs + MOVD a+0(FP), R0 + MOVD b+8(FP), R1 +#endif + CMP R0, R1 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), 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 @@ -71,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/internal/bytealg/equal_mips64x.s b/src/internal/bytealg/equal_mips64x.s index c2f7d3997edb36c0d38ad5739c4f5b61455cd3aa..d92f225e8d29d1a87263faeb593683144a8c9d64 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 11e5549e45a1fac488a6c8e65164cf8cb0887edf..4c46dd4fce42d0d8b595826095c5e873930516ca 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 5f0fea521b24a74687bb9cf3a42db3dd517049f5..bd8caa7f1831b7dda5fdbbe00c1857ff22718ebe 100644 --- a/src/internal/bytealg/equal_ppc64x.s +++ b/src/internal/bytealg/equal_ppc64x.s @@ -3,39 +3,43 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "go_asm.h" #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 +98,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/index_generic.go b/src/internal/bytealg/index_generic.go index 0a6eb90d2d9297fbcffd1195c9ea3f515d5b73c2..a59e32938e76ec2dc1a7b5e6e4b9f958e284a9df 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 9547a5d8e2aa39e4ea7a543c09f8a555b099d313..6e4a2f39e4317fc4e7b7fe836bd8912cf141d093 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 c9b2b5a59f836dd1f45ede0766b04edbbc141377..ab3cbe5e96e6ba86e4e64ab8bb1ab069ed677411 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/index_ppc64x.s b/src/internal/bytealg/index_ppc64x.s index 3ed94421256115bef15079f524ff3672a7330f31..2d2a7146f175b5497cbf60fa946d73607dc37d5d 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" @@ -46,12 +45,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,18 +70,21 @@ 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 CMP R7, $1 BNE power8 - BR indexbody<>(SB) + BR indexbodyp9<>(SB) #endif power8: @@ -141,7 +151,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 @@ -420,8 +430,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 +446,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 @@ -467,7 +489,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 @@ -746,8 +768,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 +784,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 diff --git a/src/internal/bytealg/indexbyte_generic.go b/src/internal/bytealg/indexbyte_generic.go index 6ef639fafdc992dd24023267efda30dca57947ef..0a45f903843edd8ae28d3ed07a63de5e7db35995 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_mips64x.s b/src/internal/bytealg/indexbyte_mips64x.s index 0f377f5a4c9e330d936d18dbd7efc501fe08197e..5689f84b47a54a580fa878501e0fcbdbabc2057b 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 bed015bbd6b5af3d4d54bafcaad3fc06d0b3c1bd..1c2b104d3c9efdbb92b4e01c3269b2823cd76f2d 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_native.go b/src/internal/bytealg/indexbyte_native.go index 965f38fe52761cb34643ecbc6af03df92a94b91c..2101021e2d0254bcdc5b66b6a3633f01816cc38f 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/bytealg/indexbyte_ppc64x.s b/src/internal/bytealg/indexbyte_ppc64x.s index 8e13c5a56e348674dc6c232534b043a95d74c9b5..87ef8ecffcdec853194e7226aced7a43dfb4af7f 100644 --- a/src/internal/bytealg/indexbyte_ppc64x.s +++ b/src/internal/bytealg/indexbyte_ppc64x.s @@ -3,25 +3,33 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #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 +194,9 @@ tail: notfound: MOVD $-1,R3 +#ifndef GOEXPERIMENT_regabiargs MOVD R3,(R14) +#endif RET found: @@ -229,7 +239,9 @@ found: return: SUB R17,R3 +#ifndef GOEXPERIMENT_regabiargs MOVD R3,(R14) +#endif RET found_qw_align: diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go index 815994b679ac3c70658822a155d9981e4576da54..4cb3fbd4f342a4615a8483f352b45974b3a4ec79 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/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index dab5d068ef36e4ef5bf1d028bced35fc7cd5fa94..30745344e1c816e5986f386c0c112ebb981f98b2 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -36,7 +36,7 @@ var X86 struct { HasOSXSAVE bool HasPCLMULQDQ bool HasPOPCNT bool - HasSSE2 bool + HasRDTSCP bool HasSSE3 bool HasSSSE3 bool HasSSE41 bool @@ -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_arm64_android.go b/src/internal/cpu/cpu_arm64_android.go index ac6eee54b211389b095a5bc3acdaf30e46535fb5..fbdf7baca2f14d598ff002c4dea74b954780f84b 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 ce1b250a18913792c2733007b3e0259fb64950f4..730e14caff09a9ac4e437127ff381cbafa21c337 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 8c481370da65778478a7dbdbff65bc2b990c6193..c25e021c68f1c168cdd1be7d2df147585115fef5 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 8ac04fd8f975b8d5b18967b47c085c432948d360..0baa39f9cf79b0b98f6f92ecb5287578f790ec77 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 c3a3f9a8e9d64d97d3dc40546be5845503feda33..d746bdb063ed96cb2917bdb062fb9b2c510aedad 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 e8b5d529a4bbd6517b563bb6ece707c5ef54a9c4..d313648cb7c4544f6c1d3a0ab66cdd488124f674 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 d2f9d4499ba375f258cc163d328ef361e64441e2..c452ffd8b30216641232ad2f5c0713652c9488f5 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 8d563b536c3364ddcbe54e2fe6e0bbcf9c15cd2b..37de951ba6d783cd5e66b9a5f6e33496e132429e 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 2e7fd3ebb9f75fecb31ee0b2f2bc247a4bef6940..83687d6ed3438f8f933bc7b58b6b9122d761262b 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 3d17a9c7304a565d926d91ff2462cc9098a8cd61..d518edcf490b7e23f09eb583715d845ca85a068b 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 b7c73451118b5a238e8c51f66a977e7db6b44ba0..7999656f01fc655d3eba347576d29c6160cd319c 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_test.go b/src/internal/cpu/cpu_test.go index 2de7365732d7482242648068aa78bdd77453ab25..8c21256b34825e4972c97814cc5740dee034f8b3 100644 --- a/src/internal/cpu/cpu_test.go +++ b/src/internal/cpu/cpu_test.go @@ -6,31 +6,14 @@ package cpu_test import ( . "internal/cpu" + "internal/godebug" "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") @@ -70,12 +53,12 @@ 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") } 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) } diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go index fd1217a05d7cab12bf2b7c0acd38553cafd47c03..81d5ceed61a1608698e581e936588c1899318a6a 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 @@ -37,6 +36,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,13 +55,11 @@ 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}, {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) @@ -70,8 +70,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) @@ -112,6 +111,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/internal/cpu/cpu_x86.s b/src/internal/cpu/cpu_x86.s index 0df5da1cc74d45b42b26940b4e03c8d8e8b7154b..edef21905ca51c7b1a50e170d738295d86fe8cbb 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/internal/cpu/cpu_x86_test.go b/src/internal/cpu/cpu_x86_test.go index e3e16cc1612e05955295a965204ca0dc66e497aa..c8be210055c6e2ad3c3ad3ece9e358e9f40626b2 100644 --- a/src/internal/cpu/cpu_x86_test.go +++ b/src/internal/cpu/cpu_x86_test.go @@ -3,14 +3,12 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 -// +build 386 amd64 package cpu_test import ( . "internal/cpu" - "os" - "runtime" + "internal/godebug" "testing" ) @@ -20,23 +18,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") } @@ -44,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") } diff --git a/src/internal/fmtsort/sort.go b/src/internal/fmtsort/sort.go index 7127ba6ac3d970379f1aa29629418992c94c082d..34c1f477f0e31438209c5c96b4a1b20d2cf58511 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/fmtsort/sort_test.go b/src/internal/fmtsort/sort_test.go index 5c4db1c5faa950236eba33bac73263d304299b7a..11befca6f1921f091d4ac6ede011f5a0f057143a 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" @@ -37,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) @@ -83,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{ @@ -134,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" @@ -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-- { @@ -233,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/counters_supported.go b/src/internal/fuzz/counters_supported.go new file mode 100644 index 0000000000000000000000000000000000000000..7ef553aaf2eded679ea1f0574d91572c3198c470 --- /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 0000000000000000000000000000000000000000..bf281570681fb57542fc5d7dba7b644d964c75e5 --- /dev/null +++ b/src/internal/fuzz/counters_unsupported.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. + +// 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 + +// TODO(#48504): re-enable on platforms where instrumentation works. +// 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 +// `-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 new file mode 100644 index 0000000000000000000000000000000000000000..3dee73b81ce020ca6e22864e3a2d41fac8fe633c --- /dev/null +++ b/src/internal/fuzz/coverage.go @@ -0,0 +1,96 @@ +// Copyright 2021 The Go Authors. 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" + "math/bits" +) + +// 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 + } +} + +// SnapshotCoverage copies the current counter values into coverageSnapshot, +// 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() + for i, b := range cov { + b |= b >> 1 + b |= b >> 2 + b |= b >> 4 + b -= b >> 1 + coverageSnapshot[i] = b + } +} + +// 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 { + 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 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 ( + 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. + _counters, _ecounters [0]byte +) diff --git a/src/internal/fuzz/encoding.go b/src/internal/fuzz/encoding.go new file mode 100644 index 0000000000000000000000000000000000000000..2bfa02b8c06d96af0177cc5335cfda963ba4ef83 --- /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 = "go test fuzz v1" + +// marshalCorpusFile encodes an arbitrary number of arguments into the file format for the +// corpus. +func marshalCorpusFile(vals ...any) []byte { + if len(vals) == 0 { + panic("must have at least one value to marshal") + } + 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, "%T(%v)\n", t, t) + case string: + fmt.Fprintf(b, "string(%q)\n", t) + case rune: // int32 + fmt.Fprintf(b, "rune(%q)\n", t) + case byte: // uint8 + fmt.Fprintf(b, "byte(%q)\n", t) + case []byte: // []uint8 + fmt.Fprintf(b, "[]byte(%q)\n", t) + default: + panic(fmt.Sprintf("unsupported type: %T", t)) + } + } + return b.Bytes() +} + +// unmarshalCorpusFile decodes corpus bytes into their respective values. +func unmarshalCorpusFile(b []byte) ([]any, error) { + if len(b) == 0 { + return nil, fmt.Errorf("cannot unmarshal 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 []any + 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) (any, 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 && 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 && kind != token.INT { + return nil, fmt.Errorf("float or integer 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) (any, 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) (any, 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 0000000000000000000000000000000000000000..b429d429c673723203ca324a870369dfa5f9d82f --- /dev/null +++ b/src/internal/fuzz/encoding_test.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. + +package fuzz + +import ( + "strconv" + "strings" + "testing" +) + +func TestUnmarshalMarshal(t *testing.T) { + var tests = []struct { + in string + ok bool + }{ + { + in: "int(1234)", + ok: false, // missing version + }, + { + in: `go test fuzz v1 +string("a"bcad")`, + ok: false, // malformed + }, + { + in: `go test fuzz v1 +int()`, + ok: false, // empty value + }, + { + in: `go test fuzz v1 +uint(-32)`, + ok: false, // invalid negative uint + }, + { + in: `go test fuzz v1 +int8(1234456)`, + ok: false, // int8 too large + }, + { + in: `go test fuzz v1 +int(20*5)`, + ok: false, // expression in int value + }, + { + in: `go test fuzz v1 +int(--5)`, + ok: false, // expression in int value + }, + { + in: `go test fuzz v1 +bool(0)`, + ok: false, // malformed bool + }, + { + in: `go test fuzz v1 +byte('aa)`, + ok: false, // malformed byte + }, + { + in: `go test fuzz v1 +byte('☃')`, + ok: false, // byte out of range + }, + { + 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, // extra spaces in the final newline + }, + { + 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) +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) + } + 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) + } + }) + } +} + +// 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 new file mode 100644 index 0000000000000000000000000000000000000000..b3f1381dbbf58aaf61aaaf068b94e3a83ed691e1 --- /dev/null +++ b/src/internal/fuzz/fuzz.go @@ -0,0 +1,1074 @@ +// 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 ( + "context" + "crypto/sha256" + "errors" + "fmt" + "internal/godebug" + "io" + "io/ioutil" + "math/bits" + "os" + "path/filepath" + "reflect" + "runtime" + "strings" + "sync" + "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 + + // Limit is the number of random values to generate and test. If zero, + // there will be no limit on the number of generated values. + 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. 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. 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, + // 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 +// 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. +// +// 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, opts CoordinateFuzzingOpts) (err error) { + if err := ctx.Err(); err != nil { + return err + } + if opts.Log == nil { + opts.Log = io.Discard + } + if opts.Parallel == 0 { + opts.Parallel = runtime.GOMAXPROCS(0) + } + if opts.Limit > 0 && int64(opts.Parallel) > opts.Limit { + // Don't start more workers than we need. + opts.Parallel = int(opts.Limit) + } + + c, err := newCoordinator(opts) + if err != nil { + return err + } + + if opts.Timeout > 0 { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, opts.Timeout) + defer cancel() + } + + // 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 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 + cancelWorkers() + doneC = nil + } + + // Ensure that any crash we find is written to the corpus, even if an error + // or interruption occurs while minimizing it. + crashWritten := false + defer func() { + if c.crashMinimizing == nil || crashWritten { + return + } + werr := writeToCorpus(&c.crashMinimizing.entry, opts.CorpusDir) + if werr != nil { + err = fmt.Errorf("%w\n%v", err, werr) + return + } + if err == nil { + err = &crashError{ + path: c.crashMinimizing.entry.Path, + err: errors.New(c.crashMinimizing.crasherMsg), + } + } + }() + + // 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(c, dir, binPath, args, env) + if err != nil { + return err + } + } + for i := range workers { + 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 + } + errC <- err + }() + } + + // Main event loop. + // 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) + statTicker := time.NewTicker(3 * time.Second) + defer statTicker.Stop() + defer c.logStats() + + c.logStats() + for { + var inputC chan fuzzInput + input, ok := c.peekInput() + if ok && c.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. + if stopping { + break + } + c.updateStats(result) + + if result.crasherMsg != "" { + if c.warmupRun() && result.entry.IsSeed { + target := filepath.Base(c.opts.CorpusDir) + 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 + } + if c.canMinimize() && result.canMinimize { + 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 + } + // 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. + c.crashMinimizing = &result + 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. + // Write to corpus and stop. + err := writeToCorpus(&result.entry, opts.CorpusDir) + if err == nil { + crashWritten = true + err = &crashError{ + path: result.entry.Path, + err: errors.New(result.crasherMsg), + } + } + if shouldPrintDebugInfo() { + fmt.Fprintf( + c.opts.Log, + "DEBUG new crasher, elapsed: %s, id: %s, parent: %s, gen: %d, size: %d, exec time: %s\n", + c.elapsed(), + result.entry.Path, + result.entry.Parent, + result.entry.Generation, + len(result.entry.Data), + result.entryDuration, + ) + } + stop(err) + } + } else if result.coverageData != nil { + if c.warmupRun() { + 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", + c.elapsed(), + result.entry.Parent, + countBits(diffCoverage(c.coverageMask, result.coverageData)), + len(result.entry.Data), + result.entryDuration, + ) + } + c.updateCoverage(result.coverageData) + 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. + // 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 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) + } else { + // 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) + } + result.entry.Data = nil + } + c.updateCoverage(keepCoverage) + c.corpus.entries = append(c.corpus.entries, result.entry) + c.inputQueue.enqueue(result.entry) + c.interestingCount++ + 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", + c.elapsed(), + result.entry.Path, + result.entry.Parent, + result.entry.Generation, + countBits(keepCoverage), + countBits(c.coverageMask), + inputSize, + result.entryDuration, + ) + } + } + } else { + if shouldPrintDebugInfo() { + fmt.Fprintf( + 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.Path, + result.entry.Parent, + result.canMinimize, + ) + } + } + } else if c.warmupRun() { + // No error or coverage data was reported for this input during + // warmup, so continue processing results. + 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) + + case minimizeC <- minimizeInput: + // Sent the next input for minimization to a worker. + c.sentMinimizeInput(minimizeInput) + + case <-statTicker.C: + c.logStats() + } + } + + // 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 +// 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 { + path string + err error +} + +func (e *crashError) Error() string { + return e.err.Error() +} + +func (e *crashError) Unwrap() error { + return e.err +} + +func (e *crashError) CrashPath() string { + return e.path +} + +type corpus struct { + entries []CorpusEntry +} + +// 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 { + Parent 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 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. + Values []any + + 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, +// or from disk. +func CorpusEntryData(ce CorpusEntry) ([]byte, error) { + if ce.Data != nil { + return ce.Data, nil + } + + return os.ReadFile(ce.Path) +} + +type fuzzInput struct { + // entry is the value to test initially. The worker will randomly mutate + // values from this starting point. + entry CorpusEntry + + // 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 + + // warmup indicates whether this is a warmup input before fuzzing begins. If + // true, the input should not be fuzzed. + warmup bool + + // coverageData reflects the coordinator's current coverageMask. + coverageData []byte +} + +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 + + // 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 + + // limit is the number of values the coordinator asked the worker + // to test. 0 if there was no limit. + limit int64 + + // count is the number of values the worker actually tested. + count int64 + + // 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 +} + +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 + + // 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 +// the coordinator. +type coordinator struct { + opts CoordinateFuzzingOpts + + // 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. 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 fuzzMinimizeInput + + // resultC is sent results of fuzzing by workers. The coordinator + // receives these. Multiple types of messages are allowed. + resultC chan fuzzResult + + // 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 + + // 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 + + // 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 + // generated values that workers reported as interesting. + corpus corpus + + // minimizationAllowed is true if one or more of the types of fuzz + // function's parameters can be minimized. + 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 + // 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 + + // 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 + // 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) { + // 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...) + } + } + corpus, err := readCache(opts.Seed, opts.Types, opts.CacheDir) + if err != nil { + return nil, err + } + c := &coordinator{ + 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 { + if isMinimizable(t) { + c.minimizationAllowed = true + break + } + } + } + + 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 { + c.warmupInputCount = len(c.corpus.entries) + for _, e := range c.corpus.entries { + c.inputQueue.enqueue(e) + } + // 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") + var vals []any + 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{Path: name, Data: data}) + } + + return c, nil +} + +func (c *coordinator) updateStats(result fuzzResult) { + c.count += result.count + c.countWaiting -= result.limit + c.duration += result.totalDuration +} + +func (c *coordinator) logStats() { + now := time.Now() + if c.warmupRun() { + runSoFar := c.warmupInputCount - c.warmupInputLeft + if coverageEnabled { + 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, "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 { + 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)\n", c.elapsed(), c.count, rate) + } + } + c.countLastLog = c.count + c.timeLastLog = now +} + +// 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, peekInput returns +// a zero value and false. +// +// 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/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 { + // 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.warmupRun() { + // Wait for coverage/testing-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: entry.(CorpusEntry), + timeout: workerFuzzDuration, + warmup: c.warmupRun(), + } + 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 + } + + if c.opts.Limit > 0 { + 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 + } + } + return input, true +} + +// 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, + keepCoverage: keepCoverage, + } + 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.canMinimize() { + // 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 input.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++ + } + } + } + if c.opts.Limit > 0 { + remaining := c.opts.Limit - c.count - c.countWaiting + 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 +} + +// 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 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) warmupRun() bool { + return c.warmupInputLeft > 0 +} + +// 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 { + if len(newCoverage) != len(c.coverageMask) { + panic(fmt.Sprintf("number of coverage counters changed at runtime: %d, expected %d", len(newCoverage), len(c.coverageMask))) + } + newBitCount := 0 + for i := range newCoverage { + diff := newCoverage[i] &^ c.coverageMask[i] + newBitCount += bits.OnesCount8(diff) + c.coverageMask[i] |= newCoverage[i] + } + 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.minimizationAllowed && + (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). +// +// 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 + c.entries = append(c.entries, seed...) + entries, err := ReadCorpus(cacheDir, types) + if err != nil { + 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 +} + +// 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("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. + // 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 + } + filename := filepath.Join(dir, file.Name()) + data, err := ioutil.ReadFile(filename) + if err != nil { + return nil, fmt.Errorf("failed to read corpus file: %v", err) + } + var vals []any + vals, err = readCorpusData(data, types) + if err != nil { + errs = append(errs, fmt.Errorf("%q: %v", filename, err)) + continue + } + corpus = append(corpus, CorpusEntry{Path: filename, Values: vals}) + } + if len(errs) > 0 { + return corpus, &MalformedCorpusError{errs: errs} + } + return corpus, nil +} + +func readCorpusData(data []byte, types []reflect.Type) ([]any, error) { + vals, err := unmarshalCorpusFile(data) + 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. +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)) + } + valsT := make([]reflect.Type, len(vals)) + for valsI, v := range vals { + valsT[valsI] = reflect.TypeOf(v) + } + for i := range types { + if valsT[i] != types[i] { + return fmt.Errorf("mismatched types in corpus entry: %v, want %v", valsT, types) + } + } + 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 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 + } + if err := ioutil.WriteFile(entry.Path, entry.Data, 0666); err != nil { + os.Remove(entry.Path) // remove partially written file + return err + } + return nil +} + +func testName(path string) string { + return filepath.Base(path) +} + +func zeroValue(t reflect.Type) any { + for _, v := range zeroVals { + if reflect.TypeOf(v) == t { + return v + } + } + panic(fmt.Sprintf("unsupported type: %v", t)) +} + +var zeroVals []any = []any{ + []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), +} + +var ( + debugInfo bool + debugInfoOnce sync.Once +) + +func shouldPrintDebugInfo() bool { + debugInfoOnce.Do(func() { + debugInfo = godebug.Get("fuzzdebug") == "1" + }) + return debugInfo +} diff --git a/src/internal/fuzz/mem.go b/src/internal/fuzz/mem.go new file mode 100644 index 0000000000000000000000000000000000000000..d6d45be20ef3885487b4e7eee4c3a5dae2c3d994 --- /dev/null +++ b/src/internal/fuzz/mem.go @@ -0,0 +1,140 @@ +// 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 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 + + // 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 { + // count is the number of times the worker has called the fuzz function. + // May be reset by coordinator. + count int64 + + // 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 +// 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 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 { + return nil, err + } + defer func() { + if err != nil { + f.Close() + os.Remove(f.Name()) + } + }() + + // Resize it to the correct size. + totalSize := sharedMemSize(size) + 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])) +} + +// 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().valueLen + 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.valueRef() + if len(b) > cap(v) { + panic(fmt.Sprintf("value length %d larger than shared memory capacity %d", len(b), cap(v))) + } + m.header().valueLen = len(b) + 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().valueLen = 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 +// remap the file. diff --git a/src/internal/fuzz/minimize.go b/src/internal/fuzz/minimize.go new file mode 100644 index 0000000000000000000000000000000000000000..0e410fb86a3ff83c50c0bf1bf1c93a1cc2d72514 --- /dev/null +++ b/src/internal/fuzz/minimize.go @@ -0,0 +1,95 @@ +// Copyright 2021 The Go Authors. 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 ( + "reflect" +) + +func isMinimizable(t reflect.Type) bool { + return t == reflect.TypeOf("") || t == reflect.TypeOf([]byte(nil)) +} + +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 + // 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 { + if shouldStop() { + return + } + candidate := v[:len(v)-n] + if !try(candidate) { + break + } + // Set v to the new value to continue iterating. + v = candidate + } + } + + // Then, try to remove each individual byte. + 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 !try(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 !try(candidate) { + continue + } + // Update v and reset the loop with the new length. + copy(v[i:], v[j:]) + v = v[:len(candidate)] + 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 + } + } +} diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6e5f3184b4e06fb69841436817172be3825c7c99 --- /dev/null +++ b/src/internal/fuzz/minimize_test.go @@ -0,0 +1,182 @@ +// Copyright 2021 The Go 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 + +package fuzz + +import ( + "bytes" + "context" + "errors" + "fmt" + "reflect" + "testing" + "time" + "unicode" + "unicode/utf8" +) + +func TestMinimizeInput(t *testing.T) { + type testcase struct { + name string + fn func(CorpusEntry) error + input []any + expected []any + } + cases := []testcase{ + { + name: "ones_byte", + 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: []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", + 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: []any{[]byte{1, 2, 3, 4, 5}}, + expected: []any{[]byte("00")}, + }, + { + 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: []any{[]byte{0, 1, 2, 3, 4, 5}}, + expected: []any{[]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: []any{[]byte("ท")}, // ท is 3 bytes + expected: []any{[]byte("000")}, + }, + { + name: "ones_string", + 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: []any{"001010001000000000000000000"}, + expected: []any{"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: []any{"zzzzz"}, + expected: []any{"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: []any{"ZZZZZ"}, + expected: []any{"A"}, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + ws := &workerServer{ + fuzzFn: func(e CorpusEntry) (time.Duration, error) { + return time.Second, tc.fn(e) + }, + } + mem := &sharedMem{region: make([]byte, 100)} // big enough to hold value and header + vals := tc.input + success, err := ws.minimizeInput(context.Background(), vals, mem, minimizeArgs{}) + if !success { + t.Errorf("minimizeInput did not succeed") + } + if err == nil { + t.Fatal("minimizeInput didn't provide an error") + } + 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) + } + }) + } +} + +// 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) (time.Duration, error) { + return time.Second, errors.New("ohno") + }} + mem := &sharedMem{region: make([]byte, 100)} // big enough to hold value and header + vals := []any{[]byte(nil)} + 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 := mem.header().count; count != 1 { + t.Errorf("count: got %d, want 1", count) + } +} diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go new file mode 100644 index 0000000000000000000000000000000000000000..e26ae5a5836c2e47707019d3596dbf705a43374f --- /dev/null +++ b/src/internal/fuzz/mutator.go @@ -0,0 +1,303 @@ +// 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/binary" + "fmt" + "math" + "reflect" + "unsafe" +) + +type mutator struct { + r mutatorRand + scratch []byte // scratch slice to avoid additional allocations +} + +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 [1,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 on the provided values. +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. + + // 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)) + 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: + if len(v) > maxPerVal { + panic(fmt.Sprintf("cannot mutate bytes of length %d", len(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(&m.scratch) + vals[i] = string(m.scratch) + case []byte: + if len(v) > maxPerVal { + panic(fmt.Sprintf("cannot mutate bytes of length %d", len(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(&m.scratch) + vals[i] = m.scratch + default: + panic(fmt.Sprintf("type not supported for mutating: %T", vals[i])) + } +} + +func (m *mutator) mutateInt(v, maxValue int64) int64 { + var max int64 + for { + max = 100 + switch m.rand(2) { + case 0: + // Add a random number + if v >= maxValue { + continue + } + if v > 0 && maxValue-v < max { + // Don't let v exceed maxValue + max = maxValue - v + } + v += int64(1 + m.rand(int(max))) + return v + case 1: + // Subtract a random number + if v <= -maxValue { + 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 { + var max uint64 + for { + max = 100 + switch m.rand(2) { + case 0: + // Add a random number + if v >= maxValue { + continue + } + if v > 0 && maxValue-v < max { + // Don't let v exceed maxValue + max = maxValue - v + } + + v += uint64(1 + m.rand(int(max))) + return v + case 1: + // Subtract a random number + if v <= 0 { + 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 { + var max float64 + for { + switch m.rand(4) { + 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 += float64(1 + m.rand(int(max))) + return v + 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 -= float64(1 + m.rand(int(max))) + return v + case 2: + // Multiply by a random number + absV := math.Abs(v) + if v == 0 || absV >= maxValue { + 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))) + return v + case 3: + // Divide by a random number + if v == 0 { + continue + } + v /= float64(1 + m.rand(10)) + 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() { + 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 + }() + + for { + mut := byteSliceMutators[m.rand(len(byteSliceMutators))] + if mutated := mut(m, b); mutated != nil { + b = mutated + return + } + } +} + +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} +) + +const ( + maxUint = uint64(^uint(0)) + maxInt = int64(maxUint >> 1) +) + +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/mutator_test.go b/src/internal/fuzz/mutator_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cea7e2e3be8c33fb52661a3d21dda15653d53cd9 --- /dev/null +++ b/src/internal/fuzz/mutator_test.go @@ -0,0 +1,117 @@ +// Copyright 2021 The Go Authors. 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" + "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)) + m := newMutator() + + for _, size := range []int{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + } { + 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.r = newPcgRand() + m.mutate([]any{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)) + m := newMutator() + + for _, size := range []int{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + } { + 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.r = newPcgRand() + m.mutate([]any{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)) + m := newMutator() + + types := []any{ + []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.r = newPcgRand() + m.mutate([]any{t}, workerSharedMemSize) + } + }) + } +} + +func TestStringImmutability(t *testing.T) { + v := []any{"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/internal/fuzz/mutators_byteslice.go b/src/internal/fuzz/mutators_byteslice.go new file mode 100644 index 0000000000000000000000000000000000000000..d9dab1df9f4e859c114d28a3ae1867c035dfb392 --- /dev/null +++ b/src/internal/fuzz/mutators_byteslice.go @@ -0,0 +1,313 @@ +// Copyright 2021 The Go Authors. 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)) + } + // 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. + 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 0000000000000000000000000000000000000000..788696788187247c23e07793e084541cddd09875 --- /dev/null +++ b/src/internal/fuzz/mutators_byteslice_test.go @@ -0,0 +1,186 @@ +// Copyright 2021 The Go Authors. 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 { + values []int + counter int + b bool +} + +func (mr *mockRand) uint32() uint32 { + c := mr.values[mr.counter] + mr.counter++ + return uint32(c) +} + +func (mr *mockRand) intn(n int) int { + c := mr.values[mr.counter] + mr.counter++ + return c % n +} + +func (mr *mockRand) uint32n(n uint32) uint32 { + c := mr.values[mr.counter] + mr.counter++ + return uint32(c) % n +} + +func (mr *mockRand) exp2() int { + c := mr.values[mr.counter] + mr.counter++ + return c +} + +func (mr *mockRand) bool() bool { + b := mr.b + mr.b = !mr.b + 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 + mutator func(*mutator, []byte) []byte + randVals []int + 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, + randVals: []int{0, 2, 0, 2}, + input: append(make([]byte, 0, 9), []byte{1, 2, 3, 4}...), + expected: []byte{3, 2, 1, 4}, + }, + } { + t.Run(tc.name, func(t *testing.T) { + 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) + } + }) + } +} diff --git a/src/internal/fuzz/pcg.go b/src/internal/fuzz/pcg.go new file mode 100644 index 0000000000000000000000000000000000000000..c9ea0afcf8c3286141ce54735a796a3fd7d5dfb5 --- /dev/null +++ b/src/internal/fuzz/pcg.go @@ -0,0 +1,145 @@ +// 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" + "os" + "strconv" + "strings" + "sync/atomic" + "time" +) + +type mutatorRand interface { + uint32() uint32 + intn(int) int + 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 +// 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 +} + +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 + r.step() + r.state += now + r.step() + return r +} + +func (r *pcgRand) step() { + r.state *= multiplier + 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 + 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/queue.go b/src/internal/fuzz/queue.go new file mode 100644 index 0000000000000000000000000000000000000000..42a8379541f881d2f8141abaf54223965b85419e --- /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 []any + 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([]any, 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 any) { + 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() (any, 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() (any, 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 0000000000000000000000000000000000000000..3b179afb573ce7bd8a06ea88a4c55032ac0a226a --- /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/sys_posix.go b/src/internal/fuzz/sys_posix.go new file mode 100644 index 0000000000000000000000000000000000000000..89c86c1ebbf22f9dc04d34ba54ef4e251bad9f56 --- /dev/null +++ b/src/internal/fuzz/sys_posix.go @@ -0,0 +1,130 @@ +// 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 || 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 communication channels on the cmd that will +// run a worker process. +func setWorkerComm(cmd *exec.Cmd, comm workerComm) { + 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. +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 + } + 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 +// 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 +} + +// 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 new file mode 100644 index 0000000000000000000000000000000000000000..123a32583c54cc90003c5663441f9ffe744e2f54 --- /dev/null +++ b/src/internal/fuzz/sys_unimplemented.go @@ -0,0 +1,44 @@ +// 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. + +// If you update this constraint, also update cmd/internal/sys.FuzzSupported. +// +//go: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") +} + +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 new file mode 100644 index 0000000000000000000000000000000000000000..9c006b010efc2f24dfa2e0149b51a8be4d59e4c4 --- /dev/null +++ b/src/internal/fuzz/sys_windows.go @@ -0,0 +1,152 @@ +// 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" + "os" + "os/exec" + "reflect" + "syscall" + "unsafe" +) + +type sharedMemSys struct { + mapObj syscall.Handle +} + +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 + 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 communication channels on the cmd that will +// run a worker process. +func setWorkerComm(cmd *exec.Cmd, comm workerComm) { + mem := <-comm.memMu + 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) + cmd.Env = append(cmd.Env, fmt.Sprintf("GO_TEST_FUZZ_WORKER_HANDLES=%x,%x,%q", comm.fuzzIn.Fd(), comm.fuzzOut.Fd(), memName)) + cmd.SysProcAttr = &syscall.SysProcAttr{AdditionalInheritedHandles: []syscall.Handle{syscall.Handle(comm.fuzzIn.Fd()), syscall.Handle(comm.fuzzOut.Fd())}} +} + +// getWorkerComm returns communication channels in the worker process. +func getWorkerComm() (comm workerComm, err error) { + v := os.Getenv("GO_TEST_FUZZ_WORKER_HANDLES") + if v == "" { + return workerComm{}, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES not set") + } + 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(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{}, fmt.Errorf("worker checking temp file size: %w", 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(tmpFile, size, removeOnClose) + if err != nil { + return workerComm{}, err + } + memMu := make(chan *sharedMem, 1) + memMu <- mem + + return workerComm{fuzzIn: fuzzIn, fuzzOut: fuzzOut, memMu: memMu}, nil +} + +func isInterruptError(err error) bool { + // 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 +} + +// 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/trace.go b/src/internal/fuzz/trace.go new file mode 100644 index 0000000000000000000000000000000000000000..cab0838fab4ea080de44c9d39b5a9ec7a5414468 --- /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. + +//go: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) {} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go new file mode 100644 index 0000000000000000000000000000000000000000..c2d553240c8383ee52b12ebf9c5d0299b77f6e38 --- /dev/null +++ b/src/internal/fuzz/worker.go @@ -0,0 +1,1173 @@ +// 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 ( + "bytes" + "context" + "crypto/sha256" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "reflect" + "runtime" + "sync" + "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 + + // 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 + + // 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 +// 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 + args []string // arguments for test executable + env []string // environment for test executable + + coordinator *coordinator + + 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. + interrupted bool // true after stop interrupts a running worker. + 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 + if mem == nil { + return nil + } + close(w.memMu) + return mem.Close() +} + +// coordinate runs the test binary to perform fuzzing. +// +// 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 { + // 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. + err := w.stop() + if err != nil && !w.interrupted && !isInterruptError(err) { + return err + } + return ctx.Err() + + case <-w.termC: + // Worker process terminated unexpectedly while waiting for input. + err := w.stop() + if w.interrupted { + panic("worker interrupted after unexpected termination") + } + 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 := 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) + } + // Worker exited non-zero or was terminated by a non-interrupt + // signal (for example, SIGSEGV) while fuzzing. + return fmt.Errorf("fuzzing process hung or terminated unexpectedly: %w", err) + // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. + + case input := <-w.coordinator.inputC: + // Received input from coordinator. + args := fuzzArgs{ + Limit: input.limit, + Timeout: input.timeout, + Warmup: input.warmup, + CoverageData: input.coverageData, + } + entry, resp, isInternalError, err := w.client.fuzz(ctx, input.entry, args) + canMinimize := true + 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 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) + } + 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. + resp.Err = fmt.Sprintf("fuzzing process hung or terminated unexpectedly: %v", w.waitErr) + canMinimize = false + } + result := fuzzResult{ + limit: input.limit, + count: resp.Count, + totalDuration: resp.TotalDuration, + entryDuration: resp.InterestingDuration, + entry: entry, + crasherMsg: resp.Err, + coverageData: resp.CoverageData, + canMinimize: canMinimize, + } + w.coordinator.resultC <- result + + case input := <-w.coordinator.minimizeC: + // Received input to minimize from coordinator. + result, err := w.minimize(ctx, input) + 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: double-check this is handled correctly when + // implementing -keepfuzzing. + result = fuzzResult{ + entry: input.entry, + crasherMsg: input.crasherMsg, + canMinimize: false, + limit: input.limit, + } + if result.crasherMsg == "" { + result.crasherMsg = err.Error() + } + } + w.coordinator.resultC <- result + } + } +} + +// minimize tells a worker process to attempt to find a smaller value that +// 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() + ctx, cancel = context.WithTimeout(ctx, w.coordinator.opts.MinimizeTimeout) + defer cancel() + } + + args := minimizeArgs{ + Limit: input.limit, + Timeout: input.timeout, + KeepCoverage: input.keepCoverage, + } + entry, resp, err := w.client.minimize(ctx, input.entry, args) + if err != nil { + // Error communicating with worker. + w.stop() + if ctx.Err() != nil || w.interrupted || isInterruptError(w.waitErr) { + // 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 fuzzResult{ + entry: input.entry, + crasherMsg: input.crasherMsg, + coverageData: input.keepCoverage, + canMinimize: false, + limit: input.limit, + }, nil + } + 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 == "" { + return fuzzResult{}, fmt.Errorf("attempted to minimize a crash but could not reproduce") + } + + return fuzzResult{ + entry: entry, + crasherMsg: resp.Err, + coverageData: resp.CoverageData, + canMinimize: false, + limit: input.limit, + count: resp.Count, + totalDuration: resp.Duration, + }, nil +} + +func (w *worker) isRunning() bool { + return w.cmd != nil +} + +// 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() + } + 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. +// +// 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.isRunning() { + panic("worker already started") + } + w.waitErr = nil + w.interrupted = false + w.termC = nil + + 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. + + // 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, workerComm{fuzzIn: fuzzInR, fuzzOut: fuzzOutW, memMu: w.memMu}) + + // 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{}) + comm := workerComm{fuzzIn: fuzzInW, fuzzOut: fuzzOutR, memMu: w.memMu} + m := newMutator() + w.client = newWorkerClient(comm, m) + + 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 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. + if w.client == nil { + // stop already called. + return w.waitErr + } + // Possible unexpected termination. + 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. + w.interrupted = true + 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(w.coordinator.opts.Log, "waiting for fuzzing process 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(ctx context.Context, fn func(CorpusEntry) error) error { + comm, err := getWorkerComm() + if err != nil { + return err + } + srv := &workerServer{ + workerComm: comm, + 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) +} + +// 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 { + Ping *pingArgs + Fuzz *fuzzArgs + Minimize *minimizeArgs +} + +// minimizeArgs contains arguments to workerServer.minimize. The value to +// minimize is already in shared memory. +type minimizeArgs struct { + // 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 + + // 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 + + // Index is the index of the fuzz target parameter to be minimized. + Index int +} + +// minimizeResponse contains results from workerServer.minimize. +type minimizeResponse struct { + // 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 + + // 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 + + // Count is the number of values tested. + Count int64 +} + +// fuzzArgs contains arguments to workerServer.fuzz. The value to fuzz is +// passed in shared memory. +type fuzzArgs struct { + // Timeout is the time to spend fuzzing, not including starting or + // cleaning up. + Timeout time.Duration + + // Limit is the maximum number of values to test, without spending more time + // than Duration. 0 indicates no limit. + Limit int64 + + // 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. + CoverageData []byte +} + +// fuzzResponse contains results from workerServer.fuzz. +type fuzzResponse struct { + // Duration is the time spent fuzzing, not including starting or cleaning up. + TotalDuration time.Duration + InterestingDuration time.Duration + + // Count is the number of values tested. + Count int64 + + // 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, 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. +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 +// 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 + memMu chan *sharedMem // mutex guarding shared memory +} + +// 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 + m *mutator + + // coverageMask is the local coverage data for the worker. It is + // periodically updated to reflect the data in the coordinator when new + // coverage is found. + coverageMask []byte + + // 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, +// 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 that occurred when communicating over pipes. serve +// does not return errors from method calls; those are passed through serialized +// responses. +func (ws *workerServer) serve(ctx context.Context) error { + 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 + } + } + + var resp any + 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") + } + + if err := enc.Encode(resp); err != nil { + return err + } + } +} + +// 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. +// +// 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 { + if ws.coverageMask != nil && 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 + } + start := time.Now() + defer func() { resp.TotalDuration = time.Since(start) }() + + if args.Timeout != 0 { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, args.Timeout) + 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 + }() + if args.Limit > 0 && 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 + } + + originalVals, err := unmarshalCorpusFile(mem.valueCopy()) + if err != nil { + resp.InternalErr = err.Error() + return resp + } + vals := make([]any, len(originalVals)) + copy(vals, originalVals) + + 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++ + var err error + dur, err = ws.fuzzFn(entry) + if err != nil { + 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.Warmup { + dur, _, errMsg := fuzzOnce(CorpusEntry{Values: vals}) + if errMsg != "" { + resp.Err = errMsg + return resp + } + resp.InterestingDuration = dur + if coverageEnabled { + resp.CoverageData = coverageSnapshot + } + return resp + } + + for { + 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 != "" { + resp.Err = errMsg + return resp + } + if cov != nil { + resp.CoverageData = cov + resp.InterestingDuration = dur + return resp + } + if shouldStop() { + return resp + } + } + } +} + +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()) + if err != nil { + panic(err) + } + if args.Timeout != 0 { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, args.Timeout) + defer cancel() + } + + // Minimize the values in vals, then write to shared memory. We only write + // to shared memory after completing minimization. + 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() + } 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, 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 []any, 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 || + (args.Limit > 0 && *count >= args.Limit) + } + 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++ + _, 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 + } + mem.header().rawInMem = true + + // 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 []byte) bool { + prev := vals[args.Index] + switch prev.(type) { + case []byte: + 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 { + retErr = err + 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 + } + vals[args.Index] = prev + return false + } + 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 +} + +func writeToMem(vals []any, mem *sharedMem) { + b := marshalCorpusFile(vals...) + 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 { + return pingResponse{} +} + +// 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 + 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 +} + +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 +// 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 { + 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() +} + +// 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") + +// 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, retErr error) { + wc.mu.Lock() + defer wc.mu.Unlock() + + mem, ok := <-wc.memMu + if !ok { + return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed + } + mem.header().count = 0 + inp, err := CorpusEntryData(entryIn) + if err != nil { + return CorpusEntry{}, minimizeResponse{}, err + } + mem.setValue(inp) + defer func() { wc.memMu <- mem }() + 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 + } + + 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. +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{}, true, errSharedMemClosed + } + mem.header().count = 0 + inp, err := CorpusEntryData(entryIn) + if err != nil { + 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{}, true, errSharedMemClosed + } + defer func() { wc.memMu <- mem }() + resp.Count = mem.header().count + + if !bytes.Equal(inp, mem.valueRef()) { + 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 { + 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 { + // Only mutate the valuesOut if fuzzing actually occurred. + numMutations := ((resp.Count - 1) % chainedMutations) + 1 + for i := int64(0); i < numMutations; i++ { + wc.m.mutate(valuesOut, cap(mem.valueRef())) + } + } + dataOut := marshalCorpusFile(valuesOut...) + + h := sha256.Sum256(dataOut) + name := fmt.Sprintf("%x", h[:4]) + entryOut = CorpusEntry{ + Parent: entryIn.Path, + Path: name, + 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, false, callErr +} + +// 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.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 any) (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) +} + +// 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) (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) + }() + + select { + case <-cr.ctx.Done(): + return 0, cr.ctx.Err() + case <-done: + return n, err + } +} diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go new file mode 100644 index 0000000000000000000000000000000000000000..d0b21da7838643a58b93af9d7a1c73d631119ec5 --- /dev/null +++ b/src/internal/fuzz/worker_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 fuzz + +import ( + "context" + "errors" + "flag" + "fmt" + "internal/race" + "io" + "os" + "os/signal" + "reflect" + "strconv" + "testing" + "time" +) + +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) { + 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)) + + ws := &workerServer{ + fuzzFn: func(_ CorpusEntry) (time.Duration, error) { return time.Second, 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) + } + defer func() { + if err := mem.Close(); err != nil { + b.Error(err) + } + }() + + initialVal := []any{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) + mem.header().count = 0 + + 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) { + if race.Enabled { + b.Skip("TODO(48504): fix and re-enable") + } + 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) { + if race.Enabled { + b.Skip("TODO(48504): fix and re-enable") + } + b.SetParallelism(1) + w := newWorkerForTest(b) + entry := CorpusEntry{Values: []any{[]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(), entry, 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) + } +} + +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 := []any{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{}) + } + }) + } +} diff --git a/src/internal/goarch/gengoarch.go b/src/internal/goarch/gengoarch.go new file mode 100644 index 0000000000000000000000000000000000000000..3c706e04ad0cc5a56bebe06408115c27e20c321e --- /dev/null +++ b/src/internal/goarch/gengoarch.go @@ -0,0 +1,57 @@ +// 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 + +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) // 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 Is%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 74% rename from src/runtime/internal/sys/arch.go rename to src/internal/goarch/goarch.go index 3c99a2f7da0831048e2aa5ae24cb8914e5d83785..921f5a208fc6330adc2c71bca38ab6789b612d5a 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 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,14 +30,11 @@ 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 // 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/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 1ebce3435e4be374308d59601ab52d4d572d5eb1..c6214217fcf339a5eb279c0bf80e15441acfd9b1 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 7f003d0f1d503431452dca3003f47c6c1d080621..911e3e72421720f95412579c50917d54e781bc7b 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 ef2048bb71a5dd837c2c6e03ccb312ade0baf48f..a6591713c8204006a3d9cff45f56f345092b3b01 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 b9f2f7b1fe226abd96e5907e34b04be368fa6ea3..85d0b4763913212bb2be2e81d0c6880bfa0b88d4 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 4cb0eebea7bb5c0fbaafe59ff2b9bfe8a7448e2a..59f3995e2a54fda0d1df6bfdbc883840fbfef0d6 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_mips64.go b/src/internal/goarch/goarch_mips64.go similarity index 95% rename from src/runtime/internal/sys/arch_mips64.go rename to src/internal/goarch/goarch_mips64.go index 57636ac4a4e0ebe933066ca9a6fb1722e12436a5..9e4f82797d410ae88a5bd6a7c8e6260c170b8da5 100644 --- a/src/runtime/internal/sys/arch_mips64.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_mips64le.go b/src/internal/goarch/goarch_mips64le.go similarity index 95% rename from src/runtime/internal/sys/arch_mips64le.go rename to src/internal/goarch/goarch_mips64le.go index 57636ac4a4e0ebe933066ca9a6fb1722e12436a5..9e4f82797d410ae88a5bd6a7c8e6260c170b8da5 100644 --- a/src/runtime/internal/sys/arch_mips64le.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 4240f5ce47bb7f8abfaffc75f2f3c5ffed838aa1..3e6642bb86399ba7b01378d53111460a4a30ef21 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 1869213ce241ee5f6da403b2714652756dc956dc..60cc846e6a380aae4cf1574739661e8a06efb392 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 1869213ce241ee5f6da403b2714652756dc956dc..60cc846e6a380aae4cf1574739661e8a06efb392 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 360d236e32072ac431f19ed75095b406cb6b4beb..3b6da1e02fe9b8c04dc10d7a16e4f0afd472b859 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 e33e0b7f2b890b416ac5e70c2cbdcff6a5ad2eb5..20c5705581e79ce5c897c3b6c6e442a3c92c8a02 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 ee919ff9e634996eeb54bd40e7a9c73e0509a5ec..98618d6980edd7e0ae4329c7f0575e62d64023e8 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/internal/goarch/zgoarch_386.go b/src/internal/goarch/zgoarch_386.go new file mode 100644 index 0000000000000000000000000000000000000000..4a9b0e67c454a7212c804269400f76a509aa3f2e --- /dev/null +++ b/src/internal/goarch/zgoarch_386.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build 386 + +package goarch + +const GOARCH = `386` + +const Is386 = 1 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..7926392b77510ceade8475edd1978559e248679e --- /dev/null +++ b/src/internal/goarch/zgoarch_amd64.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build amd64 + +package goarch + +const GOARCH = `amd64` + +const Is386 = 0 +const IsAmd64 = 1 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..6c03b8b060c1b4b7728e297bd46bf44a20737a52 --- /dev/null +++ b/src/internal/goarch/zgoarch_arm.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build arm + +package goarch + +const GOARCH = `arm` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 1 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..ad342d79c96bb2feb1038cb1ff6588bf4bc48b81 --- /dev/null +++ b/src/internal/goarch/zgoarch_arm64.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build arm64 + +package goarch + +const GOARCH = `arm64` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 1 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..0f260030908ecad894c655cdac66113d593ff415 --- /dev/null +++ b/src/internal/goarch/zgoarch_arm64be.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build arm64be + +package goarch + +const GOARCH = `arm64be` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 1 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..6092fee7516e3805f21eda7f2ad37cb093822203 --- /dev/null +++ b/src/internal/goarch/zgoarch_armbe.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build armbe + +package goarch + +const GOARCH = `armbe` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 1 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_loong64.go b/src/internal/goarch/zgoarch_loong64.go new file mode 100644 index 0000000000000000000000000000000000000000..21c67e1176838ece2818fb177b15970432361a95 --- /dev/null +++ b/src/internal/goarch/zgoarch_loong64.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build loong64 + +package goarch + +const GOARCH = `loong64` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 1 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..0db19746556adf77af6c6b938a7622c18217a8ce --- /dev/null +++ b/src/internal/goarch/zgoarch_mips.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build mips + +package goarch + +const GOARCH = `mips` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 1 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..738806f0aef0afa8eee1011c0065a46fcfc55fef --- /dev/null +++ b/src/internal/goarch/zgoarch_mips64.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build mips64 + +package goarch + +const GOARCH = `mips64` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 1 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..8de5beb88197290bc0afd54e19687cfd608523dc --- /dev/null +++ b/src/internal/goarch/zgoarch_mips64le.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build mips64le + +package goarch + +const GOARCH = `mips64le` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..ea461bed70c26ceee2d68d65c57f23239ef80b24 --- /dev/null +++ b/src/internal/goarch/zgoarch_mips64p32.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build mips64p32 + +package goarch + +const GOARCH = `mips64p32` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..15473ce6c7a047fa0a4768cd9c2784c35f27e48f --- /dev/null +++ b/src/internal/goarch/zgoarch_mips64p32le.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build mips64p32le + +package goarch + +const GOARCH = `mips64p32le` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..4955142e876539c6b8d328a429347750c4c055f7 --- /dev/null +++ b/src/internal/goarch/zgoarch_mipsle.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build mipsle + +package goarch + +const GOARCH = `mipsle` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 1 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..ec01763b3c3ca5cdd7c891e0ee148b5341760b0f --- /dev/null +++ b/src/internal/goarch/zgoarch_ppc.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build ppc + +package goarch + +const GOARCH = `ppc` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..39be3925c8e919ac6f379dd44136b2a367261858 --- /dev/null +++ b/src/internal/goarch/zgoarch_ppc64.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build ppc64 + +package goarch + +const GOARCH = `ppc64` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..5f959e0e0245efbf5c0c6f1dbe58ac31dcbb04f8 --- /dev/null +++ b/src/internal/goarch/zgoarch_ppc64le.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build ppc64le + +package goarch + +const GOARCH = `ppc64le` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..8d81a14dd9beace1427502533023265c69675eaa --- /dev/null +++ b/src/internal/goarch/zgoarch_riscv.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build riscv + +package goarch + +const GOARCH = `riscv` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..1df989c2a696ed0eedd8b4ddaa31e441bf55f90b --- /dev/null +++ b/src/internal/goarch/zgoarch_riscv64.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build riscv64 + +package goarch + +const GOARCH = `riscv64` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..56815b9f435567794cdc2dc5999772497719f944 --- /dev/null +++ b/src/internal/goarch/zgoarch_s390.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build s390 + +package goarch + +const GOARCH = `s390` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..e61e9bd5938a8bb5b2c30ae761b1081611c09bc4 --- /dev/null +++ b/src/internal/goarch/zgoarch_s390x.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build s390x + +package goarch + +const GOARCH = `s390x` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..ee5b746566ddd2d4fc7b717167933a5e19d5206f --- /dev/null +++ b/src/internal/goarch/zgoarch_sparc.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build sparc + +package goarch + +const GOARCH = `sparc` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..519aaa10c13bb591f2a0e681e2856b3e0e7a54a4 --- /dev/null +++ b/src/internal/goarch/zgoarch_sparc64.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build sparc64 + +package goarch + +const GOARCH = `sparc64` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +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 new file mode 100644 index 0000000000000000000000000000000000000000..25567a1b6481f6dbf2c864c527db3f53a5c83a03 --- /dev/null +++ b/src/internal/goarch/zgoarch_wasm.go @@ -0,0 +1,32 @@ +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. + +//go:build wasm + +package goarch + +const GOARCH = `wasm` + +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsLoong64 = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +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 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 1 diff --git a/src/internal/godebug/godebug.go b/src/internal/godebug/godebug.go new file mode 100644 index 0000000000000000000000000000000000000000..ac434e5fd83649f987326c1d55257d5712553786 --- /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 0000000000000000000000000000000000000000..41b9117b73bcaf8b686fdde5c7ede0ded7ea1fc3 --- /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/goexperiment/exp_heapminimum512kib_off.go b/src/internal/goexperiment/exp_heapminimum512kib_off.go new file mode 100644 index 0000000000000000000000000000000000000000..09da431b40711348ad6a1a2c90a89159eeec5690 --- /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 0000000000000000000000000000000000000000..bab684b5e680a5d601dde2cadc47d7ce85219cc9 --- /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/exp_pacerredesign_off.go b/src/internal/goexperiment/exp_pacerredesign_off.go new file mode 100644 index 0000000000000000000000000000000000000000..62e1831437bd173f7f2f3a43a59bb45215166ad7 --- /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 0000000000000000000000000000000000000000..b22b031009a2cd7857925726cd9328f79949b996 --- /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/exp_regabi_off.go b/src/internal/goexperiment/exp_regabi_off.go deleted file mode 100644 index 5d8823843d94844085e7aae6a5c2ba548637bee0..0000000000000000000000000000000000000000 --- 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 c08d58e9b2aa25099caa3021573818ab0bcd9cb4..0000000000000000000000000000000000000000 --- 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 diff --git a/src/internal/goexperiment/exp_regabidefer_off.go b/src/internal/goexperiment/exp_regabidefer_off.go deleted file mode 100644 index b47c0c2cf55129fa74af650b7586f2c355a9db6a..0000000000000000000000000000000000000000 --- 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 bbf2f6c69be4d6be7341a96ad5d69031b2236c3f..0000000000000000000000000000000000000000 --- 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/exp_regabig_off.go b/src/internal/goexperiment/exp_regabig_off.go deleted file mode 100644 index 1b37d4518680210b2bea6cea756cd76f185787c9..0000000000000000000000000000000000000000 --- 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 7e5b162e0b2ae2aa8e0f3ddd230bcea3db67ddc9..0000000000000000000000000000000000000000 --- 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/exp_unified_off.go b/src/internal/goexperiment/exp_unified_off.go new file mode 100644 index 0000000000000000000000000000000000000000..4c16fd85624c60f7fac164071839f98c158b6af1 --- /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 0000000000000000000000000000000000000000..2b17ba3e79b4bbd3422bcb18653bfae83c7b3602 --- /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 cd4c178818495f165b20ec2caebdecf8cbe6cc13..6d935edc2b223564805b8e8081978391cc42c45d 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" @@ -68,26 +72,28 @@ 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 // 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. // - // 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 + + // 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 + + // 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/internal/sys/gengoos.go b/src/internal/goos/gengoos.go similarity index 53% rename from src/runtime/internal/sys/gengoos.go rename to src/internal/goos/gengoos.go index ffe962f71df61c89cba3261d7e017c5de4e432b2..1b62503fd007427fcfcc359edb4ebf900ce87fa2 100644 --- a/src/runtime/internal/sys/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 @@ -16,17 +15,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 +31,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 { @@ -62,42 +51,18 @@ 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 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 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 { 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 0000000000000000000000000000000000000000..ebb521fec6876c6c7d01af5bcde8dae37d7fe195 --- /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 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 new file mode 100644 index 0000000000000000000000000000000000000000..ff861550c4851ab7dbb33b9059ec14e88b744adf --- /dev/null +++ b/src/internal/goos/zgoos_aix.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build aix + +package goos + +const GOOS = `aix` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..e8aaa1242842d15db905685340b820e047a6a149 --- /dev/null +++ b/src/internal/goos/zgoos_android.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build android + +package goos + +const GOOS = `android` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..decdd496425c7fb3c8424547d2f765fbc46c89e2 --- /dev/null +++ b/src/internal/goos/zgoos_darwin.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build !ios && darwin + +package goos + +const GOOS = `darwin` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..2224baa2301831deaf4ac21f3fb4e9403be693c5 --- /dev/null +++ b/src/internal/goos/zgoos_dragonfly.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build dragonfly + +package goos + +const GOOS = `dragonfly` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..3ee5bf998e21c3303edb6b789cf8908205010a5c --- /dev/null +++ b/src/internal/goos/zgoos_freebsd.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build freebsd + +package goos + +const GOOS = `freebsd` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..8a3d34304d8f7f8f4d848ceb0f0780f68a099bbf --- /dev/null +++ b/src/internal/goos/zgoos_hurd.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build hurd + +package goos + +const GOOS = `hurd` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..fc1b9a9e22fcc7eab192c68f0a6a38ec7d431c65 --- /dev/null +++ b/src/internal/goos/zgoos_illumos.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build illumos + +package goos + +const GOOS = `illumos` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..746e769ef766a0cdb9864a2b3b05b21837136021 --- /dev/null +++ b/src/internal/goos/zgoos_ios.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build ios + +package goos + +const GOOS = `ios` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..6cf2a5d9e27133923e00735fea0cee949fc0e2d7 --- /dev/null +++ b/src/internal/goos/zgoos_js.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build js + +package goos + +const GOOS = `js` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..cb9d6e8afaa90556587b7bb9fd1dd0acb85b9b76 --- /dev/null +++ b/src/internal/goos/zgoos_linux.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build !android && linux + +package goos + +const GOOS = `linux` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..8285928d3504716df16cdc89b1aa05d65a9f1dc8 --- /dev/null +++ b/src/internal/goos/zgoos_netbsd.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build netbsd + +package goos + +const GOOS = `netbsd` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..3f739a4a2f728c071ba30786423a6bafcbed08fe --- /dev/null +++ b/src/internal/goos/zgoos_openbsd.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build openbsd + +package goos + +const GOOS = `openbsd` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..d4c1c651f7bf881b28b65e63d461fe4caee6e208 --- /dev/null +++ b/src/internal/goos/zgoos_plan9.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build plan9 + +package goos + +const GOOS = `plan9` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..69e3285ab620465adadcc4c8c341b64ef40f199e --- /dev/null +++ b/src/internal/goos/zgoos_solaris.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build !illumos && solaris + +package goos + +const GOOS = `solaris` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..16158be78b97e8f85e97754aff88fc02ab27f9d9 --- /dev/null +++ b/src/internal/goos/zgoos_windows.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build windows + +package goos + +const GOOS = `windows` + +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 new file mode 100644 index 0000000000000000000000000000000000000000..fb6165c7a12ec8f4269c0e672933448a99ad9046 --- /dev/null +++ b/src/internal/goos/zgoos_zos.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build zos + +package goos + +const GOOS = `zos` + +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/internal/goroot/gc.go b/src/internal/goroot/gc.go index 2338b78f3aa987a3e76c871c2eb3ca029d277f95..8c66cd13a81c2540cc9bae1a2a399d1eba6699ea 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 b1041da11d8b7c048b15c0758b6b334667bf950f..62841222a7efdbf9d24d8ed14801c162109760df 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/goversion/goversion.go b/src/internal/goversion/goversion.go index 4cc15688c0b70505e47ddd4ffce5c20a85852442..8fcea100dc696ab6044e871730be6f4a4054237a 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 diff --git a/src/internal/intern/intern.go b/src/internal/intern/intern.go new file mode 100644 index 0000000000000000000000000000000000000000..75641106abdf94cae46c079d16954c393fed5cd7 --- /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 any + // 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() 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 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 any) 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 any) *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 0000000000000000000000000000000000000000..d1e409ef95718da4b04cf3041e6f32ff3cc98e5d --- /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/internal/lazytemplate/lazytemplate.go b/src/internal/lazytemplate/lazytemplate.go index c83eaeaf3ec6eb526f148477937683333d1f7934..8eeed5a527ac6a8aeb2fb318835630d34fd6db37 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 de3254df589f0e31844b147324e418d900a97ebd..94f38a71eeb70aeeee153dd8a17b4c08fc92f0de 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/errno_unix.go b/src/internal/poll/errno_unix.go index 55c548824f8bdd428ccb32f2cc69edb4971b43a7..c17751973225211748bf406626268f0f08ec8126 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 c55f5f0df5057da6c96a0a68f3865217bfcaaae0..3679aa8c4c795b69df890dee58df38696af0b2b3 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 bcc25dd666a7b292b16ecbf1e27e3b4aa9a98cf7..48e095254d38639c3f5c047cce701e901acb2643 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 f59c1f6dfaba5341410d34518e263d137c7334ab..3fcafac0020e8491efe34575440d823c461fb826 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 7bf0ddc792f642c163581289bbb16f20ffffb49a..0f42ef61a572be25bb0788c027a68122ed4f7458 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 cc609e48ad7af9f578a094bb6dc47a6da26e74bb..f503d7a336ffa02307c38cddc50801e746f21178 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 8db5b6650492eecc4aaad7aa891568662827cd85..accff5e0438955757eb0ba6a94651123fdfadda0 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 651a5ecd8b2d4f01e9774bedd92d16ea01314eb7..6f17019e73d8f2ab56dfac616d42e06237a6c55f 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 760e24802e3fbd625515d7fc7d556f960c336375..84bfcae633d9290448037512375e8b69b377199b 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 b072af00ea569e528dacc5de244bccc20fc54ded..4a4dddfd2743cbebc3dec55ca4cd0ad1aa4585ef 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 487f3285ee9895438b16fdc84539de4fac7f0976..dc1e29c6b7861caa5a920da29a969d6283f0d25c 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 1dcf51d41946aa972671f10cbdec8c8847b45d46..0b7ef7a577fe9c7a2fc8dbb45ad3226268ee4a8b 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 3b17cd22b03b8f85d0f9b6eb250d3379d59b9cfa..85971a16cd3e6325b8c6f3f49e308c0b012432ac 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -3,11 +3,11 @@ // 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 import ( + "internal/syscall/unix" "io" "sync/atomic" "syscall" @@ -230,6 +230,60 @@ func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) { } } +// 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 + } + defer fd.readUnlock() + if err := fd.pd.prepareRead(fd.isFile); err != nil { + return 0, err + } + for { + n, err := unix.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 + } +} + +// 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 + } + defer fd.readUnlock() + if err := fd.pd.prepareRead(fd.isFile); err != nil { + return 0, err + } + for { + n, err := unix.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 { @@ -257,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 { @@ -327,6 +435,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 := unix.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 := unix.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 { @@ -379,6 +539,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 4a5169527c42b0592d13e6c75df3fc9773647347..1ca281b2a4a0613825705b5386108480595d3e22 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -593,6 +593,64 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { return n, sa, nil } +// 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 + } + 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 + } + rawToSockaddrInet4(o.rsa, sa4) + return n, err +} + +// 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 + } + 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 + } + rawToSockaddrInet6(o.rsa, sa6) + return n, err +} + // Write implements io.Writer. func (fd *FD) Write(buf []byte) (int, error) { if err := fd.writeLock(); err != nil { @@ -791,6 +849,80 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { return ntotal, nil } +// 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 + } + defer fd.writeUnlock() + + if len(buf) == 0 { + // handle zero-byte payload + o := &fd.wop + o.InitBuf(buf) + n, err := execIO(o, func(o *operation) error { + return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, 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) + n, err := execIO(o, func(o *operation) error { + return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil) + }) + ntotal += int(n) + if err != nil { + return ntotal, err + } + buf = buf[n:] + } + return ntotal, nil +} + +// 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) + n, err := execIO(o, func(o *operation) error { + return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, 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) + n, err := execIO(o, func(o *operation) error { + return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, 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 // called when the descriptor is first created. This is here rather // than in the net package so that it can use fd.wop. @@ -984,31 +1116,54 @@ func (fd *FD) RawWrite(f func(uintptr) bool) error { return syscall.EWINDOWS } -func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { +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 int32(unsafe.Sizeof(*raw)) +} + +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 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(rsa *syscall.RawSockaddrAny, sa syscall.Sockaddr) (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) - for i := 0; i < len(sa.Addr); i++ { - raw.Addr[i] = sa.Addr[i] - } - return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil + sz := sockaddrInet4ToRaw(rsa, sa) + return 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 - for i := 0; i < len(sa.Addr); i++ { - raw.Addr[i] = sa.Addr[i] - } - return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil + sz := sockaddrInet6ToRaw(rsa, sa) + return sz, nil default: - return nil, 0, syscall.EWINDOWS + return 0, syscall.EWINDOWS } } @@ -1025,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) @@ -1040,6 +1197,64 @@ 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) + 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) + 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) + 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) + 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 { @@ -1054,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 { @@ -1066,3 +1284,53 @@ 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) + 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) + }) + 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) + 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) + }) + return n, int(o.msg.Control.Len), err +} diff --git a/src/internal/poll/fd_writev_darwin.go b/src/internal/poll/fd_writev_darwin.go index 805fa2ccd9ae79e706e15569aca5018c86d89385..8137510c8b44719e7e283dd4c90350d55bab88a6 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 a0b11ed5ae972c5337660291b52bf52c04177cdb..79190c2f6398a69da014eddb3aa3cb177a609ed5 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 87f284a56a1b21d72c24b361287bb2c84c6313c7..aa96d104c89bf1f3125e7c984f10e611ca9b01b5 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 d519f602c1e9850d23898c7924b881bb6793e660..c941cb52357938bb7aeac8d263dc307ea5b84a32 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 c88d65cdc83de5ff8567065a08a24084d637d0bf..c9aa4b4ca23a484d23ae7740929fb0dab6e1c8b4 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 f4058b298f35c5ae73ba5c3ff56fa920abcda1bc..00a65d7995b9b3954c92b1bfb5d86a643f82b34c 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 6fd5d86630b6aa45a2c6ebfb4e4d34984c8fa583..c1500840ac243e09290fff84e770e9c3a58939af 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 3ba30a2154cd545c8616138ba6998a52359f00bb..89315a8c67352e988a5b5b6197f2cd1cafe3dacd 100644 --- a/src/internal/poll/sendfile_bsd.go +++ b/src/internal/poll/sendfile_bsd.go @@ -2,8 +2,7 @@ // 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 package poll diff --git a/src/internal/poll/sock_cloexec.go b/src/internal/poll/sock_cloexec.go index b3038290b9216853c227fad6c0acc93079d81fad..d849fda0b06f87584c16b82d3333025f3e1f1d57 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 4f2e2fb455dc9bc23842b6368243b3b6a88aee36..2d354700c5d3a6862ac563dfba0a03ae5bdbee55 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 4fb9600deedff1b9d8161b0e32551e4bdc2255e2..54be1cc4b6bed0ee244e4893dac259ceb541f4b5 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 d86c4c1f81ad4c4ca7528b80dd1e56527af4db31..7fc9aeefb3b1d00a9584910a60cff01037e3db41 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/splice_linux.go b/src/internal/poll/splice_linux.go index 8062d98fae945ccf214dc095ed8165e83dd556ad..43eec04a71485b85dabc81bf7e68f413b29a9958 100644 --- a/src/internal/poll/splice_linux.go +++ b/src/internal/poll/splice_linux.go @@ -154,18 +154,26 @@ 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 - unsafe.Sizeof(splicePipeFields{})%24]byte +} + // splicePipePool caches pipes to avoid high-frequency construction and destruction of pipe buffers. // The garbage collector will free all pipes in the sync.Pool periodically, thus we need to set up // 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() @@ -218,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) diff --git a/src/internal/poll/splice_linux_test.go b/src/internal/poll/splice_linux_test.go index 280468c7e748d85ec957e7a36eac0a8149440f0d..29bcaab4140f7c5999c6597e464a51d146975e0a 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,12 +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 any) bool { + leakedFDs = append(leakedFDs, k.(int)) + return true + }) + if len(leakedFDs) == 0 { break } + select { case <-expiredTime.C: - t.Fatal("at least one pipe is still open") + t.Logf("all descriptors: %v", allFDs) + t.Fatalf("leaked descriptors: %v", leakedFDs) default: } } diff --git a/src/internal/poll/strconv.go b/src/internal/poll/strconv.go index c98332d3dac63713b4093e31dbcf477a9c3b7266..2b052fa1747f3a4eb0a5cec5f4d7eadd5ec6721e 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 7e6d422d621cda8bf433e593d3e22f19a0f89d47..312ed24a44bc203645c0c05965719901c30514d9 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 824de7569e8a2cc96b7c430f52fceb17ab71ad21..cd600b63d7d61e8d97fa1a72328bd120d4cc6cf3 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/profile/legacy_profile.go b/src/internal/profile/legacy_profile.go index d69f8deee7cb6aa677fdd36cdd8d0412419ca400..377a43d5858f08e066e59947d979a4994bc4e2d0 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/internal/reflectlite/all_test.go b/src/internal/reflectlite/all_test.go index e15f364fcd33f3086edb8bfd78cfad862cf2c84a..ea750831efbe5828f166989b7e77d60e3b83b812 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 354ea9dbd07325ec7fb9c68c3cb852e94d8ca487..adae229e92c3caf0fc26b10104966468dc40c401 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 a610499d084274f90f19d0114d3d41128ce9408a..ca7ea9b0bc39d9732c8c4051a90cf1eb15eb20c1 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 6330ab2d34668dd8f85719120befb61cd75c1984..fc402bb38a423cc8a0711a7001b7aa0609c486a2 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" ) @@ -13,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()}) @@ -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/tostring_test.go b/src/internal/reflectlite/tostring_test.go index a1e5dae09d8663dc5f32593ca45574beafc1d39e..966b0bd849920337c648c6a017251f70c3728255 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/internal/reflectlite/type.go b/src/internal/reflectlite/type.go index b1899b0191f3f9b77648945112d84b05ebc63d5a..8f649600d21d04b6683346df5a14bd8770f343c4 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. // @@ -705,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 0365eeeabf634f0ad2c1a88709b49bbc66ae70bb..966230f581701195ff42b8bd409b9cf4164840ba 100644 --- a/src/internal/reflectlite/value.go +++ b/src/internal/reflectlite/value.go @@ -5,13 +5,12 @@ package reflectlite import ( + "internal/goarch" "internal/unsafeheader" "runtime" "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, @@ -88,9 +87,9 @@ 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 != 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 { @@ -100,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 { @@ -137,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 @@ -221,17 +220,17 @@ 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() 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)) } @@ -240,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) @@ -258,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}) } @@ -268,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() @@ -289,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 // } @@ -392,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{} } @@ -434,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) } @@ -456,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 @@ -465,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 } @@ -473,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 b2d82e26c29c6b8890dd7e0590299179c4090486..07b3f40ec03d46465813d73c33272a4ed01b65e4 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 6404a1775a0de9dfbcb32e786db6ef91405750a7..c2310375f7d732e8e05f271e067691f84eab5bbb 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/execenv/execenv_default.go b/src/internal/syscall/execenv/execenv_default.go index 73289f1cd05a89201c8c0db3d0d62081db0c6d86..335647c63813cd87ee7ddbfce44eca25d70edd90 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 6c0654943e690613175113c4a97abe1292927a0e..a8aa1a644eeffa27151ca8839c5e9b6773026b8d 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 9b08864f7f580dae8697db57a9bdfc2221a7a0b2..447d48e198966bb24f47727a3a9def9b4ac896e7 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 4cc351ea278d88b9fe605c64a11bc8924db810a2..f48d3791e370c83f2218007416f6be607a34c2dd 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 050d401bc0ef6addcc53bb6477f73b0cc42c6172..445b0c38546ac089e976471771370679bfcf390d 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 e53a2d1b75fb996631cceaac9c1d46f4c2424778..73a3da5bff2112b7940caccbe1b939d4f98d96c5 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 4cb4a5976ba7371c72ea374bda4b6cbe1394b736..76edf675227f9b40611a2e67ae6542ec3f3eaf4b 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 46a4f6b030d46d929f7297f3097f9331bb0a77c5..7b39ee72bc494d9ac5c9bb2e1b56bd4c5bb2adc4 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 e1a410a454144627108c7e449430b671b2689930..7bab1f27b0c89695debed55061e21f38c686c0bf 100644 --- a/src/internal/syscall/unix/getentropy_darwin.go +++ b/src/internal/syscall/unix/getentropy_darwin.go @@ -2,6 +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 && !ios + package unix import ( diff --git a/src/internal/syscall/unix/getrandom.go b/src/internal/syscall/unix/getrandom.go index d2c58c0f6fa459ba03e0c2843a2be2f5a49225ec..a6659331e46d87c022ac76b84c3d31761556c6a1 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/ioctl_aix.go b/src/internal/syscall/unix/ioctl_aix.go index 19d56c36a13156563115d5bbdf248a08ccbf1627..d361533b5c4a43bdf3789f7711077d74278560bd 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/internal/syscall/unix/net.go b/src/internal/syscall/unix/net.go new file mode 100644 index 0000000000000000000000000000000000000000..85632e1c03c3fe82fef15788d312231add80d3d3 --- /dev/null +++ b/src/internal/syscall/unix/net.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. + +//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) + +//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) + +//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 new file mode 100644 index 0000000000000000000000000000000000000000..622fc8eb14aa03f31d4475575fff1c17f48eb20c --- /dev/null +++ b/src/internal/syscall/unix/net_js.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. + +//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 +} + +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 +} + +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/internal/syscall/unix/nonblocking.go b/src/internal/syscall/unix/nonblocking.go index a22986cb8a402bb8759b61214cab952ad6b69178..9e5f0fb4a2d57a7e2c9d78943fd604050726fd39 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 a5a5080d46153a9bed00ede4cfd324b177b11e4d..8ed40f3f9104adcd09159a2e73e949d763a5259c 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 d9565efcb6af46261bf36921483013564ffe29b9..75c6e92a6e23ef64b1e07a6945aea7fe27865d1f 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 b0aac895808deb568c4def6d39f99a1e6615f4e7..c6280f85e585e6f3dd6b14849a17f78569d119a1 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 a76025454cad46c8df043d534cce411ed11e9cf9..3c5394a96b1c1201c816ff242ab839dc9d8c3f1b 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 f353d4d73e48f606c6e04b6565ad8985941f55c6..bca526d2b905bf6c15d3bda2a51f4bd3b5bda243 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 4ed471532a2a415edb4bd26a1808557720d8f9a1..c86195e49698a5a636ee13872edc11fd4a4e79e9 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 b484ffef80b97b42c897517f5c7ef57c9817c71b..a4dcf2bc9d71f53e7ca423c70d4f3032734f0db0 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 f60949f662b58a7710acf27540740d56b7d8a20c..ee31be1302e5321f630c6d8406cd51b784f15735 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/syscall/windows/exec_windows_test.go b/src/internal/syscall/windows/exec_windows_test.go index 283d7cea94bfa0fdd622a301eacb56e2de232316..3311da5474164620b6fa65e00084f9c453df53c1 100644 --- a/src/internal/syscall/windows/exec_windows_test.go +++ b/src/internal/syscall/windows/exec_windows_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. -// +build windows +//go:build windows package windows_test diff --git a/src/internal/syscall/windows/mksyscall.go b/src/internal/syscall/windows/mksyscall.go index 599f07601bd4d5af2dedd8530b306776c7af850e..81f08c627e6496ac38a316947a56d8893a4e5053 100644 --- a/src/internal/syscall/windows/mksyscall.go +++ b/src/internal/syscall/windows/mksyscall.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 generate +//go:build generate package windows diff --git a/src/internal/syscall/windows/net_windows.go b/src/internal/syscall/windows/net_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..3d3df7161c1ce2986da917e645b9a9877e0a76fe --- /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/internal/syscall/windows/registry/export_test.go b/src/internal/syscall/windows/registry/export_test.go index 8badf6fdcf1f9a2612546c741e7119aea58abe24..7f1ac70e8fa01cf1b18e36edda1afde3ce61ca6f 100644 --- a/src/internal/syscall/windows/registry/export_test.go +++ b/src/internal/syscall/windows/registry/export_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. -// +build windows +//go:build windows package registry diff --git a/src/internal/syscall/windows/registry/key.go b/src/internal/syscall/windows/registry/key.go index 612c48f084060fa7c98339e91c076df070123532..ec38cf9288a6f66e0848d1e61ee43c6f3b5a5dbb 100644 --- a/src/internal/syscall/windows/registry/key.go +++ b/src/internal/syscall/windows/registry/key.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 windows +//go:build windows // Package registry provides access to the Windows registry. // @@ -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/internal/syscall/windows/registry/mksyscall.go b/src/internal/syscall/windows/registry/mksyscall.go index 320abf7fc69ecaad80a1487c3ac76f5da018458f..0e0b4210d58a0d25f3a093d28c0f7c2df1be08ad 100644 --- a/src/internal/syscall/windows/registry/mksyscall.go +++ b/src/internal/syscall/windows/registry/mksyscall.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 generate +//go: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 57971629006a7a842ba748eeca38cf84c58078af..278b0b491178d59d9d178bb988017243077ea004 100644 --- a/src/internal/syscall/windows/registry/registry_test.go +++ b/src/internal/syscall/windows/registry/registry_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. -// +build windows +//go:build windows package registry_test @@ -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/syscall/windows/registry/syscall.go b/src/internal/syscall/windows/registry/syscall.go index a6525dac5d91aca8337b323f7098dbee230ec164..cb315adadedf728a3f356bbc09d6f31c0e242908 100644 --- a/src/internal/syscall/windows/registry/syscall.go +++ b/src/internal/syscall/windows/registry/syscall.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 windows +//go:build windows package registry diff --git a/src/internal/syscall/windows/registry/value.go b/src/internal/syscall/windows/registry/value.go index dc3930a6bc2edaa753b23a14f49ff2ecc1af6f13..025574015f69e8ac7bd901268a7330bc07d54a8d 100644 --- a/src/internal/syscall/windows/registry/value.go +++ b/src/internal/syscall/windows/registry/value.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 windows +//go:build windows package registry diff --git a/src/internal/syscall/windows/sysdll/sysdll.go b/src/internal/syscall/windows/sysdll/sysdll.go index c587c19c77d45a31af9d77e18a30e35e627e1a81..e79fd19edc0ebb3a3907d4302575e17a550264b7 100644 --- a/src/internal/syscall/windows/sysdll/sysdll.go +++ b/src/internal/syscall/windows/sysdll/sysdll.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 windows +//go: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/internal/testenv/testenv.go b/src/internal/testenv/testenv.go index c902b1404f246ac4b4791517e2a9ad2d661be5ff..d7614b07068a00b363fa08c0e4d03fdbb2ddc44a 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,59 @@ 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) + // 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) + } + } + }() + + err := cmd.Wait() + if err != nil { + t.Logf("%s exit status: %v", args, err) + } + close(done) + + return b.Bytes(), err +} diff --git a/src/internal/testenv/testenv_cgo.go b/src/internal/testenv/testenv_cgo.go index 02f08f57c717c590bc370457b47534e11c07f0ab..7426a29c1a6efca44692bdfb313b23560cae64f6 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/runtime/crash_nonunix_test.go b/src/internal/testenv/testenv_notunix.go similarity index 53% rename from src/runtime/crash_nonunix_test.go rename to src/internal/testenv/testenv_notunix.go index 5f61476f217069a841cb0e3d4d62822d24fdeba0..180206bc9b701c481ffc706bb4b49fc1394755dc 100644 --- a/src/runtime/crash_nonunix_test.go +++ b/src/internal/testenv/testenv_notunix.go @@ -1,14 +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) -// +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_notwin.go b/src/internal/testenv/testenv_notwin.go index 846ec9385647efabf512f47b8b9361d6b2a8ae95..81171fd193ffbade5ca560ff9b8015f15a6147f2 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/internal/testenv/testenv_unix.go b/src/internal/testenv/testenv_unix.go new file mode 100644 index 0000000000000000000000000000000000000000..3dc5daf45e796566709eecba73a5b0af898db93f --- /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/internal/trace/gc.go b/src/internal/trace/gc.go index cc19fdf8912d298a0ba8d0b8e8322d74956b5bc4..c1bc86234094b0e76d327440a2ee96816800f27e 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 6fb7cca888fa54933dab4a9141be752845498f5f..f3d1a9bb68882f93709663e36e6880f3abbf6052 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/example_test.go b/src/io/example_test.go index a18df9feff696510d54adc9f53d135d15f07b23e..419e449982ad5cabc16b92aa628b22897b9f5848 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 @@ -160,6 +162,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 +208,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") diff --git a/src/io/fs/fs.go b/src/io/fs/fs.go index e603afadb0b1b166e646ed0be6a11c98333fb798..5c0d9a666486958f3aee28a43c65c5c279c9d952 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 2724321ed9d42012e2e0d3de78c673fd4a063fcc..1ea01d5d633df3d8f006c6bb3e961372058b979f 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") @@ -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) } @@ -261,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 @@ -277,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 { @@ -287,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 @@ -478,7 +481,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 @@ -585,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/io/io_test.go b/src/io/io_test.go index 5b355e8c55b1692eb543cdc66cbed0593bb6efd4..308846048095652c8974517dbac250a6278a2b88 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 { diff --git a/src/io/multi_test.go b/src/io/multi_test.go index 909b6d8be283920861f5fe0430d5c77c2ea15277..e877e54571c4a31d2cbeeb1c308d93f79b0b5a7e 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) { @@ -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) { diff --git a/src/io/pipe.go b/src/io/pipe.go index b5343bb6b73b50d4a75d86d7c1ece87abd38d4ed..2724e3f7abe4fddba4800b2ac7185ec66e031e0c 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. diff --git a/src/log/log.go b/src/log/log.go index b77af29032927b8f36a94c55d718dfa41bf328fb..5e79b1952241e0cb201c7091ace5aa61c2ede9a1 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) @@ -187,52 +198,65 @@ 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 + } 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 ...any) { + 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 ...any) { + 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{}) { +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) @@ -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. @@ -313,56 +335,65 @@ 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 + } 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{}) { +func Printf(format string, v ...any) { + 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{}) { +func Println(v ...any) { + if atomic.LoadInt32(&std.isDiscard) != 0 { + return + } std.Output(2, fmt.Sprintln(v...)) } // 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/log/log_test.go b/src/log/log_test.go index 5be8e822586f5bc83d88cb7b50a2d4809ecaef78..938ed423578cb8a8c9d646cd226aff87e7829df8 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++ { diff --git a/src/log/syslog/example_test.go b/src/log/syslog/example_test.go index 993976569e2423b1e9649cb5151486eb289e6ce4..4df29c0af0bfe22643ecf6ab72eb59a3f99079c0 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 6abd4ad124863d014de91a3a1e2037a121b65f32..8c6ba72135298c64c7e4b12c271328066cf5f163 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 62c62508452a06dcbf10905f9aa09035f52dfe02..de1681d6532328649c81332f339d94ec36283f05 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 @@ -11,9 +10,9 @@ import ( "bufio" "fmt" "io" - "log" "net" "os" + "path/filepath" "runtime" "sync" "testing" @@ -82,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 @@ -115,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 @@ -130,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() + }) } } @@ -166,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() @@ -183,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() @@ -283,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 @@ -300,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) @@ -324,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?") @@ -360,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) } diff --git a/src/log/syslog/syslog_unix.go b/src/log/syslog/syslog_unix.go index 2e45f0764fd9e430a652e2daf84d5b22b76467dc..f9cdcdc273493d6834776fcd2330d472721ea6f6 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/make.bash b/src/make.bash index 7986125a06ffc652016aef3252a24f6337379ea9..9acf079c24b9141792131a35e119a6df679e594c 100755 --- a/src/make.bash +++ b/src/make.bash @@ -152,12 +152,26 @@ if [ "$1" = "-v" ]; then shift fi -export GOROOT_BOOTSTRAP=${GOROOT_BOOTSTRAP:-$HOME/go1.4} +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 + 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 + 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.bat b/src/make.bat index 8f2825b09a935fe36cc6cb67baa230eeed9e5977..6bffee050eec548aed83c86659297d534fcef34b 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 7bdc7dea1c1eefde25478f71b970b2466512b41c..37087d6357c8b868e89e7163906ec0563636bba9 100755 --- a/src/make.rc +++ b/src/make.rc @@ -51,13 +51,23 @@ 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(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){ if(go_exe = `{path=$p whatis go}){ goroot = `{GOROOT='' $go_exe env GOROOT} if(! ~ $goroot $GOROOT){ + 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 } } diff --git a/src/math/all_test.go b/src/math/all_test.go index 55c805e199ed9cd200c3a5322e5a3b11ce917f9e..c11d823233148890fa729294a43ee93cc7131d9f 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/arith_amd64.s b/src/math/big/arith_amd64.s index 59be952200f3c40d1ce684f2a5bfaa79e49614f8..5c72a27d8d8e5d82700d6a0219feb5604ac30cda 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 diff --git a/src/math/big/float.go b/src/math/big/float.go index 42050e2c39d76e2c703730ac8883b0dd2f31f715..a8c91a6e547c268371b1093ae0d57c5af2fa47a3 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 diff --git a/src/math/big/floatconv_test.go b/src/math/big/floatconv_test.go index 3aa68341436fef55daa368b0a4405d9751b9d999..a1cc38a4596c5b3f8d67b9506c4a6329eeb848d6 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/example_math_test.go b/src/math/bits/example_math_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4bb466f85cd8f088b03474a009ff4ff80da54ae0 --- /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] +} diff --git a/src/math/bits/make_examples.go b/src/math/bits/make_examples.go index ac4004df4149033a96febdbd0358a68f46b1cf3c..92e9aabfb52738ebc1af7f5526c893b873b14e65 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/cmplx/huge_test.go b/src/math/cmplx/huge_test.go index 78b42316de59d998eea787f476a40a7a2976365d..e794cf281abe6d24764d50390d80c5d9ad1f82f5 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 9ba742a407a27bf52419af92ad6f1f63f27d669f..f4adbd0ae5e11cdea85a685efbed2aea0c9ce5fe 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 ea46577d8ded7f2a78c62d4a687138562eb87051..5b9e06fed33d03ad6745ed9fcd0c2601129e8d66 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/example_test.go b/src/math/example_test.go index 9fc196796796c9ac1c1406a53242741fc207284d..a26d8cbe97d8b463cbcb1ea6e57197545a253dbc 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) diff --git a/src/math/exp2_asm.go b/src/math/exp2_asm.go index 76d258f125264446c956dcf037ca34627025c54b..c26b2c3fab67c743e00d7539f9e0e188214ba18e 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 1b0ac87ebf0ed49f159a628e586a69fbe75f49bb..c2b409329f1e1f18deec411388e6a961ed4e2beb 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 654ccce48103508d82d091a1e9e32fa1060a9a24..0f701b1d6d8da1fa4bf3c8e14c3c45bb348df9d2 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 a1673ea1ddbdace0d34cdef8e5ebfa9b35dd410e..424442845bb07e2645c28df400253e4de9fa4de9 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 b757e6e23033c7455d88cf128609be4446e2bb3b..bd3f02412a28a2ab2cb98d71e88e7b11d5deaa43 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 1265e5171e9b747c096d11cc2c609154d18e02ae..fb419d6da2f6bfc98fcf8d12a82b39dc987f86d0 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 821af2102007c00539707000bd312ff45b9bac30..5641c7ea0a49caf563cf496e2be234612dd0d2c8 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 ec81a4a31da396fe4e9000f996a2dfe9aa6f1624..bc28c6ff693a55855ecee6fc124b224f8a057026 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 9435af41cf8a9a76474bcb6befe5931e3b309c71..852691037f6f4bc4a8e848d17bebc682181073eb 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 bc41b136e56e27857e9fd3ad551e2c1b70aafd1c..8b64812a1c197e048839bf23858ff4bafbd3aaa7 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 4d3b7ee065a6cec1e0cd73b6f2cb111315b85391..848cce13b289b52e37c8f08e9c3d6d0c149831d7 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 e1697164364e096f30bd7d4af52955ab162fabe0..d35992bf37ab69227a4afe49a21cef7e37d0fc30 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 ce431a9d8d41a901c89d4ee4995e3f6d596dbc22..c63be6cf361a5f4c6adfbfcbfdd9ee9a74f81965 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 9607a0894b25a16549a262d365b8408ff992b472..55c6a7f6e20693d98502bbe70df51748806f586d 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/example_test.go b/src/math/rand/example_test.go index 41076135558cbbda570321fe1d6261a77936bacc..f691e39d648fd2986181c127c5a5e3e2f5010078 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/gen_cooked.go b/src/math/rand/gen_cooked.go index 7950e09fd7c3f2b7a99a1e093b831c2d154e96ce..782bb6671d2e933943980d7faa8fc1e4487cb21a 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/rand/regress_test.go b/src/math/rand/regress_test.go index 1f30be85d1ac0fe8305180a4f35f81ea86cd4678..813098ec9c5a7bc1413f1ec6c65feaf837e30283 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/math/sinh_s390x.s b/src/math/sinh_s390x.s index 73701f24f12fd813d590714df09e705a4a3283aa..d684968a3a87e684c80d166369fc3dc229a1186c 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/sqrt_asm.go b/src/math/sqrt_asm.go index b9102568ed51cddf2d6943d02867b93d00d4c3da..2cec1a5903d708c9c114a797d791cdfe674c34a6 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 7b546b7e8cb2cafe404171d8dfed871582c0479e..3979622023141e55b64a4744b12fcadbe1907927 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 e1345eb841dd25c601e6648b7e8c8876df155ae8..c4350d4b8758e12328241f994b7e05a445c3c2a2 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/math/tan_s390x.s b/src/math/tan_s390x.s index b6e2295874e6ee83f1a70b38502492ad7d591135..82267608b97ea6c17b1f7f89a218c1c87c0d15b5 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/mime/encodedword.go b/src/mime/encodedword.go index 58f60daec4312c673bf4b627a869273caf1033df..e6b470b1fb0ef83548656fc06f13d8e14cc6be02 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 56ceb488533fc9b94063b68c6250c2e4e0f4fea6..6c1b095065a8bd59e2d1ea6d9b2af0b3aa9c1f94 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 { @@ -167,15 +163,14 @@ 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 } 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/mime/mediatype_test.go b/src/mime/mediatype_test.go index e91ff38d68b4892d8ff1b8f1836db51ac0920c6e..079c080db716f19caee14186cc02baf2cf5bfc44 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 { diff --git a/src/mime/quotedprintable/reader_test.go b/src/mime/quotedprintable/reader_test.go index 48a7ff64953be95be43ec2c365921927db7ea1b7..19e9fea19bbed1971af86a7f6dca3c53a9dd109c 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 26424339af8d03b319c5dbb870f3562e80cde891..bdb8bb319af39af91ab7d904723725ea9e76677c 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/mime/type_unix.go b/src/mime/type_unix.go index f954bc8a1fba6811ef0daff83c3ab2ecada9aa2a..3abc1fa10e47216bcaea015918e78d451be49b82 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 6e2988225c35ce17d21902d7171204529058038e..4d109aa71a228eb1124900ad22242bdf9d06c303 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 ae93c595afafe6955868a63cca6b0b3583cb268b..29e4ed85abc3b4aecd3a72a3d0c36263a9eeb56e 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 dc13917018b23d0241ccb0adb02aa863437c7d6b..2894d5d846ab99fe3997b64d30aabda2d66bfcd5 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 a94405ecc049698e9ec5c57a5ac5c3836c44180b..f3478148b4f60e352dec179b9c5e8304c446f6e2 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 4b1a2e3e1d44bdcd737708b58ef15bac41125b98..5ab8b5fedea13aacbdc9bb0758c5e4b9da232b73 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 23be72140b694b0d01f6f819ab709b27b38449e3..1456289b0691ba29a3167afde13757f3b6e82c7b 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 1bd6be93f7891c2a632a23260a0092cd2962ebb9..de6e87f17622df6a46a73c1b99ae2e21be6672c4 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 3714793a52f3c5373f5346f56dd4b06f9d2e74da..03392e8ff34c596a979e6b20469e8f636a4925c2 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 3714793a52f3c5373f5346f56dd4b06f9d2e74da..03392e8ff34c596a979e6b20469e8f636a4925c2 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 154405270f17287c6bd3c801cd5f662f8d680bec..fa6e68770ce35f16d1fc7d30e387948b0008815e 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 c4aab33eaa05700bba9e812889220a2df294e841..37c75527f95c0dedf8b36792cc94fb22eb89abc9 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 f9cfad9909cce8c857459f90042b6851d32ec07a..fbb9e10f3401967f2018f477392fb8428f7df752 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 22c67252f55cece64f33b751dc4249337a292362..4d9869de04fabbf6f9dcf14375dfae035cfb1d5d 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 a84f5b0d34c1472e947bf7632917c8758c47e7f0..cde9c957fee53c33d5dc074b3b6ce8a879202479 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 039e4be88b908a257dd426daba8d6616a1d39421..cc84ca47aed0bc79b7791909474c7beab6e1d2fe 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 2ea86e074fb9436fa55f9a6884a828b4cd16ad24..6fc2c1930e8145c2b825fbcfdeac258bee8d06cf 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 @@ -323,7 +320,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/cgo_unix_test.go b/src/net/cgo_unix_test.go index 1f3d9ea207ae93273aa584eaa62906c95ea9b69d..b4da25b84c1fb0f62357d8cce842922544e063fd 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 1fd1f29787c8601a4875143da36d5e91fdbb21cc..6bb6cbbb2fdcfaaf652c5a0147d6ce80dacf6f91 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 6b9569cd92f7f78c9ade438119ef0a17157c7a15..415caedacc41b2501f364bd2852df770a3e3103b 100644 --- a/src/net/conf.go +++ b/src/net/conf.go @@ -3,12 +3,12 @@ // 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 import ( "internal/bytealg" + "internal/godebug" "os" "runtime" "sync" @@ -287,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/conf_netcgo.go b/src/net/conf_netcgo.go index 8f387ebc03e5cfbe681be0cd1752895a8454de09..82d1bb643e19f01ad08211a57dbf75dfbeb8f4e0 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 b1f2c55ea50909bba28834121a2eb7fae32cd3de..5ae705508601979982d871e074f19af3ba69c823 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 45e271c264267ae10f1ed58bc2d40f1d04c8fa3a..3403eddfd3ff7c8d41ecda191e73c95a711f73f6 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 @@ -27,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 723038c7a22a44b6dfc73443ca6b344b855f096f..e0c9cdc2aec425a9cc10c56a69d3b3644402e881 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 @@ -60,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 { @@ -538,6 +534,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") @@ -593,7 +592,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, }) @@ -615,20 +616,16 @@ 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) } } - for _, tt := range tests { + for i, tt := range tests { d := &Dialer{LocalAddr: tt.laddr} var addr string ip := ParseIP(tt.raddr) @@ -640,7 +637,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 { @@ -713,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) @@ -814,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) @@ -920,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()) @@ -940,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()) } @@ -980,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 108b973099715c96dfb7d8e1b4f4e6a08d57f575..4170367c4bd663f2ca96454d4e486ba0f564dd44 100644 --- a/src/net/dial_unix_test.go +++ b/src/net/dial_unix_test.go @@ -3,17 +3,23 @@ // 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 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 @@ -25,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/dnsclient.go b/src/net/dnsclient.go index 1bbe39650bbac2f7ec755d8de90c2ccae3845632..a779c37e53df578e0651aff6c438048380046562 100644 --- a/src/net/dnsclient.go +++ b/src/net/dnsclient.go @@ -5,6 +5,7 @@ package net import ( + "internal/bytealg" "internal/itoa" "sort" @@ -75,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 @@ -136,18 +142,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/dnsclient_unix.go b/src/net/dnsclient_unix.go index 50e9bb0f20dd70745541c67c016eab7fa068ccd2..21aa91f665ad3d481bd3dd22672fd1903b0e0096 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 350ad5def797bc9b95aa4a9c1a56b58e8f5db7f2..14366eca8c63b100eb05c6a5cfefa12cc5f66c76 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 @@ -2121,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/dnsconfig_unix.go b/src/net/dnsconfig_unix.go index db9213a13fd3e95fb6f37226dc748df22920bdf4..5ad254cd7c9a5956c642eab80984dd808ea17e43 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 0e2317c46912f43fb55aabdd0c6b929db212f0a4..4d352214976de224f93ea8dcb6989989b417fbf4 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 d851bf75667d3a6c6c00f75a8220ab67b8ea08d0..28b7c680feb16a27fa7ce3fd6d310c5cb80bc84b 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_plan9_test.go b/src/net/error_plan9_test.go index d7c7f1487fb14321e5cf1275aad7ad003155e71b..1270af19e54d5bcf53e44b99c891cb96b0183476 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_posix.go b/src/net/error_posix.go index 50eb66fc61740e2362313ffb1fef001f8e4ef5d7..10e3caa67b7498b0a7dd0efb99dee003323b4e36 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 ea52a45ee89db67def805df8be4b21f3e9d57a97..081176f771aebf72fa02563e862e82da678dc3f8 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 c304390819a915331276a62c68760ec986d57b8d..4a191673e2fcb22101a2d7a58c4459166d17a2d0 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 @@ -554,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 { @@ -665,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) @@ -774,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/error_unix.go b/src/net/error_unix.go index d0b5e2ce96905e2ca39e2662fb130b0e66166002..0e64b40ea1ccb4e71aa5c729ba38daee71a84a7f 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 533a45e648f11803f10f51095954975e286f1c4b..291a7234f2155574318e523e0c8c74feb1824d13 100644 --- a/src/net/error_unix_test.go +++ b/src/net/error_unix_test.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. //go:build !plan9 && !windows -// +build !plan9,!windows package net import ( + "errors" "os" "syscall" ) @@ -33,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 834a9de4411a015412d49c74c1b93e11d0daac72..25825f96f807534241a6c56433383fd9f5256b24 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/example_test.go b/src/net/example_test.go index 72c7183c13469ae32ee7e6121cd22206801792ed..2c045d73a24bcb01ee8ea08f10afcac4ae305c03 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)) diff --git a/src/net/external_test.go b/src/net/external_test.go index b8753cc092bf1b9d322db63db93addba66022be6..3a97011fe8570b65283046d79b6c3ada1b3ad3a8 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 0320d63a8632131711354104cad69f16edcd1ab1..3478ce723188b579834afcec1b2a741844e019df 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 0f04bb4ed65add47a256ccc53aeffcd4908695d5..2d1f7e22a459fcdb2dcbdb52265ed3eb49d65be9 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 4703ff33a10c71ef22df5317f8b413cfe186e0d6..1845c173bb756c7f3b6f28964d868cb6d0666714 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 @@ -63,6 +62,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) @@ -70,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) @@ -82,12 +104,36 @@ 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) 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/fd_unix.go b/src/net/fd_unix.go index a7bbdd26b458403a849fe1b39206680c38f333af..aaa7a1c18559b10808ad6f87bb5493145c5a5444 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 @@ -92,12 +91,12 @@ 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() { + ctxDone := ctx.Done() + if ctxDone != nil { // Wait for the interrupter goroutine to exit before returning // from connect. done := make(chan struct{}) @@ -117,7 +116,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. @@ -141,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: } diff --git a/src/net/file_stub.go b/src/net/file_stub.go index 9f988fe89936179a3f177e266d15f2afd38f4219..91df926a5789144ef0ad8e197d854b8c5c01d1b0 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 a70ef1b312ff127eb8d4c430c5aa07d3bdb1933a..ea2a218dfbc562146c5904f51b6309e34411b47c 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 @@ -45,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() @@ -62,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) @@ -149,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() @@ -241,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() @@ -315,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/file_unix.go b/src/net/file_unix.go index 4520d4b839ed60d81c48e00e9e37f29175e140be..68d7eb9ca0198c15ed43b890e6dec6e076610314 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 b9153d1947f98ccf0646135ba6fd7781ba8ae65a..7c36b0d6e3272dfd17f8f07660cc14aba265fc4d 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/hosts.go b/src/net/hosts.go index 5c560f3756ed1a2ec58ef9b08345f8a96530c3ba..e604031920b1fe55a495679f64b740683161fdfd 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 19c43999f9291ca77a13053c92b7efedc1c8e95e..72919140e9c79f032b493e2642b863c3b026755b 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/http/cgi/child.go b/src/net/http/cgi/child.go index 0114da377b564725f7d33d804625cb4aacc2994c..bdb35a64e50b97ec0e542458621141cc6f85cb2a 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 eff67caf4e6efbe242129f768898acbd1f95741b..95b2e13e4efb8cdee462a35367c2af4910e8ecdb 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 @@ -351,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/cgi/host_test.go b/src/net/http/cgi/host_test.go index fb869a67282d60df9abd4626accfe737a9f995a3..f8abc88c8973775397063bb28468b9c1c57763c8 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/cgi/plan9_test.go b/src/net/http/cgi/plan9_test.go index f998bac6ea654cdc582e26caa579b057c9f14c40..b7ace3f81c94d572f6851e6f58baef38ea031790 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 bc58ea94cc93b782f1c7efc17e073902cf471e4e..49b9470d4ae2a4128df7502503a335b529d1ec84 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/client.go b/src/net/http/client.go index 4d380c65db983672ea22974c1be303c2f8065c41..22db96b2674c9037fd8620b38ea6c1f03ef85c87 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 01d605c35194f88e954c2b348458f5e7aae9c478..c2ea6f43304037f17c6bc52ae572e75177437c13 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) @@ -746,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...) @@ -1206,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") } @@ -1276,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 } } @@ -1353,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) { @@ -2082,3 +2124,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/clientserver_test.go b/src/net/http/clientserver_test.go index 5e227181acb05cf9e5034682c8dc0375e619f49f..71b2a32cb4eea5893390226b36c129821387d2c2 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 @@ -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/cookie.go b/src/net/http/cookie.go index ca2c1c2506694cc7c636c09af3b7cf9921352287..cb37f2351f58890b0c73008946dded3456be1e28 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" @@ -67,15 +69,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 +91,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 @@ -240,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. // @@ -256,19 +285,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 +401,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/cookie_test.go b/src/net/http/cookie_test.go index 959713a0dcf0a092e9cde35824517f89cecbb303..ccc5f98091d6d3251885e4a44ff2898e20806003 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) @@ -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{ diff --git a/src/net/http/export_test.go b/src/net/http/export_test.go index 096a6d382a8afab3ea3e8ce7cb231524994ce02c..a849327f4528b430cac53046168f4a4a9440aaf2 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/fs.go b/src/net/http/fs.go index 57e731e481ad49830b67a907dee59f554130579b..19b2894bf2ff388cbc0de14c38e26c4b342d2b4c 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/fs_test.go b/src/net/http/fs_test.go index b42ade1e8ac4f4482b37fbee242205f6384e857e..4b01cce72dbf413b93b5c6839ded32e5e47a774a 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 a948ff3eed4af65f0ac3393d89355cd2eabfee05..bb82f2458589d83c3b03bb5351d3bfdd8f111772 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 { @@ -733,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) } @@ -759,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) { @@ -771,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) @@ -806,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 } @@ -825,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 + } } } @@ -922,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) @@ -1208,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 @@ -1224,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} } @@ -1438,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, @@ -1583,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 @@ -1745,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, @@ -1819,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) @@ -1907,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() @@ -1924,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 } } @@ -1932,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)] @@ -2014,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 @@ -2022,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 { @@ -2032,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. @@ -2151,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} @@ -2191,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{ @@ -2231,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 } @@ -2242,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 @@ -2255,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{ @@ -2307,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, } @@ -2316,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 } } @@ -2328,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)] @@ -2444,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]) @@ -2491,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 @@ -2521,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 @@ -2571,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, } @@ -2582,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. @@ -2589,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)] @@ -3570,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() @@ -3786,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. @@ -3915,16 +3979,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){} @@ -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()) @@ -4373,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 } @@ -4479,7 +4550,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 +4590,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 } @@ -5055,7 +5135,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 } @@ -5080,7 +5160,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 @@ -5100,7 +5180,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 @@ -5119,7 +5199,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 @@ -5130,7 +5210,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)) { @@ -5151,7 +5231,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() @@ -5203,7 +5283,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 } @@ -5211,7 +5291,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 @@ -5278,7 +5358,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 @@ -5311,7 +5391,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" @@ -5328,7 +5408,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 @@ -5341,7 +5421,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") @@ -5353,12 +5433,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)) @@ -5366,7 +5446,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") @@ -5452,7 +5532,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 @@ -5469,7 +5549,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) } @@ -5480,7 +5560,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 @@ -5497,14 +5577,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 @@ -5514,7 +5594,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) @@ -5558,15 +5638,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() { @@ -5575,7 +5655,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) } @@ -5584,13 +5664,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 } @@ -5599,7 +5679,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) @@ -5656,7 +5736,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: @@ -5669,13 +5749,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) @@ -5758,7 +5838,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 } @@ -6642,6 +6722,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. @@ -6657,6 +6765,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. @@ -6727,6 +6844,17 @@ 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. + // 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). @@ -6833,11 +6961,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 @@ -6850,87 +6979,94 @@ 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 - hbuf bytes.Buffer // HPACK encoder writes into this - henc *hpack.Encoder - freeBuf [][]byte + // 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 sync.Mutex // held while writing; acquire AFTER mu if holding both - werr error // first write error that has occurred + // 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 } // 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 - 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 + isHead bool + + 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 + reqBody io.ReadCloser + reqBodyContentLength int64 // -1 means unknown + reqBodyClosed bool // body has been closed; guarded by cc.mu - 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, @@ -6942,73 +7078,65 @@ 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) +func (cs *http2clientStream) abortStreamLocked(err error) { + cs.abortOnce.Do(func() { + cs.abortErr = err + close(cs.abort) + }) + if cs.reqBody != nil && !cs.reqBodyClosed { + cs.reqBody.Close() + cs.reqBodyClosed = true } -} - -// 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 + // 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 { +func (cs *http2clientStream) abortRequestBodyWrite() { 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") + if cs.reqBody != nil && !cs.reqBodyClosed { + cs.reqBody.Close() + cs.reqBodyClosed = true + cc.cond.Broadcast() } - cc := cs.cc - cc.mu.Lock() - cs.stopReqBody = err - 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 @@ -7082,9 +7210,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 @@ -7095,7 +7223,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() } } } @@ -7126,7 +7254,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 } @@ -7139,7 +7267,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 @@ -7151,10 +7278,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 } @@ -7166,6 +7291,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 @@ -7240,14 +7369,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 @@ -7262,9 +7392,16 @@ 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 { + cc.fr.countError = t.CountError + } cc.fr.ReadMetaHeaders = hpack.NewDecoder(http2initialHeaderTableSize, nil) cc.fr.MaxHeaderListSize = t.maxHeaderListSize() @@ -7317,6 +7454,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() @@ -7334,27 +7478,94 @@ 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 +} + +// 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 { canTakeNewRequest bool - freshConn bool // whether it's unused by any previous request } func (cc *http2ClientConn) idleState() http2clientConnIdleState { @@ -7375,13 +7586,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 } @@ -7412,7 +7623,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 } @@ -7427,9 +7638,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 @@ -7468,15 +7685,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 } @@ -7484,7 +7704,6 @@ func (cc *http2ClientConn) sendGoAway() error { return err } // Prevent new requests - cc.closing = true return nil } @@ -7492,17 +7711,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() } @@ -7517,47 +7731,10 @@ 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") - 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] - } + if f := cc.t.CountError; f != nil { + f("conn_close_lost_ping") } - 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. + return cc.closeForError(err) } // errRequestCanceled is a copy of net/http's errRequestCanceled because it's not @@ -7621,41 +7798,158 @@ func http2actualContentLength(req *Request) int64 { return -1 } +func (cc *http2ClientConn) decrStreamReservations() { + cc.mu.Lock() + defer cc.mu.Unlock() + cc.decrStreamReservationsLocked() +} + +func (cc *http2ClientConn) decrStreamReservationsLocked() { + if cc.streamsReserved > 0 { + cc.streamsReserved-- + } +} + func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { - resp, _, err := cc.roundTrip(req) - return resp, err + ctx := req.Context() + cs := &http2clientStream{ + 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 { + case <-cs.donec: + return nil + case <-ctx.Done(): + return ctx.Err() + case <-cs.reqCancel: + return http2errRequestCanceled + } + } + + 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: + return handleResponseHeaders() + case <-cs.abort: + 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) + return nil, err + case <-cs.reqCancel: + cs.abortStream(http2errRequestCanceled) + 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(req *Request) { + err := cs.writeRequest(req) + cs.cleanupWriteRequest(err) } -func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterReqBodyWrite bool, err error) { +// 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(req *Request) (err error) { + cc := cs.cc + ctx := cs.ctx + if err := http2checkConnHeaders(req); err != nil { - return nil, false, err - } - if cc.idleTimer != nil { - cc.idleTimer.Stop() + return err } - trailers, err := http2commaSeparatedTrailers(req) - if err != nil { - return nil, false, 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 <-cs.reqCancel: + 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 + if http2isConnectionCloseRequest(req) { + cc.doNotReuse = true + } + 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") == "" && - 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 @@ -7668,195 +7962,224 @@ 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 { + if !httpguts.HeaderValuesContainsToken(req.Header["Expect"], "100-continue") { + continueTimeout = 0 + } else { + 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 + // 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 + } - defer func() { - cc.wmu.Lock() - werr := cc.werr - cc.wmu.Unlock() - if werr != nil { - cc.Close() + hasBody := cs.reqBodyContentLength != 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 <-cs.reqCancel: + 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); 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: + respHeaderRecv = nil + respHeaderTimer = nil // keep waiting for END_STREAM + case <-cs.abort: + return cs.abortErr + case <-ctx.Done(): + return ctx.Err() + case <-cs.reqCancel: + return http2errRequestCanceled } } +} - readLoopResCh := cs.resc - bodyWritten := false - ctx := req.Context() +func (cs *http2clientStream) encodeAndWriteHeaders(req *Request) error { + cc := cs.cc + ctx := cs.ctx - 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 <-cs.reqCancel: + return http2errRequestCanceled + default: } - for { + // 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(req) + if err != nil { + return err + } + hasTrailers := trailers != "" + contentLen := http2actualContentLength(req) + hasBody := contentLen != 0 + hdrs, err := cc.encodeHeaders(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 + + 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 + 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 { + // 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: - 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 - 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() - case <-req.Cancel: - if !hasBody || bodyWritten { - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil) + 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 { - bodyWriter.cancel() - cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) - <-bodyWriter.resc - } - cc.forgetStreamID(cs.ID) - return nil, cs.getStartedWrite(), 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 + 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) + } + + cc.wmu.Lock() + werr := cc.werr + cc.wmu.Unlock() + if werr != nil { + cc.Close() } + + close(cs.donec) } -// 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: } } } @@ -7883,10 +8206,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 } @@ -7902,32 +8221,59 @@ var ( http2errReqBodyTooLong = errors.New("http2: request body larger than specified content length") ) -func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) { +// 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 := 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 + // 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(req *Request) (err error) { cc := cs.cc + body := cs.reqBody 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) - // 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 - cerr := bodyCloser.Close() - if err == nil { - err = cerr - } - }() - req := cs.req hasTrailers := req.Trailer != nil - remainLen := http2actualContentLength(req) + remainLen := cs.reqBodyContentLength 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,35 +8284,36 @@ 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 { err = http2errReqBodyTooLong - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, err) return err } } - if err == io.EOF { - sawEOF = true - err = nil - } else if err != nil { - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, err) - 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: - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil) - return err - case err != nil: + if err != nil { return err } cc.wmu.Lock() @@ -7997,24 +8344,26 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos return nil } - 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) - return err - } - } - + // 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() - maxFrameSize := int(cc.maxFrameSize) + 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 len(trailer) > 0 { + trls, err = cc.encodeTrailers(trailer) + if err != nil { + return err + } + } // Two ways to send END_STREAM: either with trailers, or // with an empty DATA frame. @@ -8035,17 +8384,24 @@ 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 + 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 } - 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 <-cs.reqCancel: + return 0, http2errRequestCanceled + default: } if a := cs.flow.available(); a > 0 { take := a @@ -8063,9 +8419,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 == "" { @@ -8251,12 +8612,12 @@ func http2shouldSendReqContentLength(method string, contentLength int64) bool { } } -// requires cc.mu be held. -func (cc *http2ClientConn) encodeTrailers(req *Request) ([]byte, error) { +// requires cc.wmu be held. +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()) @@ -8266,7 +8627,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 @@ -8296,51 +8657,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. @@ -8400,23 +8761,49 @@ 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}: + case <-cs.peerClosed: + // The server closed the stream before closing the conn, + // so no need to interrupt it. default: + cs.abortStreamLocked(err) } - close(cs.done) } - 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 @@ -8433,9 +8820,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 } @@ -8443,6 +8828,7 @@ func (rl *http2clientConnReadLoop) run() error { } continue } else if err != nil { + cc.countReadFrameError(err) return err } if http2VerboseLogs { @@ -8455,22 +8841,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: @@ -8488,38 +8868,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 { @@ -8543,9 +8909,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 { @@ -8553,7 +8921,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 } @@ -8615,6 +8987,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 { @@ -8627,42 +9002,49 @@ 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 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 } - cs.bufPipe = http2pipe{b: &http2dataBuffer{expected: res.ContentLength}} + 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} - go cs.awaitRequestCancel(cs.req) - 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 @@ -8701,8 +9083,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 } @@ -8720,7 +9101,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 @@ -8738,8 +9119,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 { @@ -8756,6 +9135,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() @@ -8776,34 +9157,45 @@ 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() + + // 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 { 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.ctx.Done(): + // 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 + } 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() @@ -8832,6 +9224,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{ @@ -8841,7 +9241,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, @@ -8863,30 +9263,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 } } @@ -8899,24 +9308,32 @@ 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 + // 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) + } } 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() { @@ -8935,12 +9352,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() @@ -8953,12 +9391,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: @@ -8990,17 +9430,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 } @@ -9020,24 +9466,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 } @@ -9059,19 +9503,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: @@ -9148,6 +9597,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 { @@ -9194,87 +9649,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 { @@ -9751,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) } @@ -9771,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 @@ -10450,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() @@ -10464,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/net/http/header.go b/src/net/http/header.go index 4c72dcb2c88d254f3e8b81a483bb6b40079f4b37..6487e5025d718d20ef8994bcd06c634169643034 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. @@ -155,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 @@ -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 response 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 47893629194b6a6dedde343b06c73ac0db976f34..57d16f51a5d62e662847b47fbf33203048c8b8bb 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) { diff --git a/src/net/http/httptrace/trace.go b/src/net/http/httptrace/trace.go index 5777c91747c200c9e232c50a3c9796e114952c6c..6af30f78d1f4b99b4b6c7f772761fc889a514a73 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.go b/src/net/http/httputil/dump.go index 2948f27e5d5c58b4b93a7b3452b56b7062264406..d7baecd9c17b3d2d14a6faef879c045c774b11b4 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/httputil/dump_test.go b/src/net/http/httputil/dump_test.go index 366cc8239ac7550b8137044d8a534d8d556258ff..5df2ee80752a5808f268cca695ab0807d39d8455 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 8b63368386f43ba81a574e571ada7bcfffd195e0..319e2a3f3f0430af0bb7feaf28f73f97d3d2c930 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 } @@ -483,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/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go index 4b6ad77a29466fe0fbb9f1e79fa1bd804b2264ea..90e8903e9cfd5bfa3086422cb9f442a0861bd250 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{ diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go index f06e5725f3477988281ef10ae078cd945083a428..37a72e9031a1127f573d3f34f42d1ad0740593ae 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 @@ -152,6 +159,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 +168,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/internal/chunked_test.go b/src/net/http/internal/chunked_test.go index 08152ed1e24d67cbc439a4d90ffbe65682144ad6..5e29a786dd61e42d9380df0aaa6bf9d343293fa3 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) + } +} diff --git a/src/net/http/main_test.go b/src/net/http/main_test.go index 6564627998f53eb988cead8f72cbfbfc4202e54f..27872b4e7a40f10409e85bc83e9d5dd96240f2a4 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") || @@ -46,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 } diff --git a/src/net/http/omithttp2.go b/src/net/http/omithttp2.go index 79599d006aaf94dc1537c6024d200de2b6d0c961..3316f55c6dcf5c5d496f5504d57068985991bf4a 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 @@ -27,7 +26,7 @@ const http2NextProtoTLS = "h2" type http2Transport struct { MaxHeaderListSize uint32 - ConnPool interface{} + ConnPool any } func (*http2Transport) RoundTrip(*Request) (*Response, error) { panic(noHTTP2) } @@ -57,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/pprof/pprof.go b/src/net/http/pprof/pprof.go index 888ea35c9a6c5229c50c946926f17a256c8da59c..dc855c8a6da9a04acde7784ed8638ff1dc4f12fc 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/ diff --git a/src/net/http/request.go b/src/net/http/request.go index 09cb0c7f564f745f1b50c9f861f441603055e764..76c2317d28256dfbbce67752b0951290bbea5656 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 } - return major, minor, true + min, err := strconv.ParseUint(vers[7:8], 10, 0) + if err != nil { + return 0, 0, false + } + return int(maj), int(min), true } func validMethod(method string) bool { @@ -939,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) } @@ -950,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 @@ -979,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/request_test.go b/src/net/http/request_test.go index 4e0c4ba207f8be66a7f529de7aa7ac7fb052021a..4363e1103332567d28e7d0a4103945241cda87a1 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) { diff --git a/src/net/http/requestwrite_test.go b/src/net/http/requestwrite_test.go index 1157bdfff940a97cc0ec1beace82f892607c3d35..bdc1e3c508c73f823d6a7868610a15f76dbbe454 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.go b/src/net/http/response.go index b8985da3c80fc413ef30f640bbd8fd282e65465e..297394eabebed53dc1853d4547c5e19e73256e4b 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/response_test.go b/src/net/http/response_test.go index 8eef65474e4c8586de6967e4875fb2055e7c724b..5a735b021587d5592218ff8ca4626cb7bfb57efc 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.go b/src/net/http/roundtrip.go index eef7c79293e643e08677e24ba9d5c1e2fb769ffc..c4c5d3b6ebb3dd67786808e8885876fcfe036a52 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 74c83a9172cab2524156d097394fb1fe5f1ef202..01c0600ba55500aea05b3f38a57c05ee0e124fec 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 @@ -41,11 +40,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) } @@ -111,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() @@ -131,8 +138,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") @@ -159,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()) @@ -200,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 @@ -212,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 @@ -266,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()) @@ -275,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 6394da3bb7cf60d0263e723bb611967f64d43820..fb18cb2c6f5b2e156bb10a177b7615f8a6e40bbe 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" @@ -2146,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 @@ -2238,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" + @@ -2273,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) { @@ -2285,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: @@ -2307,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) @@ -2428,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: @@ -2450,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) @@ -2500,6 +2517,47 @@ func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) { } } +func TestTimeoutHandlerContextCanceled(t *testing.T) { + setParallel(t) + defer afterTest(t) + writeErrors := make(chan error, 1) + sayHi := HandlerFunc(func(w ResponseWriter, r *Request) { + w.Header().Set("Content-Type", "text/plain") + 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.WithCancel(context.Background()) + cancel() + h := NewTestTimeoutHandler(sayHi, ctx) + cst := newClientServerTest(t, h1Mode, h) + defer cst.close() + + 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 in handler: %v, want %g", g, e) + } +} + // https://golang.org/issue/15948 func TestTimeoutHandlerEmptyResponse(t *testing.T) { setParallel(t) @@ -2708,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 @@ -3017,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) } } @@ -3884,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) @@ -3893,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: @@ -4888,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) })) @@ -5689,22 +5739,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) + } } } @@ -5933,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. @@ -6232,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 } @@ -6490,7 +6551,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")) @@ -6609,3 +6670,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 5b113cff970dc19148c5ba4fe96020b54bfd0d5a..ddc799bd9e45090e48d2ec32cc7a73935c2886ba 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" @@ -798,7 +798,7 @@ var ( ) var copyBufPool = sync.Pool{ - New: func() interface{} { + New: func() any { b := make([]byte, 32*1024) return &b }, @@ -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 { @@ -1404,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 @@ -1419,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. @@ -1794,6 +1817,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,18 +1825,25 @@ 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) } }() 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 @@ -1826,6 +1857,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) { @@ -1926,7 +1962,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 @@ -2272,7 +2310,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) @@ -3152,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 { @@ -3163,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...) @@ -3259,7 +3297,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 @@ -3326,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 { @@ -3354,9 +3392,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 + } } } @@ -3367,7 +3411,7 @@ type timeoutWriter struct { req *Request mu sync.Mutex - timedOut bool + err error wroteHeader bool code int } @@ -3387,8 +3431,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) @@ -3400,7 +3444,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 { @@ -3567,3 +3611,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) + }) +} diff --git a/src/net/http/server_test.go b/src/net/http/server_test.go index 0132f3ba5fbd77611fb22d9c965f98f98afccb33..d17c5c1e7ef5e6329587d37761f38f3d8329825f 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") diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go index 85c2e5a360d68676f2f6c4574b0e5833fc68ca24..6d51178ee9082dc8cdb12eba6fce8f9f0d8b1f4d 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 @@ -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 { @@ -480,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 @@ -808,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 @@ -1029,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 @@ -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 } diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 309194e8e52c86f8ef17109464f8b28a1f244bfa..5fe3e6ebb49ac2654b72f247ddf2e493d2df5088 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" @@ -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, @@ -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 } @@ -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) } } @@ -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. @@ -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_default_js.go b/src/net/http/transport_default_js.go new file mode 100644 index 0000000000000000000000000000000000000000..c07d35ef861ebc2a8c56288b46b8fbb949a5e23e --- /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 0000000000000000000000000000000000000000..8a2f1cc42bbcf5422f0adfdb0416aa61edaeb997 --- /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 +} diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index eeaa49264450de6785415669622801410d8abca9..e5d60afb1bb51f0e3ba4a9d00f82759ec12eab23 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...) @@ -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() +} diff --git a/src/net/http/triv.go b/src/net/http/triv.go index 4dc62407c6d5ecef2049db623b31c5db4d21df8f..11b19ab30c55be11df0a5e4afb2cc9c847c94d4f 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_aix.go b/src/net/interface_aix.go index 49f78c2abbcbfa78eba1c57e3f8755842dc4a095..7ad45d11756a0646096121fdcf200a0e61ecd5e9 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 } diff --git a/src/net/interface_bsd.go b/src/net/interface_bsd.go index 7578b1a16a91a90baabeef015e2f84d18fe14fb3..db7bc756d8cfa597bea4407e7621ee5ec1173141 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 8d0d9c367198d0abd5ba602c4209c6b0988c55ee..ce59962f6108f42e50f4f740b368933dbd420b15 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 6230e0bfeec1d56a117c107beb69e9db7861d61b..e9bea3d3798a0672c4132114a93767e66b3d7f15 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_freebsd.go b/src/net/interface_freebsd.go index 2b51fcb632a3f7add6cb1a0ece5b920899263e4d..8536bd3cf6482bbd46a9934497c1c0705fd3d8bf 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 diff --git a/src/net/interface_stub.go b/src/net/interface_stub.go index efe67c24d3cde8d219488dcb3500471245a9a0b2..2d4475f63eeba33722afd2e6234abf4b073da104 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 754db36e3c44306edfa986165478611b574b3905..f6c98684181efbc4c68c0ec4db2c3c8da2bad035 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 0d69fa5da4127d2f9c863ec597db31ee8bdfcfa4..92ec13a909ca72ba736cd01c521ce65e2ab7b26a 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 8af85d382eb0935cbb606e9c6869a5b7354b69c8..c7c8d16d4c9a7e0435994022eae9ed7f7f252daf 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 6aa8875b66cf6c1cee258401128c733ee49d4c66..7d21f6f99f6baadfa6735a23a09444c9a640efd7 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 cda74e8639986909c9a3bf740a825e547f12ba35..fcad4ceae31e8ed87018c12783821a62362e074b 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 5aa2ecec08fd31ad596e475345c0befa72fc8721..8a2fc353f05816aa61f98c931bcc54e3705a6d06 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 bfe9d4dbd3622927e8fa330219baa6404f007996..77d68f61120fdd904c8f576475c4c4a925770de4 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 c7f8331c2e52765321579b6d17a052cc7b3c3e97..cc7cefbe2c5cf046b35c692cb18b005d39e5f269 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 e7cc45922e09d1c6815c15cad54ee66673f08070..0424164ed3095eb79bf76284d2d08318ed7c7cd7 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.go b/src/net/ip.go index 38e1aa2247f5c329d9c247de420b2a58ecc8a25b..b016bef144a5d7e3b4e7c0369b617fd88161f93d 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 diff --git a/src/net/ip_test.go b/src/net/ip_test.go index 5bbda6024dc3d9dd54189eb202afcb5cda572ad7..777461ad27245e48c9729d0335f7404450a9c992 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 @@ -719,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/iprawsock_posix.go b/src/net/iprawsock_posix.go index b94eec0e182b3d006771e30238078fdb93dd9f44..74f977e1efe079940e5d911686087095542def14 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 a96448ee6c656817f1a16e5ff6fd27ca774048fa..ca5ab480c0eca9419e5a532979e6cf34668ae982 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 c51c2274015dcf8382e079bcb8ef3759d1a87f88..e433e8a91c75c0b025e657a98bebc33da9658e6e 100644 --- a/src/net/ipsock_posix.go +++ b/src/net/ipsock_posix.go @@ -3,13 +3,13 @@ // 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 import ( "context" "internal/poll" + "net/netip" "runtime" "syscall" ) @@ -142,42 +142,87 @@ 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()} } + +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/listen_test.go b/src/net/listen_test.go index b1dce29ac209a91e45436583ef3ffa2788e39378..59c0112122babe68d5e5af7d31d82f154429e43b 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 @@ -380,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 @@ -535,8 +534,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 +607,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") @@ -702,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() { @@ -743,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 @@ -764,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/lookup.go b/src/net/lookup.go index d350ef7fc03b0b6259a562e5f28b04a40157fdf0..c7b8dc690590ef664c9c87950ecdd5fba74f686f 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 { @@ -242,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 @@ -291,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) }) @@ -316,24 +339,45 @@ 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) } } // 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 } @@ -347,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 } @@ -442,7 +486,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 +504,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 +534,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 +547,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 { @@ -514,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) @@ -532,7 +574,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 +587,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 +627,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 +643,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 { @@ -620,6 +662,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/net/lookup_fake.go b/src/net/lookup_fake.go index f4fcaed5cfa1c78d9ca3b80d81926b20074de7dd..c27eae4ba5097e11460aae0f40f7206eb3c0a9df 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_plan9.go b/src/net/lookup_plan9.go index 75c18b33ac06f0eca362200a8909b45bf3ab23c3..d43a03b778d477a3327dfd00f96667a6f56b9507 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_test.go b/src/net/lookup_test.go index 3faaf007106b7c7327f1eb194dfc8d944f8b53d4..d71a18c684d59a2fd853ebdad003ee11cde0bd12 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 @@ -890,7 +889,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) } @@ -926,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 @@ -944,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) } @@ -1050,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"}, @@ -1267,3 +1274,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() +} diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 8030e3d99e1e13dfb5e3f2ef8f361edba6e34af4..255a19dfdb4dd4bf8da0e6d6392688147e8fcd56 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/lookup_windows.go b/src/net/lookup_windows.go index bb34a081336930dee36c8a6d17e67ded263f9058..27e5f86910e0fcff75b14b80731b4bebb46d21d4 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 aa95501d023930d114970e828296e9d10b531d9e..9254733364595933d311ffd0493a7d576e6c3643 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) } @@ -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/mail/message.go b/src/net/mail/message.go index 47bbf6ca9771bdcf23f3cd37357d21f721816ef3..985b6fcae271bc9eba8993e87b290f2723007422 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...) } @@ -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_cloexec_test.go b/src/net/main_cloexec_test.go index 742be2fcd81eef81e3300193e4d037a22897f5b3..ca7fc7849137a2d961284913076045d9f38f3b22 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 645b267b78090835050a56c68e768759239b0f5f..41b78eda1d8219f58388e58512fe5e757450e1b8 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 bcea630cd3c4ccb037b4d19582c927892d13a825..ab050fac2b4ec04aad5b38be65d88a96fa1b1fb0 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 c9ab25a4ad572ebb8e663fbf6bfe1d2c18999802..8899aa9c94ec7200b1e25b17062428e99d16eac3 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 @@ -18,9 +17,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 dc17d3fbb84d1547879afa575352561299aa510e..1ee8c2efe717b44c1723a5f8e6435ce4f0b213f3 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 @@ -174,11 +173,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/main_unix_test.go b/src/net/main_unix_test.go index c8cff2d305aa9998395a6641db90c359bf187b0a..2ed0615ad86a2ea8b6b33d87c1649410ae74bed9 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 b50a1e59a1a9239b7da034fe38f6b1619e88ea95..186bd330b2c20933228fba0fb025c2a23b13de28 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 @@ -11,46 +10,67 @@ 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(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(t)) } - 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) { @@ -121,12 +141,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 { @@ -135,8 +153,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 { @@ -288,75 +306,39 @@ 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")) +func newLocalPacketListener(t testing.TB, network string) PacketConn { + listenPacket := func(net, addr string) PacketConn { + c, err := ListenPacket(net, addr) if err != nil { - break + t.Helper() + t.Fatal(err) } + return c } - 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": 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(t)) } - 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) { @@ -421,20 +403,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) { @@ -505,25 +485,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/net.go b/src/net/net.go index a7c65fff79526d1ce70fef7a96eaafd9ff06dd18..77e54a91258e14997615d3fc6e88a27afb58333d 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 @@ -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. diff --git a/src/net/net_fake.go b/src/net/net_fake.go index 74fc1da6fd80af665696880153bfc49a508900d6..ee5644c67f087f77c021aa747a61c5f368b18b1e 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 @@ -266,16 +265,48 @@ 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) { 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 +} + +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 } +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/net_test.go b/src/net/net_test.go index 6e7be4db23c1e2a26733bf251ff47546efcddd0d..7b169916f1b4bd0c5feab13e7c25f1faa8f4f85a 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 @@ -34,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()) @@ -133,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) @@ -190,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()) @@ -235,16 +225,12 @@ 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()) } - dst := ln.Addr().String() if err := ln.Close(); err != nil { if perr := parseCloseError(err, false); perr != nil { t.Error(perr) @@ -257,28 +243,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.) }) } } @@ -293,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()) @@ -321,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() @@ -378,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) @@ -408,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() @@ -460,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/netgo_unix_test.go b/src/net/netgo_unix_test.go index 5551e47de7ff7d2c616be585492eb13ebf4aa52e..019772aa6aaab4ed183ca1089e44b6b89adba2e0 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/netip/export_test.go b/src/net/netip/export_test.go new file mode 100644 index 0000000000000000000000000000000000000000..59971fa2e4e51998c5add3103dd5a9a6bb530fa2 --- /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 0000000000000000000000000000000000000000..107fe1f08309e25a28573b9188d3233380ace58a --- /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 0000000000000000000000000000000000000000..70513abfd920cec4780e4f55818b268e146a50ef --- /dev/null +++ b/src/net/netip/leaf_alts.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. + +// 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) +} + +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 new file mode 100644 index 0000000000000000000000000000000000000000..591d38abc894b5f15d633acb812c2d9e14be1e1c --- /dev/null +++ b/src/net/netip/netip.go @@ -0,0 +1,1498 @@ +// 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 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). +// +// 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. +// +// 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. + // + // 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} } + +// 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{ + 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 + 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"} + } + } 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 + digLen = 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 } + +// 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 == IPv4Unspecified() || 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 == IPv4Unspecified() || 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() (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() (a4 [4]byte) { + if ip.z == z4 || ip.Is4In6() { + bePutUint32(a4[:], uint32(ip.addr.lo)) + return a4 + } + if ip.z == z0 { + panic("As4 called on IP zero value") + } + 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 { + 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. + if z := ip.Zone(); z != "" { + return "::ffff:" + ip.Unmap().String() + "%" + z + } else { + 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:"...) + b = ip.Unmap().appendTo4(b) + if z := ip.Zone(); z != "" { + b = append(b, '%') + b = append(b, z...) + } + return 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:"...) + 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. +// 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 +} + +func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte { + var b []byte + switch ip.z { + case z0: + b = make([]byte, trailingBytes) + case z4: + b = make([]byte, 4+trailingBytes) + bePutUint32(b, uint32(ip.addr.lo)) + default: + 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. +// 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: + 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, ':') + 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 +} + +// 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 := p.Addr().marshalBinaryWithTrailingBytes(2) + 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. +// 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 complicated 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 a 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 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 { + if p.ip.Is4In6() { + b = append(b, "::ffff:"...) + b = p.ip.Unmap().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 +} + +// 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 := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1) + b[len(b)-1] = uint8(p.Bits()) + return b, 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() { + 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 0000000000000000000000000000000000000000..f5cd9ee86d83bae81c6ccc4b60a2b062599684b7 --- /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 0000000000000000000000000000000000000000..d988864827b6ebe2f9af17a9f9444b7895e8403c --- /dev/null +++ b/src/net/netip/netip_test.go @@ -0,0 +1,1974 @@ +// 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 + mustIPPort = MustParseAddrPort +) + +func TestParseAddr(t *testing.T) { + var validIPs = []struct { + in string + ip Addr // output of ParseAddr() + str string // output of String(). If "", use in. + wantErr string + }{ + // 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", + 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", + 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. + { + 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", + }, + // 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", + 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 { + 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("got %#v, want %#v", 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 _, n := range []int{3, 5} { + var ip2 Addr + if err := ip2.UnmarshalBinary(bytes.Repeat([]byte{1}, n)); err == nil { + t.Fatalf("unmarshaled from unexpected IP length %d", n) + } + } +} + +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 + 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 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 + 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) + } + } +} + +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", + "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.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")}, + {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 any +} + +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) + } + } +} + +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) { + addr := MustParseAddr("1::10") + for i := 0; i < b.N; i++ { + sink16 = addr.As16() + } +} diff --git a/src/net/netip/slow_test.go b/src/net/netip/slow_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5b46a39a83448822dc0e1d9fab1a6111cabe758c --- /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 0000000000000000000000000000000000000000..738939d7de165e034cbd0d13082c26013965b4b0 --- /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 0000000000000000000000000000000000000000..dd1ae0ec798813e0f9d2f0dcc79fb1b98fc3cfad --- /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/nss.go b/src/net/nss.go index 85177cab9b92da2cbd26aeff0959180c8df34252..ee5568883f2d473736f6835442e7d8e5b78ef68f 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 4b73886c5119c453f953b43d830713cd11facff2..c9ccc60cb787225413d2cd96a9e6c7700a41aa3d 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 aeb9845fa77b8fc12828c797908910b673bfe9dc..fa160df5f50a1da8f5e36f69007f162e238912d8 100644 --- a/src/net/packetconn_test.go +++ b/src/net/packetconn_test.go @@ -6,14 +6,12 @@ // tag. //go:build !js -// +build !js package net import ( "os" "testing" - "time" ) // The full stack test cases for IPConn have been moved to the @@ -29,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 { @@ -61,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 { @@ -71,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 { @@ -93,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 { @@ -116,9 +117,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 { @@ -127,9 +125,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) diff --git a/src/net/parse.go b/src/net/parse.go index 6c230ab63fa0c7906a5c80b95f0e2443be5d139f..ee2890fe2ce5b33a18a692c48a36c50587d835a9 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 { @@ -331,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 c5f8bfd198ce4f519beae58f25407ffe747b44cb..97716d769a9b498c037dcae8f89e0d4bc32aa1b5 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/platform_test.go b/src/net/platform_test.go index 2da23dedcea6749a74997c3804e376dc7b9b3801..c522ba282915b0c729e52e76c5dd780ddf276328 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": @@ -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/port_unix.go b/src/net/port_unix.go index a9a96a2323b80d0a104e3de0dc132a08d3450c7a..102722b2ca7045f6ea655c9e8c9db2920bc21bea 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 fc9b3862563e9a2c0cef4a76eee225eb281848dc..e4198a3a051a6a8d7518953f94e25d2fc5545884 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 @@ -74,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) @@ -208,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) @@ -249,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/rawconn_stub_test.go b/src/net/rawconn_stub_test.go index 975aa8d9569162ff52f750d58f648e0f6f77502a..ff3d829893d06e07c6ff8631b9d1f5add88a5caa 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 3ef7af33b7330e307d31d61f1bf2fc330ef72369..d1ef79d7157a3b87b8d82ab3312bbc12150f3180 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 @@ -65,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) @@ -103,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()) @@ -181,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/rawconn_unix_test.go b/src/net/rawconn_unix_test.go index 75bbab8b27eeb4dbd19086b3ecdf252548bd7683..e6e1ad771a5a35489b54dbd05470f3a0dbf9546f 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/rpc/client.go b/src/net/rpc/client.go index 60bb2cc99f99bf8d983b013f32a245d9264e7a60..42d13519b1907ef434439014606d4d487a07577a 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 03225e3d0104b5277d8a0af2fea98be725676c02..ffc12faedae9c9656f85e59e8a940df9d3082f04 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") @@ -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)) diff --git a/src/net/rpc/debug.go b/src/net/rpc/debug.go index a1d799ff19a1424258dd18123664a6476c343293..9e499fd984de6560894c093f86e1525eebcecc28 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 667f839f580224fb572d541296c5fec59594bd9a..f4e1278d03ef5f167453adef4421081e4ea580dd 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 e6359bed5985cf02f899103f842a5bfa6f7e90dc..c473017d26d95656ddb49ade28874c42d99a89f3 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 40e4e6f2aa5c18b58c1e7913136c3b87cae69220..3ee4ddfef2ac2afe4d5799c1e097b0a0d4644867 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 074c5b9b0d7a5ecaf84aaef241cb29225a3a2ed4..d5207a42cf1036408e378ae87e87da8cf02fe945 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, @@ -221,17 +221,21 @@ 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) } -func (server *Server) register(rcvr interface{}, name string, useName bool) error { +// 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 any, name string, useName bool) error { s := new(service) s.typ = reflect.TypeOf(rcvr) s.rcvr = reflect.ValueOf(rcvr) @@ -252,13 +256,13 @@ 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 := "" // 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 { @@ -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,36 +300,36 @@ 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 } // Second arg must be a pointer. replyType := mtype.In(2) - if replyType.Kind() != reflect.Ptr { - if reportErr { + if replyType.Kind() != reflect.Pointer { + 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 @@ -340,7 +344,7 @@ func suitableMethods(typ reflect.Type, reportErr 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 @@ -397,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, @@ -552,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) @@ -632,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) } @@ -650,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 e5d7fe0c8f55e79c30ae41aeaecd116670964b90..dc5f5decc770b3db090e3339ff1308db42344cb2 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/sendfile_stub.go b/src/net/sendfile_stub.go index 5753bc02898742181c55fd7979f17ef6ed2422d5..7428da3127b10b22a763eb65b8b928fe56145c64 100644 --- a/src/net/sendfile_stub.go +++ b/src/net/sendfile_stub.go @@ -2,8 +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 || darwin || (js && wasm) || netbsd || openbsd -// +build aix darwin js,wasm netbsd openbsd +//go:build aix || (js && wasm) || netbsd || openbsd || ios package net diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go index 54e51fa0abc66e38a1646bd04cd443f82ef04833..6edfb67dd7dda9347ca009e7120c6a00282c556b 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 @@ -28,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) @@ -98,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) @@ -156,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 @@ -226,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() @@ -318,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/sendfile_unix_alt.go b/src/net/sendfile_unix_alt.go index 54667d672f87b405e2c599999664ce193fe575ff..f99af92bc80b6211747ddc92e75859340380f724 100644 --- a/src/net/sendfile_unix_alt.go +++ b/src/net/sendfile_unix_alt.go @@ -2,8 +2,7 @@ // 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 && !ios) || dragonfly || freebsd || solaris package net diff --git a/src/net/server_test.go b/src/net/server_test.go index 7cbf15229887155f05ac91092e3e4d079fa961bd..6796d7993e9c5bf8ca372995782be0b2474aebfa 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 @@ -78,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)) } @@ -126,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 { @@ -163,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)) } @@ -188,7 +181,11 @@ func TestUnixAndUnixpacketServer(t *testing.T) { } t.Fatal(err) } - defer os.Remove(c.LocalAddr().String()) + + if addr := c.LocalAddr(); addr != nil { + t.Logf("connected %s->%s", addr, lss[i].Listener.Addr()) + } + defer c.Close() trchs = append(trchs, make(chan error, 1)) go transceiver(c, []byte("UNIX AND UNIXPACKET SERVER TEST"), trchs[i]) @@ -267,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) } @@ -319,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) @@ -345,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/smtp/smtp.go b/src/net/smtp/smtp.go index 1a6864a0f2436caf5ad74a5aa05350d1f99c2f48..c1f00a04e1f9eb0ddb2481a17eaabd222943a965 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 @@ -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/smtp/smtp_test.go b/src/net/smtp/smtp_test.go index 55219372d278c7f4a38f0434534303947ab45e35..0f758f4a339414720dd23278a23920bc1e48cba2 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) diff --git a/src/net/sock_bsd.go b/src/net/sock_bsd.go index 4c883ada78f91ef2d9dcd16e9641d664ce6125d4..27daf722b53466318304097a043ae9e93d1431f4 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 6861c4bf635dcfb3fda8b7b1cc6a1cd8cf25e81f..56dab31b1466a18cb3584671c8e906460f455c16 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 9b1e7880aed4494b947ba57e1a76b92054f80da0..98a48229c755517e9eff597cae1dfa944feaf5c4 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 d804bfaacce3a0edbca43a53213f7ed952a45050..4b73e575fe3a3fd7a7e9dcb7f232ecd02cf57651 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 9d77cb569b938ebe3a22b87f935cda3f4a8044cd..c8e91936ade1d940969f52b1f0bf7b0188794e43 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 ee1f98b834cf3753de73a653a33fc0aca47e937f..ff998119808e48d67a2bfbdd8116f65768133d9f 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 50b9bfa0a78ea5da5b0a920f3397fdc0dc5a3567..645080f9885e5374fb0504745c6d6e5870c5cd4f 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 99b5277ed0a874c098ed936633f44d8dc4cad436..98e23714d9a267060dca78a2551110d6d57fd218 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 56022fd1a59e37ba7a00292b7488d5e8ebe6b940..3e9ba1ee7867e75746d460ab926055d1e668e35d 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 a2143aec2cba6787b9ed486d4e811a6f1994408f..22031df22c221a344627ac1122e7b79507331dd1 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 4175922cec5f6f7d013626c3a28a928d979a2d7f..2c993eb71953f67ff37fff0521140e06c42602e0 100644 --- a/src/net/sockoptip_stub.go +++ b/src/net/sockoptip_stub.go @@ -3,38 +3,31 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm 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 } diff --git a/src/net/splice_stub.go b/src/net/splice_stub.go index ce2e9046a9440f9506c808fdb9934bc42ffd2944..3cdadb11c5615f6fa628f87facfc61351da3b569 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 be13cc924d04f50536e75ec4ea075d55e7ad920d..fa14c95eb715335a96d7fccd117d6d9afde01b83 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 @@ -47,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 { @@ -104,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() @@ -141,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) } @@ -151,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 @@ -211,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 @@ -238,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) } @@ -248,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. @@ -285,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) @@ -297,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) @@ -328,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{}) @@ -346,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/sys_cloexec.go b/src/net/sys_cloexec.go index a32483e2df94e4101948501042aba46ef7790394..26eac5585a8a29ab301089883a35eba9001d3775 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.go b/src/net/tcpsock.go index 19a90143f34861be7efc3ddb6de3a102bef59391..6bad0e8f8bb93b70ffb3d6bfff53817e7f83f834 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" } @@ -81,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 { diff --git a/src/net/tcpsock_posix.go b/src/net/tcpsock_posix.go index 7c4523c5eea8ec6352728cc70cf9907728e716c7..ed6b18b5517eb1c38ac6921e05e4b26f3d11fc1e 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 9c9f1eae93d832e7f295badc182abe00368697a2..ae65788a73dc5ea73ee11af2f29740d84b45ebda 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 @@ -388,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) } @@ -627,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 { @@ -677,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) @@ -724,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) @@ -795,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 41bd229132d912883a18aefb1b24b6b56d2e59a2..b14670bc6728bef8c3cd2b63589a1f280fd0234d 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 @@ -23,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/tcpsockopt_posix.go b/src/net/tcpsockopt_posix.go index d08832adc04c98b0f8a772ad906dcc42ae193c8e..73754b1a0f7fe2c30dc5687f535f770912354b85 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 028d5fd29cff8ebda730b1e9eb7bf46c72fd2430..0fe91829c0e05a91b7d1442c459abb90b247078c 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 a945889e00e86f9cef70d2e1d356123a87ab6f64..bdcdc4023983944dbe39b8483786df7555418f8c 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/textproto/reader.go b/src/net/textproto/reader.go index 5c3084f8a7c9fd8be8eb93af87cb9e758bca1fa2..157c59b17accfb2a48ca5ace16bf1d214ebe388c 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/textproto/textproto.go b/src/net/textproto/textproto.go index 8fd781e7775745d247ffda98ca442904a9fa7f7a..cc1a847e4e1e47aa86921cf388ae372acd6b384a 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 33c146c02204042402c964e0b9f8d2fe38d513d8..2ece3f511b9864b33f4dbbf3dada1c1ff60765b8 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/timeout_test.go b/src/net/timeout_test.go index e1cf1467c36f00aca3bf254d9c0676a91398a173..032770dd8348f516fb71bc13dee1a5ec9c242ca7 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 @@ -93,53 +92,35 @@ 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() + ln := newLocalListener(t, "tcp") + 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) + } + }) } } @@ -163,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 @@ -219,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) @@ -265,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) @@ -318,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) @@ -370,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()) @@ -437,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) @@ -500,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 { @@ -548,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()) @@ -600,24 +557,10 @@ 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() - c1, err := newLocalPacketListener("udp") - if err != nil { - t.Fatal(err) - } + c1 := newLocalPacketListener(t, "udp") defer c1.Close() host, _, err := SplitHostPort(c1.LocalAddr().String()) @@ -625,47 +568,106 @@ 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++ } - } + }) } } -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 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 +) - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) +// 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 := newLocalListener(t, "tcp") defer ln.Close() c, err := Dial(ln.Addr().Network(), ln.Addr().String()) @@ -674,31 +676,54 @@ 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 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 = next + continue + } + + break } } func TestReadFromTimeoutFluctuation(t *testing.T) { - t.Parallel() - - 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()) @@ -707,36 +732,59 @@ 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 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 = next + continue + } + + break } } func TestWriteTimeoutFluctuation(t *testing.T) { - t.Parallel() - switch runtime.GOOS { case "plan9": 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()) @@ -745,25 +793,67 @@ 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 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 + // 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 { + // 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 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 = next + } + continue } + + break } } @@ -819,10 +909,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) @@ -954,10 +1041,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) @@ -984,10 +1068,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()) @@ -1037,10 +1118,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 @@ -1049,6 +1127,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.go b/src/net/udpsock.go index 70f2ce226aa7b149471b23432baf1d7fae3e62ea..6d29a39edfcfcb389401e6bba22841a5f6605390 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,24 @@ func ResolveUDPAddr(network, address string) (*UDPAddr, error) { return addrs.forResolve(network, address).(*UDPAddr), 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 { + return &UDPAddr{ + IP: addr.Addr().AsSlice(), + Zone: addr.Addr().Zone(), + Port: int(addr.Port()), + } +} + +// 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 { @@ -130,6 +163,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 @@ -138,8 +183,18 @@ 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) + if ap.IsValid() { + 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 { @@ -160,6 +215,18 @@ 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) { + 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. func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) { if !c.ok() { @@ -195,6 +262,18 @@ 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) { + 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}} } // DialUDP acts like Dial for UDP networks. diff --git a/src/net/udpsock_plan9.go b/src/net/udpsock_plan9.go index 1df293d1db93525d91938d8e5b291142ce9c3a6f..732a3b07eec0b42792f5155226f967e072c25464 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,27 @@ 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) 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 } func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { @@ -52,10 +72,18 @@ 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 } +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 96fb373ce770ca91a8a8dc0eec2f1712ca381ed1..654439767378a86bcb73ddd959eec7a57e4948c1 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -3,12 +3,12 @@ // 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 import ( "context" + "net/netip" "syscall" ) @@ -44,27 +44,68 @@ 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 } return n, addr, err } -func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, 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} - case *syscall.SockaddrInet6: - addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))} +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) { + 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.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)) } return } @@ -76,11 +117,49 @@ 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()} + } +} + +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()} } - return c.fd.writeTo(b, sa) } func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) { @@ -97,6 +176,32 @@ 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 + } + 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) + 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 { diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 0e8c3511c36e459258d617d7217b81d1b8ed6a3c..6f82554e56d0d4e66a834ff27bb11cc88cd5421e 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 @@ -286,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) } @@ -334,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} { @@ -370,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") @@ -407,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()) @@ -475,11 +462,98 @@ 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) + } + 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 { + 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.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 { b.Fatal(err) } + defer conn.Close() addr := conn.LocalAddr() buf := make([]byte, 8) b.ResetTimer() @@ -495,3 +569,61 @@ 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.ReadFromUDPAddrPort(buf) + if err != nil { + b.Fatal(err) + } + } +} + +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) + } + 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") + } +} diff --git a/src/net/unixsock_posix.go b/src/net/unixsock_posix.go index 99a89c827b8abbebf361141c42458e6c0c6c55f9..1b69df53bfd3256088bf9f8acfcd39d02dc6dbe1 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 716484cc6ce95704e6d817018f41387045a0c063..fa4fd7d9331f422bdad34e3efbb24786df5739f3 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 bb851b89c05bd395150e9cee60b272f2f882a076..6b0de875ad5c3f1cca2d50c84c7af60c5f23087f 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 329076183aece9894ee1e539bbdb0db5cd9a2cfc..b3d19fe73dda2891f8261d691a82e9f29eba80b8 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 a4d2fca69cefde72dc464f67c7f6008be73ea445..c3bfbf9af2f1f867509a1ad5e8130b16de8480ae 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 71092e88fb600f98f0b1f642d7e121475d0985f6..2fc9580cafb68f88108cf287443f563c7d94519b 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 @@ -26,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) @@ -77,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() @@ -127,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() @@ -175,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) @@ -220,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) @@ -249,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) @@ -260,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) @@ -311,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) @@ -369,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 29244f64710337f97c79068fe0c965da2d388211..d541d89f78c1e875dca9c1b90578aeca985968e6 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 @@ -46,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) @@ -57,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/url/example_test.go b/src/net/url/example_test.go index 476132a1c93aa0306de9469531c2664b20d8625c..a1913508f72fcec18f05f736824e90b8bc942605 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") @@ -28,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 { @@ -247,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.go b/src/net/url/url.go index 20de0f6f5178a1e9f4cb39ab7352973d44732bdf..f31aa08b5929db2880fd22ec735e2db3692cc222 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('/') } @@ -1109,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 63c8e695af765050f5bfa0c1db616d0cf905a7f9..664757b832af04ff05b603691089df3d5def5c65 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 { @@ -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"}, @@ -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) { @@ -2059,12 +2062,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/net/write_unix_test.go b/src/net/write_unix_test.go index f79f2d0865d559ebb358430d32956ea65e95d858..23e8befa92dc9ece8265eab762a9033f815c7771 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 bf40ca2023ac9e52902bf8514194a8c2852db0d1..18795a457ac1f6a4066fc6b72a827f282c43820d 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 @@ -187,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) diff --git a/src/net/writev_unix.go b/src/net/writev_unix.go index a0fedc2f99061df9424f712d55be2d65ec4c4bf9..51ab29dc312a170e9a14ff68db882af615f134a3 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 5589c9c68256b0a09cdaae143526c3d475d7b486..9b3871a3e866eef81e1e6e95571ca7e0cf82fd1e 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 @@ -28,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/endian_big.go b/src/os/endian_big.go index 0529dccd6f214325541430ab168839f6b45d1f43..0375e533726ef4f642465e6d686c64543382980e 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 6be6020f534229330d7a5e8d8517503279c7335e..10643a804e03b0d8014f9ebca02b4413ec577617 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_test.go b/src/os/env_test.go index 4b860157b4c24257cf5e4989b0941ced17a7b088..f8d56ef8e022fdd0e4edcf02b88f397a096fcba9 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) { @@ -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) + } + } +} diff --git a/src/os/env_unix_test.go b/src/os/env_unix_test.go index d45e1deb833897b52ca82c0fac8e90426c1f5808..75225d85476f22b920e5faa0593b1cdfc5bd36b5 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 580e915b73c3db1cf7a33005b143fee58f9ba62e..c8140461a4dd9fd2596c23a70a39456fe2ecb141 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 268b3a923ab1abc03563f18f7688b2d0042980b0..234f4eb6921fb5493946a8c676f0cb9b33095bf7 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 e45282a0fdb4778a934e5a0fd4c57ab89c09728d..81bccebedbba6edf814523779f5a4bcf3e05f07f 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 aa0c14b7d46e36b295497ab1164ad3a7e2ab8729..86c8a985bb3359af155eb91604edb16af92cd11d 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.go b/src/os/exec.go index bc75d4dd66c9103ccf27df5729baa074d4fa0cdd..9eb3166ecb764e6e9d282d9c6ff9e32d2ef28749 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() } @@ -162,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() } @@ -171,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 0c495755116f5254030d45284ea31515cadb8487..845b737e28fc773538b8c9701b44162245eda300 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() }() @@ -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_linux_test.go b/src/os/exec/exec_linux_test.go index 3cfa30ee72477ee3c89fa096656138ebe860834f..4a37c96e63a0ad66be60aff2e77a1a391a7c8f83 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 7b2c0c0c111b35edcb2c7639e6cd0a250db752bb..fd7fb42d36a4e92a67c94305f23ca2c68787ae8d 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_test.go b/src/os/exec/exec_test.go index d854e0de843d69eff3da155b0710812c412d068b..92992a6d664a6a3b61016a1b03f678e737a14445 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 } } } @@ -166,12 +152,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) } @@ -379,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() @@ -432,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) { @@ -794,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) } @@ -1048,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") @@ -1072,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 { diff --git a/src/os/exec/exec_unix.go b/src/os/exec/exec_unix.go index 467c069e1ca48cb7fca9ea887d293cc210d44c1e..c20f35276c66fb6fc42809aa79aff4a970007cc5 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 fbccffec0e9c9735388ee01d5c6a2f3510e5a3a4..8e31e47190feaf374ed0b6163f49e5b289018903 100644 --- a/src/os/exec/exec_windows_test.go +++ b/src/os/exec/exec_windows_test.go @@ -3,13 +3,13 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package exec_test import ( "io" "os" + "os/exec" "strconv" "syscall" "testing" @@ -41,3 +41,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/os/exec/internal/fdtest/exists_js.go b/src/os/exec/internal/fdtest/exists_js.go new file mode 100644 index 0000000000000000000000000000000000000000..a7ce33c74f4259a4e5cfce7b2d7158fe5931c974 --- /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 0000000000000000000000000000000000000000..8886e0602715ebcf3a5d59d854ec71f6cf0e0edc --- /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 0000000000000000000000000000000000000000..a02dddf7f7de5e0e7f989770477365aab99460a0 --- /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 0000000000000000000000000000000000000000..49f264cebdaad0a96f31349090d243d39c83b6c2 --- /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 0000000000000000000000000000000000000000..72b8ccfd23c47e8e04932822f72fbf4a5c4ff449 --- /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/lp_js.go b/src/os/exec/lp_js.go index 4eac25fe6f402177eb596ff6fe5637f57ef0cd3a..54ddc4d5b483bc6f0ef67bfb8ad2a8ded4e3bb8c 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 d1d246accf18b4c3379f198295be295e70428338..38b9fc7c27fefb34399d27c95b4f2a70341ccafa 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 9fded0eb0af37c501f2133ca8357825835dd3dbc..52e401e58016c10532c9b5960f073195b30f1525 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 a8c71831d8806e8e126162130ff118f5c1dd85b4..10cbfbd54abfee9950f6360d658ccdcd1d192b42 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. @@ -19,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) @@ -38,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) } diff --git a/src/os/exec_plan9.go b/src/os/exec_plan9.go index cc84f976696290ef79b4dfd138ac53ed62c7debe..69714ff79830d9b9e3bc702b4a8c1b73e9b7719d 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 e8736f7c54eaab44bd1d1a812c1d7112077ac48a..d61998469351711c13e0295db4e537022fadf615 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 @@ -88,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/exec_unix.go b/src/os/exec_unix.go index d1bbeb752987c597f40d9f03caf83860ededc304..250c5c6402e9573d70a60f24c96b059c749d187c 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 f14b3519fbe759864fe6b824fd201f69b20b824c..fa332bf1ed840a6494b244e2c035b26bb43673e8 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 625430ecfca1e53cb9af7fcc1c501eef286abcea..d6161bcb08bbecae79f716de1b53acc29ebe3ff2 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 ad7a4410dcdd03747b656befb5a12c5016535d49..8d8c83260f59ca6601be1499cedd522fd76b8fea 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 76ba0e6d085e5bac291c47374cd971c49d42e1ce..18348eab912aa0e440a5bb3c6cfd2e7bdc479fa4 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 039448b5573a920b97a8f68f17e293cd41273aec..3c2aeacf7da53f82e43ed698596ac2c4018adf78 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 10f8312831792c637f52b822c08b95ea541b304d..d4eb7a4fb146a9d1a678cef7afdc59d595bfa129 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 007ed2912933bbcde5fe99d1d877f89c5d790586..de70927961314c2f4e50025482ac4c97cd243178 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.go b/src/os/file.go index e717f171e72580330de5f8ced30de0a24edc331c..28231285542a19b8ffd6d545ffb5d460cc3c8fe1 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) { diff --git a/src/os/file_plan9.go b/src/os/file_plan9.go index 604aea607bcf304e4ac111fbdd4aeb4e3c596cc0..887e1c889232b3536c0e6db2483b42b66ac8b4bb 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 211f2a1798aba3fbe87a285d3b30d2f04f051fda..f34571d68d78ec05a5c81cfa05338d6c0871958c 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 @@ -17,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 { diff --git a/src/os/file_unix.go b/src/os/file_unix.go index a2531b9656278cac8e3bd4155b83e4813415bf1a..a38db189548551cc00688ef291a2f4cd8f736426 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_test.go b/src/os/os_test.go index 506f1fb0ee6071e513d96a6a9f21702e8f8afdfd..717330e86a2b7f46989a3a900d0ccea625422281 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) { @@ -1761,8 +1757,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/os_unix_test.go b/src/os/os_unix_test.go index 9b4c0ab290bc072a73df89696b1f1c4d05c3ff29..3ec3dee24ba6f3374e8a5b6001c7d453d8240757 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 db383594920e97db5f3342d53c9b335d2a218dde..d1ffe2c1877bdc3f92b5069460b11b2b9cb73b70 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 bf6d081db5b83c9cfe8e47d392fba4db71fd4eaa..7eb1350d025347dd37ce09810511ae3f8d0d5511 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 71b8cb8e25be5706532908826dfb25d5e6b768ed..354b35cc462ee71632c38bbcc9e7aeae7d73374d 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 097b32e7eb33cf0414a28209c681b399449e07ba..554d62111a570b6c65feae24ba3737ea68d1bb27 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_linux.go b/src/os/pipe_linux.go index acd7b88e1d45d70d5f29e197699d72ddfc74e081..52f4e21e7c6616e95ccacfa72b8d52efcf91e945 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/os/pipe_test.go b/src/os/pipe_test.go index 41a1e9c78aa36542a892392b63ae136cfd3403be..ab6d1ce2b61f577d8ba8210537f9be9df402dc2d 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 ffc598b0618987c1a9c5928c7de6896e11df63eb..14a495d9c0a59d66e2eff0f00633d0f007423404 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 8aebaf87a60760623531ffc402e12f0feeba3ab2..fd2038a2332a1688fc5061fc29132107edc5a27e 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 826760f3df65cc290470e171032e16a62c57b013..8b7d5fb8f9e35c88dbce07825c73e97614c1a64d 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 d04540bc63eb2ca8918021ae7faa854240b68f5d..da804c436f6978060ae975a79deace8af4572940 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 853e0eddfc8920478d2fd3f2f5735d845c88186b..a0332e8c3560e956a911f5bce45a736096cd6a5d 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 3f7795b8cf9558dfb4a1b0b573ae1eaee21cbc11..b279ee9491f6ca3aa726fb50b2df9ebcb9670911 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 8d2eac71035f2274f6e4df918c14c3745a539dd8..537febba553c6916c49314465ea66739e32d5258 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 e1e4509e2a723b9ae4df542a485703a7fde79b82..67bad66e0b2fa2a838ee0a7c6f2de43762aca6ca 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 7abe1ec5a0a5954464b92dc79cb497bc6feeec04..f70f108442bb07eb72fcfabfbace0136bd321340 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 649854b746c149e0dc2a9002f299b3b962a44e99..e6fb24c6a831be007e5dc011161cab2e084c585a 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 @@ -137,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...") diff --git a/src/os/signal/signal_unix.go b/src/os/signal/signal_unix.go index 9e241c43acef2c7137898f082a160ccdba50a608..e2e5c4ae970d48d75068fd05bd2f4a7143d0e585 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 3badf5ba575b24de3a77895dcee9e21a6e9ffc10..c3e9b5b5e53176fd443ee65176ce3a79ea1ae215 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_plan9.go b/src/os/stat_plan9.go index 57ae6fb0bbdf67c1ca4c49126b1af2b8a45a097e..e20accf191321cdc7d37e271e7f679742bb306f1 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/stat_unix.go b/src/os/stat_unix.go index 8c17805f71fc30622d193fbdf5dcfe0bbfb5e308..eb15db5453b785fd77b131bd8852de343bbe204d 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 ab23d8111d3b4e8bf8f2df3e21b84b59f9f87707..e71daf7c7494aba8c594fe6572dbbec70e04665d 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 9979b43e8e69d011470c91da9e4521cfbe7fe9f5..9a87fbde92c2ba6837c1149ea6f9fcfb52860608 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 1e245eb53a2d947f2b0d48252a59099c5e947fcc..e272c245717cbbf9e8fb985e457b19e6bd34ea65 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 4d6a64e8ebeaec86baadf818747eab59e825b504..4fd0e2d7c7dd128fc2a07efa39b2c9651a52afe2 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 e316eaf06c4f768920bffc582e647d7d7e546f4d..5ff39780e5e8fa54914add0f05999955d279f6a3 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 6d65e420f044ef5df3f606fb3b1aab93fbd57348..2ff58110d65bdf8eac448a14ddc0fc056a59093e 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_plan9.go b/src/os/types_plan9.go index 125da661b79de9307e5830d0e5867a46f769a62b..ccf4fd932e7a53e4498a6a94fff69e330e3f70fb 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 e9b8b8ba3ac7af2de64026385ee26881f21d8277..1b90a5a14157a9b6d8f03b6eff98ea166bd59abf 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 @@ -24,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 59bf5ca38143dca2480b779a39c8a82530a74996..5443dfedc8ca2113680b19639f6fd02e08de4994 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/cgo_listgroups_unix.go b/src/os/user/cgo_listgroups_unix.go new file mode 100644 index 0000000000000000000000000000000000000000..0d937da3345dcc4dd2260ebfbc9b5b22a28805b5 --- /dev/null +++ b/src/os/user/cgo_listgroups_unix.go @@ -0,0 +1,48 @@ +// 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 + +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/cgo_lookup_unix.go b/src/os/user/cgo_lookup_unix.go index abc9e9ce6d617d8c79e58b20c4774424eccde2a2..523269086e68f8ab32ccf8d930be68c55ab60f98 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 @@ -125,9 +122,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/cgo_unix_test.go b/src/os/user/cgo_unix_test.go index 9ec32b3a7889694953d795b8c811fd5500478970..6d16aa20b30ec827cdc9837bd7b65896f254d525 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 23d12e3247624e94e73f3aba3650f989be4b0f6b..db6fb87e23fb99f02dd3e72e24696ef6b02c5fb1 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 fd66961ccf716616648d8132413169672bc7e6da..104c2243df618cd7cedf33a663e9b3da37ec25b5 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_aix.go b/src/os/user/listgroups_aix.go deleted file mode 100644 index d2fdfdc6b1e3b7bf8624659d874b1dfcf9928e2c..0000000000000000000000000000000000000000 --- a/src/os/user/listgroups_aix.go +++ /dev/null @@ -1,14 +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" - -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 d25e0339b99593d909c012cbdc274de242f68dad..0000000000000000000000000000000000000000 --- a/src/os/user/listgroups_illumos.go +++ /dev/null @@ -1,18 +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" - -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 0000000000000000000000000000000000000000..4cf808b65decc046fcc43bf582fcaca3e3cfb1a4 --- /dev/null +++ b/src/os/user/listgroups_stub.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 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 38aa7653b054f6b2cb101b76865b4cc7aa75017d..fa2df4931c152e76144fcb30041947c8e3bc770e 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 0000000000000000000000000000000000000000..a9f79ec6bb06eaab342926fad67c038e8a8691e6 --- /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_android.go b/src/os/user/lookup_android.go index 151aab49c203d7a0f75b418941819aa69ad634e1..0ae31fd8189bf200fb3bbd52c98838cc80b8db1e 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_plan9.go b/src/os/user/lookup_plan9.go index 33ae3a6adf416c5d74523e5fba68b51c002e64c2..07939363e739c69440db6a81da8cf2625b7b3c3a 100644 --- a/src/os/user/lookup_plan9.go +++ b/src/os/user/lookup_plan9.go @@ -18,7 +18,9 @@ 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 c975a11964c11c83d7e6b721bc16a62ac00f14bf..ce1617d2507bdf24be8ccc3e82a521dd1297d58a 100644 --- a/src/os/user/lookup_stubs.go +++ b/src/os/user/lookup_stubs.go @@ -3,22 +3,16 @@ // 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 import ( - "errors" "fmt" "os" "runtime" "strconv" ) -func init() { - groupImplemented = false -} - func current() (*User, error) { uid := currentUID() // $USER and /etc/passwd may disagree; prefer the latter if we can get it. @@ -64,13 +58,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 97c611fad42fdf264af9bbef9259d10b5c2662a0..058dab1fb5ad6f817a5c2dcaa3cc12e752c7b0ff 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 @@ -18,17 +16,10 @@ import ( "strings" ) -const groupFile = "/etc/group" const userFile = "/etc/passwd" -var colon = []byte{':'} - -func init() { - groupImplemented = false -} - // 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 @@ -36,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. @@ -107,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 } @@ -154,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 } @@ -181,9 +172,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/os/user/lookup_unix_test.go b/src/os/user/lookup_unix_test.go index 060cfe186f5ced2d288611965300d1163bda5571..77917677fc1dc6c96fa8297f36497a4788b02312 100644 --- a/src/os/user/lookup_unix_test.go +++ b/src/os/user/lookup_unix_test.go @@ -3,36 +3,15 @@ // 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 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 +30,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 c1b8101c8629cb889efa0ca9208b3fae647cf853..0307d2ad6a12713e2e1339d92a5a0800adb621c0 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. */ @@ -20,9 +22,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 49920317bed93b9c7c32baea3d4f809c2127f538..80251749a7d670e4306aa60abce77583b728cdba 100644 --- a/src/os/user/user_test.go +++ b/src/os/user/user_test.go @@ -5,7 +5,6 @@ package user import ( - "runtime" "testing" ) @@ -56,10 +55,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 +72,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) @@ -127,14 +118,15 @@ func TestLookupGroup(t *testing.T) { } } -func TestGroupIds(t *testing.T) { - checkGroup(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") +func checkGroupList(t *testing.T) { + t.Helper() + if !groupListImplemented { + t.Skip("user: group list not implemented; skipping test") } +} + +func TestGroupIds(t *testing.T) { + checkGroupList(t) user, err := Current() if err != nil { t.Fatalf("Current(): %v", err) diff --git a/src/os/wait_unimp.go b/src/os/wait_unimp.go index 9bb85da80262b01fef4ce289c3b597caf7e4ba8e..721b9f9f7e33233a07d3c965504d7fdc6f0c707b 100644 --- a/src/os/wait_unimp.go +++ b/src/os/wait_unimp.go @@ -2,8 +2,11 @@ // 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 package os @@ -11,7 +14,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 45b370a802e8ae1ae14f76d138085e761d35c0b4..d395dac40b491b124a1756a190e320f170b0698d 100644 --- a/src/os/wait_wait6.go +++ b/src/os/wait_wait6.go @@ -2,8 +2,7 @@ // 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 package os diff --git a/src/os/wait_waitid.go b/src/os/wait_waitid.go index 44962c8534e086a6108f2489e5120f24602868fa..c0503b209c082ca4af3e2fce95da69c492e243e0 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 4ce10095e67360e21f62352d7bce451e93cc69ae..b364cf0608de2b2464fc7562bb47f4b81a092582 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 d72efcebe6130505a2c30f4ddeb081291a63b011..86146dba5be6cff43b7679779e90781b8cb32a7f 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_test.go b/src/path/filepath/path_test.go index bc5509b49cf1ab7e4820405a10a869d9b56edd61..55b27f1af88928df36c993dd28d500105676a35c 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_unix.go b/src/path/filepath/path_unix.go index d4b6f967a3f785f8c6021a52117a4791c80c7b9e..dcf1d187e7ae927f2cc4ff0b22e724c12f45bb70 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/path_windows.go b/src/path/filepath/path_windows.go index 445c868e41460456469d1459d868352fdaa3e5c2..b4d8ac33010e753bf158f3c7f550995e52c7e5e1 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 diff --git a/src/path/filepath/symlink_unix.go b/src/path/filepath/symlink_unix.go index 657945a81a3361797b7b4768b2fa8d721b0ccece..7bfe17e2fd1746dceec7951f60acf03d361d3db8 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.go b/src/plugin/plugin.go index 4a524bfa3f02ebe48b18886f6bf627e97287ad71..b2a0fbe3ea2f18578a05acb5c6d50217481646c5 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 aa85d4831ce84952aeb112d2a33f17b21caf0d11..c59f11ef719d609f39adf18d53505068e7c15935 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 @@ -103,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 { @@ -148,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/plugin/plugin_stubs.go b/src/plugin/plugin_stubs.go index 67855bed4ba82a5d56949dc34b5c0b6fc47b0863..2e9492e7c657e66d5a4c8483902095d495ff0a13 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 4ce912132c911f27219fb6d0f7057aeb1e33a50e..8185095f8580bdc039d4b555b377f8bf4ae8d74d 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/race.bash b/src/race.bash index 81fb4be60646b70cc0b7541beb82695d673a25e8..f795ec9b7b75f27976eea9ecec92144f627d8311 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 diff --git a/src/reflect/abi.go b/src/reflect/abi.go index 17b79a8394fad5b5f12afd581356a6c354cfa0b4..28204b81937fc3abbd464fd16657002cc1cd70c1 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 @@ -197,12 +198,12 @@ 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) 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. @@ -466,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/abi_test.go b/src/reflect/abi_test.go index 5a0130f7b452b988bae5cb1eea552c635236633d..f39eb5efeae914cf92dbf46a0939d42f64ab9d19 100644 --- a/src/reflect/abi_test.go +++ b/src/reflect/abi_test.go @@ -2,13 +2,13 @@ // 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 package reflect_test import ( "internal/abi" + "math" "math/rand" "reflect" "runtime" @@ -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, @@ -962,3 +962,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 eac27e886f21d6c8d8325d50ad5e9c615457d929..9c8434c22c953e41993531d6777f5895ca99bc46 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" @@ -28,7 +29,7 @@ import ( "unsafe" ) -var sink interface{} +var sink any func TestBool(t *testing.T) { v := ValueOf(true) @@ -46,7 +47,7 @@ type T struct { } type pair struct { - i interface{} + i any s string } @@ -335,6 +336,115 @@ func TestSetValue(t *testing.T) { } } +func TestMapIterSet(t *testing.T) { + m := make(map[string]any, 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() { + k.SetIterKey(iter) + e.SetIterValue(iter) + 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() { + k.SetIterKey(iter) + e.SetIterValue(iter) + } + })) + // Making a *MapIter allocates. This should be the only allocation. + if got != 1 { + t.Errorf("wanted 1 alloc, got %d", got) + } +} + +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 any + 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 } @@ -436,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 { @@ -581,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) @@ -594,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) @@ -610,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") @@ -810,7 +920,7 @@ type Basic struct { type NotBasic Basic type DeepEqualTest struct { - a, b interface{} + a, b any eq bool } @@ -824,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 @@ -842,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 } @@ -864,6 +974,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}, @@ -884,6 +997,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}, @@ -891,7 +1007,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}, @@ -906,9 +1021,12 @@ 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}, + {[]MyByte{1, 2, 3}, MyBytes{1, 2, 3}, false}, + {[]byte{1, 2, 3}, MyBytes{1, 2, 3}, false}, // Possible loops. {&loop1, &loop1, true}, @@ -1008,7 +1126,83 @@ func TestDeepEqualUnexportedMap(t *testing.T) { } } -func check2ndField(x interface{}, offs uintptr, t *testing.T) { +var deepEqualPerfTests = []struct { + x, y any +}{ + {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 any, offs uintptr, t *testing.T) { s := ValueOf(x) f := s.Type().Field(1) if f.Offset != offs { @@ -1041,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()) @@ -1058,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 }{}, @@ -1103,7 +1297,7 @@ func TestIsNil(t *testing.T) { NotNil(mi, t) var ii struct { - x interface{} + x any } Nil(ii, t) ii.x = 2 @@ -1119,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 @@ -1179,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}, @@ -1231,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) } } @@ -1780,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() @@ -2317,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) @@ -2566,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) @@ -2615,7 +2814,7 @@ func TestInterfaceSet(t *testing.T) { p := &Point{3, 4} var s struct { - I interface{} + I any P interface { Dist(int) int } @@ -2657,7 +2856,7 @@ func TestAnonymousFields(t *testing.T) { } type FTest struct { - s interface{} + s any name string index []int value int @@ -2888,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)), ""}, @@ -3024,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()) } } } @@ -3067,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()) } } @@ -3091,7 +3290,7 @@ func TestEmbeddedMethods(t *testing.T) { } } -type FuncDDD func(...interface{}) error +type FuncDDD func(...any) error func (f FuncDDD) M() {} @@ -3114,22 +3313,22 @@ 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{} + var x []any for i := 0; i < n; i++ { v := New(pt) p := new(*uintptr) @@ -3161,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) } }) } @@ -3251,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 @@ -3329,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) } } @@ -3376,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) } } @@ -3425,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") } @@ -3768,7 +3967,7 @@ func shouldPanic(expect string, f func()) { f() } -func isNonNil(x interface{}) { +func isNonNil(x any) { if x == nil { panic("nil interface") } @@ -3794,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() } @@ -4235,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))}, @@ -4387,8 +4586,17 @@ func TestConvertPanic(t *testing.T) { var gFloat32 float32 +const snan uint32 = 0x7f800001 + func TestConvertNaNs(t *testing.T) { - const snan uint32 = 0x7f800001 + // 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))) @@ -4425,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) { @@ -4475,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)) } @@ -4485,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 @@ -4612,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++ { @@ -4688,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] @@ -4706,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] @@ -4776,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++ { @@ -4966,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{ { @@ -5142,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++ { @@ -5407,8 +5615,8 @@ func TestStructOfWithInterface(t *testing.T) { }, { name: "StructI", - typ: PtrTo(TypeOf(StructI(want))), - val: ValueOf(func() interface{} { + typ: PointerTo(TypeOf(StructI(want))), + val: ValueOf(func() any { v := StructI(want) return &v }()), @@ -5416,8 +5624,8 @@ func TestStructOfWithInterface(t *testing.T) { }, { name: "StructIPtr", - typ: PtrTo(TypeOf(StructIPtr(want))), - val: ValueOf(func() interface{} { + typ: PointerTo(TypeOf(StructIPtr(want))), + val: ValueOf(func() any { v := StructIPtr(want) return &v }()), @@ -5505,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() @@ -5519,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() @@ -5535,7 +5743,7 @@ func TestStructOfWithInterface(t *testing.T) { { Name: "SettableStruct", Anonymous: true, - Type: PtrTo(TypeOf(SettableStruct{})), + Type: PointerTo(TypeOf(SettableStruct{})), }, { Name: "EmptyStruct", @@ -5679,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++ { @@ -5737,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++ { @@ -5775,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++ { @@ -5843,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)}, @@ -6270,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() @@ -6313,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 { @@ -6331,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() }() @@ -6466,10 +6697,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} @@ -6490,56 +6721,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, + typ: ValueOf(func(a map[int]int, b uintptr, c any) {}).Type(), + 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{}, @@ -6548,9 +6779,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 @@ -6610,7 +6841,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. @@ -6751,14 +6982,14 @@ 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)) - hdr := make([]byte, 8/PtrSize) + 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) } @@ -6772,7 +7003,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), @@ -6782,20 +7013,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))) } @@ -6820,7 +7051,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{}))) } @@ -6887,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 } @@ -6899,7 +7130,7 @@ var nameTests = []nameTest{ {(*func() D1)(nil), ""}, {(*<-chan D1)(nil), ""}, {(*chan<- D1)(nil), ""}, - {(*interface{})(nil), ""}, + {(*any)(nil), ""}, {(*interface { F() })(nil), ""}, @@ -6925,7 +7156,7 @@ func TestExported(t *testing.T) { type p3 p type exportTest struct { - v interface{} + v any want bool } exportTests := []exportTest{ @@ -7000,6 +7231,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 @@ -7013,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}, @@ -7182,6 +7460,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() { + kv.SetIterKey(iter) + seenk ^= kv.Uint() + kv.SetIterValue(iter) + 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() { @@ -7247,6 +7591,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} @@ -7295,4 +7649,122 @@ 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) + } +} + +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() { + v.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() { + v.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 any + 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) + } +} + +//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() }) + 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) { + m := ValueOf(Point{}).Method(1) + want := MethodValueCallCodePtr() + 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/asm_amd64.s b/src/reflect/asm_amd64.s index facf07516d8c2441058c7c032db482bd5a4d2c6b..d21d498063b55e382a1e473fcb5e6a501be88d36 100644 --- a/src/reflect/asm_amd64.s +++ b/src/reflect/asm_amd64.s @@ -24,15 +24,13 @@ // 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. 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,22 +46,20 @@ 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. // 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. 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) @@ -79,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 diff --git a/src/reflect/asm_arm64.s b/src/reflect/asm_arm64.s index 5fe88e27e400d24bb97d2c57c5f58c7d95248c46..5b9b3573fa2a7e721e482cfe61b91dbf25552e62 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/reflect/asm_mips64x.s b/src/reflect/asm_mips64x.s index 8d01c5fb7ed737c490a14a50ee81520ba4c8e21c..f21e34df1bc248080e94c77013f6d3edeb3b77a0 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 6ea82331084248bff8f45d6953d625c794be865a..636c8a5c71c3d701940e6d00d7acd7ccea90592e 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 d955e4110f8b789afaa0a90a3b25457a607bdf40..3b529be6853529a960bca62df456b07d77c1fb20 100644 --- a/src/reflect/asm_ppc64x.s +++ b/src/reflect/asm_ppc64x.s @@ -3,40 +3,81 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" #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/deepequal.go b/src/reflect/deepequal.go index d951d8d9997b36075b230c8d3ea1b647465c59db..eaab1012215379641b20233c77f3a3c058e3813d 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 @@ -35,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 @@ -53,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 @@ -99,9 +102,13 @@ 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. + 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 @@ -113,8 +120,8 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { return v1.IsNil() == v2.IsNil() } return deepValueEqual(v1.Elem(), v2.Elem(), visited) - case Ptr: - if v1.Pointer() == v2.Pointer() { + case Pointer: + if v1.UnsafePointer() == v2.UnsafePointer() { return true } return deepValueEqual(v1.Elem(), v2.Elem(), visited) @@ -132,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() { @@ -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) @@ -206,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 23c08e4950049ed44f818d1d118ef1892adb1ad9..3db971c3aeed7ab904fdc9cc93542383ef881b70 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. @@ -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 +} diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go index b6830a98020f54bc18f30e995c56f50f3412aef7..a5a3c1c27103c8cf6ebde103160e8740948de1c3 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,8 +23,6 @@ func IsRO(v Value) bool { var CallGC = &callGC -const PtrSize = 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 @@ -65,7 +64,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) @@ -89,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)) @@ -162,3 +161,5 @@ func SetArgRegs(ints, floats int, floatSize uintptr) (oldInts, oldFloats int, ol clearLayoutCache() return } + +var MethodValueCallCodePtr = methodValueCallCodePtr diff --git a/src/reflect/float32reg_generic.go b/src/reflect/float32reg_generic.go new file mode 100644 index 0000000000000000000000000000000000000000..307c0bb33c1c7c94bc33dd45d4f4f5e73d191c21 --- /dev/null +++ b/src/reflect/float32reg_generic.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 !ppc64 && !ppc64le + +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/float32reg_ppc64x.s b/src/reflect/float32reg_ppc64x.s new file mode 100644 index 0000000000000000000000000000000000000000..a4deb18427af0f81441a2e247fe7304facc471b7 --- /dev/null +++ b/src/reflect/float32reg_ppc64x.s @@ -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 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/makefunc.go b/src/reflect/makefunc.go index d53e68a3594a66de2fddde11860279931d1106f5..d0b0935cb8cb2944fadb591c04ff3b42f0207c05 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 := methodValueCallCodePtr() // methodValue contains a stack map for use by the runtime _, _, abi := funcLayout(ftyp, nil) @@ -138,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/set_test.go b/src/reflect/set_test.go index a633e6eee2b3e4e1cae1a128b86a815f719ec9fa..9ce0e09b824213037e8fa2a9ed929d79a41a70b2 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] @@ -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) } } @@ -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/stubs_ppc64x.go b/src/reflect/stubs_ppc64x.go new file mode 100644 index 0000000000000000000000000000000000000000..06c8bf5483bbe5baeee34a05c557e8c47613e1a6 --- /dev/null +++ b/src/reflect/stubs_ppc64x.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. + +//go:build ppc64le || ppc64 + +package reflect + +func archFloat32FromReg(reg uint64) float32 +func archFloat32ToReg(val float32) uint64 diff --git a/src/reflect/swapper.go b/src/reflect/swapper.go index 0cf40666b1e8e5c35a0920440b75f579e72c0a2e..745c7b9f4970ba411cc38412cc2b3723ed24b0fb 100644 --- a/src/reflect/swapper.go +++ b/src/reflect/swapper.go @@ -5,6 +5,7 @@ package reflect import ( + "internal/goarch" "internal/unsafeheader" "unsafe" ) @@ -13,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()}) @@ -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/tostring_test.go b/src/reflect/tostring_test.go index e416fd84da7bd15c355775a6843a034aa0b38178..193484a01bc4eb9548d8510db8a91bd92d367243 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 f672a7a5d5fc996e93a38c4c99fddd4fee76a687..6217291a3f2aed0ef46d57084c31eeda6ba61509 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -16,6 +16,7 @@ package reflect import ( + "internal/goarch" "internal/unsafeheader" "strconv" "sync" @@ -125,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 @@ -153,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. @@ -260,13 +261,16 @@ const ( Func Interface Map - Ptr + Pointer Slice String Struct UnsafePointer ) +// Ptr is the old name for the Pointer kind. +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. // @@ -657,7 +661,7 @@ var kindNames = []string{ Func: "func", Interface: "interface", Map: "map", - Ptr: "ptr", + Pointer: "ptr", Slice: "slice", String: "string", Struct: "struct", @@ -740,7 +744,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 @@ -944,7 +948,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: @@ -1264,7 +1268,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 @@ -1335,7 +1339,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() } } @@ -1410,17 +1414,24 @@ 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) } -// 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 { +// +// PtrTo is the old spelling of PointerTo. +// The two functions behave 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() } @@ -1447,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 @@ -1694,7 +1705,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: @@ -1865,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 @@ -1911,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 @@ -1924,13 +1935,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) @@ -1991,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) @@ -2135,7 +2146,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 @@ -2159,7 +2170,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. @@ -2216,10 +2227,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. @@ -2231,31 +2242,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 +2275,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype { } b := &rtype{ - align: ptrSize, + align: goarch.PtrSize, size: size, kind: uint8(Struct), ptrdata: ptrdata, @@ -2288,8 +2299,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 +2323,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). @@ -2349,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 @@ -2457,10 +2468,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()) } } @@ -2525,7 +2536,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 { @@ -2593,7 +2604,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{}{} @@ -2653,8 +2664,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) } @@ -2677,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 @@ -2759,7 +2770,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 @@ -2897,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 @@ -2936,11 +2947,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 +2961,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 +3074,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] @@ -3084,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{ @@ -3122,16 +3133,16 @@ 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(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 6f878eba5b0411af35e44d27ea6a64a2205248e7..dcc359dae480b7c0ece698cb169d83027c0eeec2 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -5,7 +5,9 @@ package reflect import ( + "errors" "internal/abi" + "internal/goarch" "internal/itoa" "internal/unsafeheader" "math" @@ -13,8 +15,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, @@ -91,10 +91,10 @@ 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 != 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 { @@ -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 @@ -275,7 +275,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. @@ -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") - memmove(unsafe.Pointer(®Args.Ints[st.ireg]), offset, st.size) - } 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) @@ -525,7 +529,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) + floatToReg(®Args, st.freg, st.size, offset) default: panic("unknown ABI part kind") } @@ -533,12 +537,21 @@ 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. 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) @@ -611,13 +624,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) + 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, unsafe.Pointer(®Args.Floats[st.freg]), st.size) + floatFromReg(®Args, st.freg, st.size, offset) case abiStepStack: panic("register-based return value has stack component") default: @@ -699,13 +712,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) + 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, unsafe.Pointer(®s.Floats[st.freg]), st.size) + floatFromReg(regs, st.freg, st.size, offset) case abiStepStack: panic("register-based return value has stack component") default: @@ -785,7 +798,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) + 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 @@ -800,7 +813,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) + floatToReg(regs, st.freg, st.size, offset) default: panic("unknown ABI part kind") } @@ -931,7 +944,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 { @@ -958,9 +971,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 @@ -986,9 +996,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) + intToReg(&methodRegs, mStep.ireg, mStep.size, from) case abiStepFloatReg: - memmove(unsafe.Pointer(&methodRegs.Floats[mStep.freg]), from, mStep.size) + floatToReg(&methodRegs, mStep.freg, mStep.size, from) default: panic("unexpected method step") } @@ -1004,9 +1014,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) + intFromReg(valueRegs, vStep.ireg, vStep.size, to) case abiStepFloatReg: - memmove(to, unsafe.Pointer(&valueRegs.Floats[vStep.freg]), vStep.size) + floatFromReg(valueRegs, vStep.freg, vStep.size, to) default: panic("unexpected value step") } @@ -1043,7 +1053,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. @@ -1126,6 +1136,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 { @@ -1141,17 +1161,17 @@ 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() 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)) } @@ -1160,9 +1180,24 @@ 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) { + // 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. @@ -1211,7 +1246,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]) @@ -1219,7 +1255,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") } @@ -1231,6 +1267,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. @@ -1253,6 +1312,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 { @@ -1290,7 +1359,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) { @@ -1314,6 +1383,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 { @@ -1347,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}) } @@ -1370,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() @@ -1410,7 +1489,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 } @@ -1458,7 +1537,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 @@ -1519,15 +1598,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 && tt.elem.size <= maxValSize { + 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{} } @@ -1553,11 +1638,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 @@ -1565,59 +1651,154 @@ 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 { +// 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") } - if mapiterkey(it.it) == nil { + 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()), mapiterkey(it.it)) + return copyVal(ktype, iter.m.flag.ro()|flag(ktype.Kind()), iterkey) } -// Value returns the value of the iterator's current map entry. -func (it *MapIter) Value() Value { - if it.it == nil { +// 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("reflect: Value.SetIterKey called before Next") + } + iterkey := mapiterkey(&iter.hiter) + if iterkey == nil { + panic("reflect: Value.SetIterKey called on exhausted iterator") + } + + v.mustBeAssignable() + var target unsafe.Pointer + 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()) | 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. +func (iter *MapIter) Value() Value { + if !iter.hiter.initialized() { panic("MapIter.Value called before Next") } - if mapiterkey(it.it) == nil { + 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()), mapiterelem(it.it)) + return copyVal(vtype, iter.m.flag.ro()|flag(vtype.Kind()), iterelem) +} + +// 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("reflect: Value.SetIterValue called before Next") + } + iterelem := mapiterelem(&iter.hiter) + if iterelem == nil { + panic("reflect: Value.SetIterValue called on exhausted iterator") + } + + v.mustBeAssignable() + var target unsafe.Pointer + 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()) | 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 -// 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.it == nil { - it.it = mapiterinit(it.m.typ, it.m.pointer()) +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 !iter.hiter.initialized() { + mapiterinit(iter.m.typ, iter.m.pointer(), &iter.hiter) } else { - if mapiterkey(it.it) == nil { + if mapiterkey(&iter.hiter) == nil { panic("MapIter.Next called on exhausted iterator") } - mapiternext(it.it) + mapiternext(&iter.hiter) + } + return mapiterkey(&iter.hiter) != nil +} + +// 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 iter to not to refer to any map, +// which may allow the previously iterated-over map to be garbage collected. +func (iter *MapIter) Reset(v Value) { + if v.IsValid() { + v.mustBe(Map) } - return mapiterkey(it.it) != nil + iter.m = v + iter.hiter = hiter{} } // MapRange returns a range iterator for a map. @@ -1780,7 +1961,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 @@ -1790,17 +1971,20 @@ 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. +// +// It's preferred to use uintptr(Value.UnsafePointer()) to get the equivalent result. func (v Value) Pointer() uintptr { - // TODO: deprecate k := v.kind() switch k { - case Ptr: + case Pointer: 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: @@ -1813,8 +1997,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. @@ -2029,6 +2212,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 && tt.elem.size <= maxValSize { + 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 { @@ -2274,6 +2476,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 { @@ -2301,11 +2513,12 @@ 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. +// +// It's preferred to 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}) } @@ -2315,6 +2528,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, 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 +// 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 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. + 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. + code := methodValueCallCodePtr() + return *(*unsafe.Pointer)(unsafe.Pointer(&code)) + } + 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. @@ -2370,11 +2634,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 } } } @@ -2681,7 +2946,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() @@ -2689,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{} } @@ -2733,7 +2998,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)") @@ -2745,14 +3010,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} } @@ -2786,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) } @@ -2821,10 +3086,9 @@ 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() - h := (*unsafeheader.Slice)(v.ptr) - if n > h.Len { + if n > v.Len() { return false } } @@ -2892,7 +3156,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 } @@ -2908,8 +3172,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 } @@ -3091,11 +3355,11 @@ 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)) } - return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Ptr)} + h := (*unsafeheader.Slice)(v.ptr) + return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Pointer)} } // convertOp: direct copy @@ -3118,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) } @@ -3160,25 +3424,32 @@ 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) -// 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 mapdelete_faststr(t *rtype, m unsafe.Pointer, key string) + +//go:noescape +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 @@ -3210,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 @@ -3242,10 +3513,12 @@ 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. -func escapes(x interface{}) { +func escapes(x any) { if dummy.b { dummy.x = x } @@ -3253,5 +3526,5 @@ func escapes(x interface{}) { var dummy struct { b bool - x interface{} + x any } diff --git a/src/reflect/visiblefields.go b/src/reflect/visiblefields.go index 1a2b53570bef857d37ac0aedd08572a4747d3a3f..9375faa11045a6b5b473b72dd189b654cd964276 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/reflect/visiblefields_test.go b/src/reflect/visiblefields_test.go index 915bbee867c60db0c491a97d822def430fa16213..fdedc21f738b57ab830ec91ea84418eaa4a371a9 100644 --- a/src/reflect/visiblefields_test.go +++ b/src/reflect/visiblefields_test.go @@ -6,6 +6,7 @@ package reflect_test import ( . "reflect" + "strings" "testing" ) @@ -16,7 +17,7 @@ type structField struct { var fieldsTests = []struct { testName string - val interface{} + val any expect []structField }{{ testName: "SimpleStruct", @@ -278,7 +279,7 @@ type RS3 struct { RS1 } -type M map[string]interface{} +type M map[string]any type Rec1 struct { *Rec2 @@ -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) + } +} diff --git a/src/regexp/all_test.go b/src/regexp/all_test.go index be7a2e7111876de6d6f7f6be2514556a587bfa87..c233cfa9eaac75fb1f33de6db2aa3b53887a9177 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/exec2_test.go b/src/regexp/exec2_test.go index 6444bc12f90ebdfd34d446c9973edbe01eb1f412..b6dac4a058f0cecdba4bca8f35fbd433c4c6a334 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/regexp/exec_test.go b/src/regexp/exec_test.go index 1f9a7a96e0c67d5eeb9b479b973dc0698f17f86e..5f8442668ca3c65dcc1f4be54bec12e693cb45b9 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/find_test.go b/src/regexp/find_test.go index 64c2239d905fdff2e26df72ba42b51cc1c85caca..2edbe9b86e61547d11c50040e8a39150378371ab 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 2f3ce6f9f6cb877f9e4eda1d7c3d427ca9b1f741..bc47f4c4a830da065ca5053227a97b0a53588ad0 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 b547a2ab97d71a8e26f427942d307d39ddfb28b6..af7259c9bfd2cbd0e2d9f3b1f587db97de612f35 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: @@ -922,23 +928,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 +972,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 7b4030935a7bb5056163af5794786cd6c6b727ec..06a92fb3d75322a89987d410b2f794c4039df242 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/regexp/syntax/prog.go b/src/regexp/syntax/prog.go index ae7a9a2fe0118a11f02451d32586193a10a08bce..8583f55e5421d88789cb7e036695d5244ec7a87b 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) } diff --git a/src/runtime/abi_test.go b/src/runtime/abi_test.go index f69d3a9d5012d6c3ce79968533348f2cabe05ddc..f9e8d701ceb88dcd92fe5b5f88f34c6563cfc942 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. @@ -79,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 39c742684216362c48013b8ecfb1446a7ae45d1f..5d7d1c77f4dbe3b3e32c2d0d82cb1332968df456 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -6,13 +6,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 { @@ -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) } @@ -300,7 +300,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 +321,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 @@ -337,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 @@ -345,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/asan.go b/src/runtime/asan.go new file mode 100644 index 0000000000000000000000000000000000000000..a22b56bb079e9c4c275aee7e5ee52d530911e401 --- /dev/null +++ b/src/runtime/asan.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. + +//go: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 0000000000000000000000000000000000000000..eb66b3aab54711f6865cc07b5e011df89fd3c2bc --- /dev/null +++ b/src/runtime/asan/asan.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 asan && linux && (arm64 || amd64) + +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) { + 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 0000000000000000000000000000000000000000..d5478d6bee87b48efebbdcba565b98f52243b9d0 --- /dev/null +++ b/src/runtime/asan0.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. + +//go: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 0000000000000000000000000000000000000000..e8de80399b7ca3a90f1e17e6a96030b38f3f2d9d --- /dev/null +++ b/src/runtime/asan_amd64.s @@ -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. + +//go: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 0000000000000000000000000000000000000000..acae200fb5ec894a006bf3754d89ce0cad433fd4 --- /dev/null +++ b/src/runtime/asan_arm64.s @@ -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. + +//go: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 diff --git a/src/runtime/asm.s b/src/runtime/asm.s index 72c744925d89aec9d1cc33a6eacf55f826866fcf..84d56de7dd85168084987b2ef7f47b48eaca6e36 100644 --- a/src/runtime/asm.s +++ b/src/runtime/asm.s @@ -4,15 +4,7 @@ #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 +TEXT ·sigpanic0(SB),NOSPLIT,$0-0 JMP ·sigpanic(SB) #endif diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index ec5ea58028bf0e5ad38b24792bd6d2fdaf1e9a4b..594cd5ed0d9592fad2a2fa38f71accd0b2ef6471 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 @@ -244,10 +240,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) @@ -584,26 +578,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) @@ -655,18 +629,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) @@ -860,19 +834,37 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0 // func cputicks() int64 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 - CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE done - CMPB runtime·lfenceBeforeRdtsc(SB), $1 - JNE mfence - LFENCE - JMP done -mfence: - MFENCE + // 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. +#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. + // 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 14f29e19647aa2d991cf623592411129ac3da14b..c08ae610fb7759527568d01690142d9142f14ea2 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -78,14 +78,81 @@ 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 + 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. @@ -99,13 +166,9 @@ 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 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,9 +176,8 @@ 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: +notintel: // Load EAX=1 cpuid flags MOVL $1, AX CPUID @@ -201,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) @@ -214,10 +324,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) @@ -225,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 @@ -279,7 +398,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 @@ -308,38 +426,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 @@ -467,9 +553,8 @@ 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 +TEXT ·spillArgs(SB),NOSPLIT,$0-0 MOVQ AX, 0(R12) MOVQ BX, 8(R12) MOVQ CX, 16(R12) @@ -497,7 +582,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 @@ -523,15 +608,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). @@ -588,7 +664,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 +672,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; \ @@ -664,31 +740,12 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 // compile barrier. RET -// func jmpdefer(fv *funcval, 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) // 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 @@ -731,22 +788,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 @@ -993,77 +1049,62 @@ 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 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 @@ -1100,11 +1141,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: @@ -1120,11 +1157,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: @@ -1154,11 +1187,7 @@ aes17to32: // combine results PXOR X3, X2 -#ifdef GOEXPERIMENT_regabiargs MOVQ X2, AX // return X2 -#else - MOVQ X2, (DX) -#endif RET aes33to64: @@ -1200,11 +1229,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: @@ -1286,15 +1311,9 @@ 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 - MOVQ X8, (DX) -#endif RET aes129plus: @@ -1410,41 +1429,24 @@ 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 - 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) @@ -1452,28 +1454,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) @@ -1596,10 +1586,10 @@ 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 -#ifdef GOEXPERIMENT_regabig +TEXT ·sigpanic0(SB),NOSPLIT,$0-0 get_tls(R14) MOVQ g(R14), R14 +#ifndef GOOS_plan9 XORPS X15, X15 #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. @@ -1956,146 +1940,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/asm_arm.s b/src/runtime/asm_arm.s index 6d3573d68fb0ef3b90462220cc36bd502090ef58..b47184e36bc9801e1c2c2080b9a9ef629122304a 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 $8, R13 MOVW $runtime·mainPC(SB), R0 - MOVW.W R0, -4(R13) - MOVW $8, R0 - MOVW.W R0, -4(R13) + MOVW R0, 4(R13) // arg 1: fn MOVW $0, R0 - MOVW.W R0, -4(R13) // push $0 as guard + MOVW R0, 0(R13) // dummy LR BL runtime·newproc(SB) - MOVW $12(R13), R13 // pop args and LR + ADD $8, R13 // pop args and LR // start this M BL runtime·mstart(SB) @@ -507,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) @@ -571,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 2d495397a8d0aea274a68290fe24584141f202b7..9e9d9314efc0b808badc0b27e1f55f30161453a5 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) @@ -103,7 +100,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 @@ -152,7 +149,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 +171,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) @@ -310,6 +317,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 +468,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 +495,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 @@ -440,12 +533,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 @@ -459,18 +554,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 @@ -484,75 +585,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 @@ -561,11 +676,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 @@ -575,7 +700,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] @@ -593,7 +718,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: @@ -604,7 +733,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] @@ -636,7 +765,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: @@ -657,7 +790,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 @@ -711,7 +844,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: @@ -732,12 +869,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 @@ -776,8 +913,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 @@ -830,7 +967,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 @@ -841,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) @@ -903,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 @@ -1052,7 +1177,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 @@ -1158,7 +1284,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 +1379,141 @@ 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 +#ifndef GOEXPERIMENT_regabiargs MOVD R0, x+0(FP) MOVD R1, 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 R0, x+0(FP) MOVD R1, 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 R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, 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 R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, 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 R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, 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 R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, 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 R0, x+0(FP) MOVD R1, 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 R0, x+0(FP) MOVD R1, 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 R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, 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 R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, 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 R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, 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 R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, 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 R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, 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 R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, 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 R0, x+0(FP) MOVD R1, 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 R0, x+0(FP) MOVD R1, 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 R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, y+8(FP) - JMP runtime·goPanicSliceConvert(SB) +#endif + JMP runtime·goPanicSliceConvert(SB) diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index d4d22801055157c1a4079ccce2142b6cfc928ba4..3597ebec57c74ffad714f5fdc751d55c94032531 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" @@ -63,12 +62,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) @@ -385,22 +383,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) @@ -441,8 +423,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. MOVV g_m(g), R5 + MOVV m_gsignal(R5), R6 + BEQ R6, g, g0 MOVV m_g0(R5), R6 BEQ R6, g, g0 diff --git a/src/runtime/asm_mipsx.s b/src/runtime/asm_mipsx.s index ea7edf20cf9f84fc21b38f81e66afe001d3a2030..4a086b8eb302cf167f028351012b052c9ab9b4b8 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" @@ -64,12 +63,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) @@ -383,22 +381,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) @@ -430,8 +412,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 942cc14f17d044d8705ca4343a042139c2176204..ae14213999534c9bf490f1cd5e8170d10a34fc46 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" @@ -94,9 +93,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) @@ -104,7 +102,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 @@ -166,8 +164,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) @@ -181,10 +185,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) @@ -429,6 +434,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; \ @@ -437,6 +444,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; \ @@ -453,11 +462,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 @@ -504,34 +514,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) @@ -570,9 +552,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 @@ -718,7 +699,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 @@ -804,15 +788,80 @@ 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) -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 @@ -890,7 +939,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 @@ -959,71 +1008,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/asm_riscv64.s b/src/runtime/asm_riscv64.s index ef7af4e10d8826861804362f3604310ca570a584..0e813189d4d21b7b56076efb1c55b93dde865f36 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) @@ -82,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 @@ -249,21 +248,6 @@ TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 MOV gobuf_pc(T0), T0 JALR ZERO, T0 -// func jmpdefer(fv *funcval, 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 @@ -326,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 @@ -644,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 @@ -663,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 @@ -677,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. @@ -712,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/asm_s390x.s b/src/runtime/asm_s390x.s index fb382716303b42a6647b729be116512d1355bedd..9159a673721ff3aad7928c446ebfb136dee8c51c 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) @@ -481,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) @@ -529,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 @@ -790,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. @@ -811,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 diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s index 33c335ba5af91bfde9c613cd164b095e03ea090f..d885da6e70f4398d36e04b7a4ac25613d749048d 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 @@ -194,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/atomic_mips64x.s b/src/runtime/atomic_mips64x.s index e2118e6a20b2538cbd0f0740316533837a8bed05..dd6380ce409e51e4b7076e060a0dd244a1ea70de 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 1eacd273b44154e06ff0b9cd19676d4d2e881757..ac255fe7e626382265c4f040c32c62916177d818 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 b63de2dbd311cd8396630938368ab93366f74a18..4742b6cf56789de50d90b5960f16301e06899482 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/auxv_none.go b/src/runtime/auxv_none.go index 3178f1a154cec36bafe578cb6379b2b452316454..5d473cab5ca482c1a16fc491caef8869e7a2717e 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.go b/src/runtime/cgo.go index 395d54a66e249b9fb6404bbffa9405df19393eed..d90468240df97cf131d64b19d563d19a0fb5b950 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/asm_riscv64.s b/src/runtime/cgo/asm_riscv64.s index fcd1d36ca84f8060c22489e69701e32494dd3252..45151bf02bacbea6c09e2e5a72ff9b29a209d570 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/callbacks_traceback.go b/src/runtime/cgo/callbacks_traceback.go index 7302c1eedfa64625d03e3eef41c35aef4605c882..dae31a8fcde16c79a3f9bc2f8bbbcf2068455b4f 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 cfa6fe86e2f360e04bba3edc5037b57387c56af9..36d70e34e2d39f0d4eb4cea3221d1fe5c2d31cbb 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 d56702ec704b2ac5e48805855d7556d6e1fab787..2d9f6245b5436096ae3105845c49b565c95d9ea1 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/gcc_sigaction.c b/src/runtime/cgo/gcc_sigaction.c index dd283151f17055c1061f1e2e850e62534de489e6..fcf1e50740e855765a2ff471472e8e3fdca53cc5 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(); diff --git a/src/runtime/cgo/handle.go b/src/runtime/cgo/handle.go index 720acca802c882c3b9877132ce0616c13c68b1d3..d711900d7990ee0e509f8db5b2e57523185949d1 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. @@ -70,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") @@ -83,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 738051a0ea13048d594c823a73f95de6dc83398c..b341c8e1e4463b3c4cead1f41c6727c56bf1bdc9 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/cgo/linux.go b/src/runtime/cgo/linux.go index 070d531beeb5d7cb12464bbc40837b1d4e36a6ee..1d6fe03917b819de0d0806605eed83a1d742874e 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 347ae6b363f0023f69cc146afe688278d4fe7b89..eae0a9e7cc859d2339fd48bed0b299e991ca564b 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 7e17d1fcd257069849d372845ecd0747489fdb8f..8a8018b7a89b5c8dd47eeb48990b4db314a616d5 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 f6215613c33419caa3e4ac6eb54249c307e9ca2c..872d02e3345bf3d7e0f7c6cb03492eda477f5370 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 e6e8040ae088c8dec9d3dfecc92ffc38664e034d..0f4780a945810819f27cdd31e538d894172f8cef 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 692fd2675f9475febed88480b615584c2d663fef..dc714f7ef4a3b08b06231a534591fa6b3c92a46e 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 17d26b4cc82f66569eed91fde308f41ec157b8c1..0cb25bdcdab3227b04b91fa0099dcbbfe9edaf5e 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 4dc92ea3211b87d39863c0da10c684cfed8a1786..97b962e40f69f80afe3ade4afe123a64710c6607 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 6099d1b746f80a3803c9e21c2d3a19125168b18c..a2e12f0f0e272eb65ff97a340e74308cc4e49b1b 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 @@ -28,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 { @@ -80,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/cgocall.go b/src/runtime/cgocall.go index 2626216f9584c5313aa64f953ad86575ca6a8724..a0c9560fd0f65538d89d1d42850c96b0bf0e82e9 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -85,6 +85,7 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -290,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) @@ -381,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 } @@ -480,7 +488,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 } @@ -560,7 +568,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 @@ -620,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/cgocheck.go b/src/runtime/cgocheck.go index 516045c16331dcb6ae20a13fd1e5fe4433a3f775..3acbadf803d0443b76e94388ae13f0a19e7eaf74 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/chan.go b/src/runtime/chan.go index f2a75b30f44596490a95c191139d0a1346394ec8..3cdb5dce117e3325fab2712bca53df1c704c0f7c 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/chan_test.go b/src/runtime/chan_test.go index c9ce3ac643184f99a6776aa2b81971b9ddcf992d..9471d4596c2e16c7cee87269723c8f3f94f681e4 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: @@ -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, diff --git a/src/runtime/checkptr_test.go b/src/runtime/checkptr_test.go index d5dd101adbe051164a9f23f858dfd46d99f29c66..15011ec494ad6c69b4958532613bdac9f65d87a0 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) @@ -55,3 +61,46 @@ 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) + + 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/cpuflags.go b/src/runtime/cpuflags.go index 5104650c5d73e824ee1bc79b9a0db171d23b1002..bbe93c5bea2d7e46d752b25ebfca2e7b1640bdd6 100644 --- a/src/runtime/cpuflags.go +++ b/src/runtime/cpuflags.go @@ -11,10 +11,10 @@ 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) offsetARMHasIDIVA = unsafe.Offsetof(cpu.ARM.HasIDIVA) diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go index e5d0193b9cbd4f5c10fc9ca0cac49464658ddec3..48cef46fe9c938bc1048ac59164f637a60423674 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" @@ -88,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() @@ -103,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) } @@ -166,8 +158,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 +168,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 @@ -208,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/cputicks.go b/src/runtime/cputicks.go index 7c926f4a2b88248e1fc3d6b2946b7b905553f991..2cf324033338d5d8699a32eabb8258be10493b4c 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 5729942cee3bfb36b0e0152059aa607155c23aef..058eae1c09c8144f6d2245d3a06ff6fe17b78737 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 @@ -65,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 { @@ -91,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 { @@ -125,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) } @@ -303,12 +301,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" { @@ -321,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) @@ -526,13 +519,38 @@ 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) + } + // No runtime errors like "runtime: unexpected return pc". + nowant := "runtime: " + if strings.Contains(got, nowant) { + t.Errorf("unexpectedly saw %q in output", nowant) + } +} + +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) } - nowant := "unexpected return pc" + 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.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got) + t.Errorf("did not see %q in output", want) } } @@ -591,17 +609,54 @@ 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) 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". + 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) + } } }) } } +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) { @@ -641,3 +696,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/crash_test.go b/src/runtime/crash_test.go index e0c0bac8926adc2bd5465fb8fdcb64b53dac441d..9b9ab4f3e1b0e97710b08e0495dad1e9bb492f88 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" @@ -14,11 +15,9 @@ import ( "path/filepath" "regexp" "runtime" - "strconv" "strings" "sync" "testing" - "time" ) var toRemove []string @@ -34,12 +33,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 { @@ -69,52 +69,19 @@ 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) + 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 +92,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) { @@ -417,7 +403,7 @@ func TestRuntimePanicWithRuntimeError(t *testing.T) { } } -func panicValue(fn func()) (recovered interface{}) { +func panicValue(fn func()) (recovered any) { defer func() { recovered = recover() }() @@ -691,6 +677,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", "illumos", "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") diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index 694cc3d138b73e42640b23f31785f8f67f005200..1eb10f9b60d93a9e9754d048a3e851990e78b89f 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 @@ -14,7 +13,7 @@ import ( "os" "os/exec" "runtime" - "strings" + "runtime/debug" "sync" "syscall" "testing" @@ -22,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 } } @@ -212,6 +207,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) @@ -245,9 +245,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") diff --git a/src/runtime/debug.go b/src/runtime/debug.go index 82deefa200cdf7cf68d1af6fe7cd48534423d1ca..2703a0ce019d3f41f88caefd1fe95b0ff0e1a222 100644 --- a/src/runtime/debug.go +++ b/src/runtime/debug.go @@ -61,3 +61,56 @@ 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 + } +} + +// 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 + } +} diff --git a/src/runtime/debug/garbage_test.go b/src/runtime/debug/garbage_test.go index 69e769ecf29d382f42a8fe417746afa952ab46af..7213bbe641dd6e38c64f2e504a23080ea25b3325 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,27 +88,71 @@ 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) } } var ( - setGCPercentBallast interface{} - setGCPercentSink interface{} + setGCPercentBallast any + setGCPercentSink any ) func TestSetGCPercent(t *testing.T) { diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go index 0381bdcc53951c64b6277277467ca896c8863941..14a496a8eb3390de381ad884cd9a049460d7391f 100644 --- a/src/runtime/debug/mod.go +++ b/src/runtime/debug/mod.go @@ -5,6 +5,9 @@ package debug import ( + "bytes" + "fmt" + "runtime" "strings" ) @@ -15,15 +18,32 @@ 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 + } + + // 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 -// 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 - 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. @@ -34,81 +54,151 @@ type Module struct { Replace *Module // replaced by this module } -func readBuildInfo(data string) (*BuildInfo, bool) { - if len(data) < 32 { - return nil, false +// 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. + // Key must not contain an equals sign, space, tab, or newline. + // Value must not contain newlines ('\n'). + Key, Value string +} + +func (bi *BuildInfo) MarshalText() ([]byte, error) { + buf := &bytes.Buffer{} + if bi.GoVersion != "" { + fmt.Fprintf(buf, "go\t%s\n", bi.GoVersion) } - data = data[16 : len(data)-16] + 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) + } + for _, s := range bi.Settings { + if strings.ContainsAny(s.Key, "= \t\n") { + return nil, fmt.Errorf("invalid build setting key %q", s.Key) + } + 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 +} - const ( - pathLine = "path\t" - modLine = "mod\t" - depLine = "dep\t" - repLine = "=>\t" +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) + } + }() + + var ( + 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") ) - 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(), except for go version. for len(data) > 0 { - i := strings.IndexByte(data, '\n') - if i < 0 { + line, data, ok = bytes.Cut(data, newline) + if !ok { break } - line, data = data[:i], data[i+1:] 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 + case bytes.HasPrefix(line, buildLine): + key, val, ok := strings.Cut(string(line[len(buildLine):]), "=") + if !ok { + return fmt.Errorf("invalid build line") + } + if key == "" { + return fmt.Errorf("empty key") + } + bi.Settings = append(bi.Settings, BuildSetting{Key: key, Value: val}) } + lineNum++ } - return info, true + return nil } diff --git a/src/runtime/debug/panic_test.go b/src/runtime/debug/panic_test.go index 65f9555f3761c55022fe2a4e8ddc7ebf58e1207e..ec5294ce4ce7662934c0d9063fd4a940cf6d8303 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 f74383457f36765f07fb3ed9e8a41d461b37e16d..5bb0c5cee3be8b122d2dad43ac88a2516324a425 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 @@ -35,12 +34,22 @@ 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 - // 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) 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 @@ -144,6 +153,7 @@ func TestDebugCall(t *testing.T) { x1: 42.0, } } + if _, err := runtime.InjectDebugCall(g, fn, ®s, args, debugCallTKill, false); err != nil { t.Fatal(err) } @@ -234,6 +244,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. @@ -257,6 +273,19 @@ 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 #10958 and #49370. + 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 defer atomic.StoreUint32(&stop, 1) diff --git a/src/runtime/debugcall.go b/src/runtime/debugcall.go index faddf59eed6b405b11709b69012d1148af9845c6..205971c4286876ec8206ad82e38ad08b9ba8bc5d 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 @@ -17,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 @@ -78,7 +77,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) @@ -112,7 +111,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/debuglog.go b/src/runtime/debuglog.go index 3ce3273f4def09707d447e42e79dea6ef1d6221c..75b91c4216d4cc401599e234435bc1e3f22f84d3 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 } @@ -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/debuglog_off.go b/src/runtime/debuglog_off.go index dd3815699929411a86170237417b1f4f6b6e0656..fa3be39c70f83449c279caa070bc07aaa6f718c4 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 2fcdbe70d14428e4f805f27b360a69e062661e90..b8150202251b36eeda9d16244e26da2aee0bab08 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/defer_test.go b/src/runtime/defer_test.go index fc961445975867b219812a9f6846790a5dc1996c..3a54951c318a58744735a1e4958d02b289f5fe2a 100644 --- a/src/runtime/defer_test.go +++ b/src/runtime/defer_test.go @@ -433,8 +433,86 @@ 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) } } + +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) { + *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/defs1_linux.go b/src/runtime/defs1_linux.go index df9c05dd5ed14702dabc22ff20e849c55c5bbf02..709f19e599910d2f8035a9956ef422cbdfa6f375 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 d016db7d027cf624c1cabe9553b6554ddf13aef6..41ad73576f15af06b2ca6fed5f347459c0a4eaa0 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 0a06aa2370725b4f8c354007a30bf673687200a3..99479aad06191ebb496c0bde0a5fa72c26c41f17 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 1605002ea20b9dbd21602efc904178c8742ff945..b794cd5de8b2da354cdd988cdbc14850daa42cc4 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 f84ff1160d0df517db666395640e55293c83a9e2..4e20c858411d9b344d9fb1032fda46a51b4f7941 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 f6b6dd2c09e58a6529f7f95bda3deb9c3bb659b6..805735bd0eef8c68f705bd9ecdaa5bf6c6b94455 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 2d41a97b5741b0630ed9027a93551d97cca31a84..59b81cf7136e24ba11bb42b7ec4e5f7813f60ca4 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 aca2bf9001e82a296cffcaa0707edce29ddc7a58..47a2e4d1232537d1a3606c7c62c93f92662afb3b 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 c258759549c8b96ace028097d6bc1c2431c1b820..9ba97c84596bd30d4e2eaa8110e5303c255d0561 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 022ef19427e1885ff19d37145b0e368c2350e540..fa94e388f45bbdd35341a678b6592dc5a44da4c1 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 @@ -58,6 +57,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 +111,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 +132,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 64a0fbcaaaa5f0ae539f8af1cf6ba5bb18013190..24fb58bbf8db695eae5bf9c2bf0da4aae80c2c06 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 @@ -28,6 +30,9 @@ const ( _SA_RESTORER = 0x4000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -79,6 +84,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 @@ -159,7 +168,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -167,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 @@ -212,11 +228,31 @@ 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 sigeventFields 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 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 1ae18a309bd70c6bb68d61f940b34a2827f050ed..36da22f8cedb78541dd89f4ea58d23f5831a8879 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 @@ -28,6 +30,9 @@ const ( _SA_RESTORER = 0x4000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -79,6 +84,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -121,7 +130,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -129,11 +138,38 @@ 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 +} + type itimerval struct { it_interval timeval it_value timeval } +type sigeventFields 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 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 5bc0916f8b66ca96e052d165797af86c34c2c2e1..13d06969e3dea42123ac2cccac491eb9f9f361b0 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 @@ -29,6 +31,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 +83,10 @@ const ( _O_NONBLOCK = 0x800 _O_CLOEXEC = 0x80000 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -153,12 +161,32 @@ 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 siginfo struct { +type sigeventFields 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 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 @@ -166,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 0690cd35b2e07e60f3a9eabcdda9578d73f73b36..f9ee9cbc35aea63a1b26993ecedcccea6ec70175 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 @@ -28,6 +30,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 +84,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -121,7 +130,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -129,11 +138,38 @@ 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 +} + type itimerval struct { it_interval timeval it_value timeval } +type sigeventFields 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 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 2cafad20cf98821c48004b51fccd6ef592b31de9..2601082ee1aef7e39323bf07316bd84c06dab18e 100644 --- a/src/runtime/defs_linux_mips64x.go +++ b/src/runtime/defs_linux_mips64x.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. //go:build (mips64 || mips64le) && linux -// +build mips64 mips64le -// +build linux package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -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 @@ -129,7 +136,7 @@ type sigactiont struct { sa_restorer uintptr } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_code int32 si_errno int32 @@ -138,11 +145,38 @@ 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 +} + type itimerval struct { it_interval timeval it_value timeval } +type sigeventFields 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 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 3a8dfe2e99008171588e5c238789ba53253dfe91..37651ef7e4330ebdd7086446e826b4e436e6bdd0 100644 --- a/src/runtime/defs_linux_mipsx.go +++ b/src/runtime/defs_linux_mipsx.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. //go:build (mips || mipsle) && linux -// +build mips mipsle -// +build linux package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -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 @@ -124,7 +131,7 @@ type sigactiont struct { sa_restorer uintptr } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_code int32 si_errno int32 @@ -132,11 +139,38 @@ 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 +} + type itimerval struct { it_interval timeval it_value timeval } +type sigeventFields 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 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 90b1dc1ff9d84edc4143b8793331c992965e9720..c7aa7234c195551d588c33fe09f6493d1eed6703 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 @@ -27,6 +29,9 @@ const ( _SA_ONSTACK = 0x8000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -78,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 @@ -122,7 +131,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -130,11 +139,38 @@ 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 +} + type itimerval struct { it_interval timeval it_value timeval } +type sigeventFields 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 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 90b1dc1ff9d84edc4143b8793331c992965e9720..c7aa7234c195551d588c33fe09f6493d1eed6703 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 @@ -27,6 +29,9 @@ const ( _SA_ONSTACK = 0x8000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -78,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 @@ -122,7 +131,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -130,11 +139,38 @@ 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 +} + type itimerval struct { it_interval timeval it_value timeval } +type sigeventFields 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 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 60da0fae000775df74809ce0d0c3e97acf5cad64..747e26bc4b6d9acfe7a14a59ee1a658b132c9170 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 @@ -29,6 +31,9 @@ const ( _SA_RESTORER = 0x0 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -80,6 +85,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -113,13 +122,15 @@ 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 siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -127,11 +138,38 @@ 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 +} + type itimerval struct { it_interval timeval it_value timeval } +type sigeventFields 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 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 fa289d531c074bbef57c54892d64c5082daa8889..740d8100c5dd449da5c6c5a43523cc7f598f5bef 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 @@ -28,6 +30,9 @@ const ( _SA_ONSTACK = 0x8000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -79,6 +84,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -118,7 +127,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -126,11 +135,38 @@ 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 +} + type itimerval struct { it_interval timeval it_value timeval } +type sigeventFields 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 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_netbsd.go b/src/runtime/defs_netbsd.go index 755992d18e03591b9e5df75864045f9eb0a6438a..df8bc579f2556ab2e6d42fbfc21c98ac7ce9a2cb 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 03c9c2de59e5e6376068cadb8852d4bc44e0951d..2943ea3f13eebf78e4039b0c6b3812531abacede 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 9fda1d7d22657269f7d046de9c69ab6be02a08e2..33d80ff53c0ccc5a0bccd99171f9d98b3d4cb078 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 e7f4f6cece7ac15f44a87016541a96e53267bab9..74b37527df66a6a0912008e43ed8861f64cf2bc5 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 8d323449d1c5d4330f0ce732b10be0e036f5bec6..ec7d82a33cf018e12316de8ad70c80c42e463680 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. @@ -26,6 +25,7 @@ package runtime #include #include #include +#include #include */ import "C" diff --git a/src/runtime/defs_plan9_386.go b/src/runtime/defs_plan9_386.go index 49129b3c3fcb1c675f26c89426b27ebb8a0d0624..428044df6871d71823a5f18edd745e1fb749eda9 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 00995630341a81c09cd28eaab16a31942532fd48..15a27fc7db9e5110991e4dcf282ed590b2171d9a 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/defs_solaris.go b/src/runtime/defs_solaris.go index e644f9c6ddd5afc1a8cec2098b869286b60cf237..ec16c9dcce94afa5cd9b5d4a7d8daae5c124071c 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 a0b38319a5ddcaf051211fdb5b19ad95cec59940..56e4b38c5e43842747ee534feee62acd349e27db 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/duff_arm64.s b/src/runtime/duff_arm64.s index 128b076af9db658b41847080c5fa72e35d7eecc6..33c4905078d242502ac00743a8b705f3ce16e23b 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/duff_mips64x.s b/src/runtime/duff_mips64x.s index a897d7fd9bf25e073f0eb5fd1bad22c0a7b35917..3a8524c78bfe1ac0265796f22276a79b703b9168 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 d4e3b409d24b9d911e8f8ff332c6aec52a187427..a3caaa881728a05d33c2cf64e23fdeea67823e34 100644 --- a/src/runtime/duff_ppc64x.s +++ b/src/runtime/duff_ppc64x.s @@ -3,140 +3,395 @@ // See mkduff.go for comments. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #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/env_posix.go b/src/runtime/env_posix.go index 95517b2a958808e26e50d7768b7c8364aa10e6ae..44086c1d6341b47c8eca577db42b639231b5e1f2 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/error.go b/src/runtime/error.go index 91f83ae126405c4f2915c9364d6305d811d794f8..43114f092e1cdd78e62d0565ae8e5ebac8ea0bd5 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_regabiargs_off_test.go b/src/runtime/export_debug_regabiargs_off_test.go index 5009003d27d7cbfed6a0dd7b6c65e317ab7f1a37..81f73925d58c2f6eb72803e2fc1e5afb2c72f7a2 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 e1b72efd0f765ed6087eb6f9d0df3e47b27e2911..7d1ab6888e63e83fb3376fb0ae252a23567d360c 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 fe4c9045c107ebc01c0b25548d2e0c397397136a..19a9ec135fac0f8d2086f3b6b350c7049d103aa3 100644 --- a/src/runtime/export_debug_test.go +++ b/src/runtime/export_debug_test.go @@ -3,13 +3,12 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux -// +build amd64,linux package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -23,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") } @@ -97,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 @@ -108,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 { @@ -115,7 +118,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. @@ -125,7 +128,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: @@ -142,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 @@ -166,7 +173,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 +189,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_debuglog_test.go b/src/runtime/export_debuglog_test.go index 8cd943b43822e4d65e881f41c124ca603473927e..1a9074e64641344a97adb7db0627a623129af45e 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_futex_test.go b/src/runtime/export_futex_test.go index 34c970d6d2d337d065450a8a51647ab791e282fc..03157d8eed3e612c34ec6fd0222acf49233fa235 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_linux_test.go b/src/runtime/export_linux_test.go index b7c901f238ff29479ef2f4c8fa3466e62540f0c2..dea94a934cef6665d72dff6cbfc1b02563f2874b 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/export_mmap_test.go b/src/runtime/export_mmap_test.go index bf4a81589916cc55d68d566a3157875cbf93eae1..f9c3229316a1fa2f83a7589763ce53aa57c1b512 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 26d8b7d185948aef22540176d5be6a0abc41961e..bdf39c60dfcf72c0577d4315b7e4aeb1d6a7d965 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 a0c6c0440d8d94447157f28f762bc1587ca7ab09..0583039982ebbc909af45356c4770f8311a1d5f2 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_test.go b/src/runtime/export_test.go index c8d01fbb1574de6b78faff16ed63b8d8c7362d52..3c8f9eb49b62283c842cc28df4cc110ad1135c1b 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -7,6 +7,8 @@ package runtime import ( + "internal/goarch" + "internal/goos" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -27,8 +29,6 @@ var Exitsyscall = exitsyscall var LockedOSThread = lockedOSThread var Xadduintptr = atomic.Xadduintptr -var FuncPC = funcPC - var Fastlog2 = fastlog2 var Atoi = atoi @@ -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) }) @@ -147,40 +147,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; { } @@ -210,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) { @@ -228,11 +216,9 @@ var Write = write func Envs() []string { return envs } func SetEnvs(e []string) { envs = e } -var BigEndian = sys.BigEndian - // For benchmarking. -func BenchSetType(n int, x interface{}) { +func BenchSetType(n int, x any) { e := *efaceOf(&x) t := e._type var size uintptr @@ -259,7 +245,7 @@ func BenchSetType(n int, x interface{}) { }) } -const PtrSize = sys.PtrSize +const PtrSize = goarch.PtrSize var ForceGCPeriod = &forcegcperiod @@ -277,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 { @@ -560,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< 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) @@ -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)))) } @@ -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 { @@ -531,7 +532,7 @@ func dumpparams() { } dumpint(uint64(arenaStart)) dumpint(uint64(arenaEnd)) - dumpstr(sys.GOARCH) + dumpstr(goarch.GOARCH) dumpstr(buildVersion) dumpint(uint64(ncpu)) } @@ -630,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) @@ -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 cd5fead9990cbfe2c98cfd291620c16b14f59589..a4d56dd33bccfb8bddad7aad332758a875ac0782 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -5,8 +5,9 @@ package runtime import ( + "internal/abi" + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "unsafe" ) @@ -63,7 +64,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 @@ -100,7 +101,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 @@ -133,7 +134,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. @@ -161,7 +162,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 @@ -295,11 +296,11 @@ type ( ) var ( - uint16Eface interface{} = uint16InterfacePtr(0) - uint32Eface interface{} = uint32InterfacePtr(0) - uint64Eface interface{} = uint64InterfacePtr(0) - stringEface interface{} = stringInterfacePtr("") - sliceEface interface{} = sliceInterfacePtr(nil) + uint16Eface any = uint16InterfacePtr(0) + uint32Eface any = uint32InterfacePtr(0) + uint64Eface any = uint64InterfacePtr(0) + stringEface any = stringInterfacePtr("") + sliceEface any = sliceInterfacePtr(nil) uint16Type *_type = efaceOf(&uint16Eface)._type uint32Type *_type = efaceOf(&uint32Eface)._type @@ -315,26 +316,43 @@ 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(), funcPC(convT2E)) + raceReadObjectPC(t, v, getcallerpc(), abi.FuncPCABIInternal(convT)) } if msanenabled { - msanread(elem, t.size) + msanread(v, t.size) + } + if asanenabled { + asanread(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) + } + if asanenabled { + asanread(v, t.size) + } + + x := mallocgc(t.size, t, false) + memmove(x, v, t.size) + return x } 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 { @@ -347,7 +365,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 { @@ -388,63 +406,16 @@ func convTslice(val []byte) (x unsafe.Pointer) { return } -func convT2Enoptr(t *_type, elem unsafe.Pointer) (e eface) { - if raceenabled { - raceReadObjectPC(t, elem, getcallerpc(), funcPC(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(), funcPC(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(), funcPC(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 { @@ -511,7 +482,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/iface_test.go b/src/runtime/iface_test.go index 4fab6c968a5fa43f6f680820a645d831392be0fa..06f6eeb95246379a336e39dd2e16856dfff16cf2 100644 --- a/src/runtime/iface_test.go +++ b/src/runtime/iface_test.go @@ -44,8 +44,8 @@ func (Tstr) Method1() {} func (Tslice) Method1() {} var ( - e interface{} - e_ interface{} + e any + e_ any i1 I1 i2 I2 ts TS @@ -196,7 +196,7 @@ func BenchmarkAssertI2I(b *testing.B) { func BenchmarkAssertI2E(b *testing.B) { i1 = tm for i := 0; i < b.N; i++ { - e = i1.(interface{}) + e = i1.(any) } } @@ -224,33 +224,33 @@ func BenchmarkAssertE2T2Blank(b *testing.B) { func BenchmarkAssertI2E2(b *testing.B) { i1 = tm for i := 0; i < b.N; i++ { - e, ok = i1.(interface{}) + e, ok = i1.(any) } } func BenchmarkAssertI2E2Blank(b *testing.B) { i1 = tm for i := 0; i < b.N; i++ { - _, ok = i1.(interface{}) + _, ok = i1.(any) } } func BenchmarkAssertE2E2(b *testing.B) { e = tm for i := 0; i < b.N; i++ { - e_, ok = e.(interface{}) + e_, ok = e.(any) } } func BenchmarkAssertE2E2Blank(b *testing.B) { e = tm for i := 0; i < b.N; i++ { - _, ok = e.(interface{}) + _, ok = e.(any) } } func TestNonEscapingConvT2E(t *testing.T) { - m := make(map[interface{}]bool) + m := make(map[any]bool) m[42] = true if !m[42] { t.Fatalf("42 is not present in the map") diff --git a/src/runtime/internal/atomic/atomic_386.go b/src/runtime/internal/atomic/atomic_386.go index d4aed6b6717da97ab96463b58f7f15d95b8d4ea4..27a77ec37a90e8216ea0410451374b718cdc8df5 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 2e9374ca269dd63a7a0c809f5d9ab245b5be19ea..e2539b6c7ec5e7f070ae7e48483c2ae4abdc7dcd 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 dbb1796ec0941abc9820b53763f77b93565f088b..459fb9978db30afff6a0c5ea52798f9c385ee18b 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 5b407ebc7a5918006993978db2360a5f4570bd03..1e12b83801dba27180e78026adc2eb76ead3a088 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_mips64x.s b/src/runtime/internal/atomic/atomic_mips64x.s index fedfc4a175cc35c460313c99d0756ae3b89f6677..b4411d87da65b5b68b9e6aa6157b92ec75c3c7fe 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.go b/src/runtime/internal/atomic/atomic_mipsx.go index 80cd65b33388ab4e432d2d85499045857eb65937..e552e5749528122aaafb4d62c448dc59ce6ad42b 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_mipsx.s b/src/runtime/internal/atomic/atomic_mipsx.s index c0835d66ed886acfbad9d82376c994676490097c..390e9ce7acc386f74c16ead53cfcdf37e4703965 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.go b/src/runtime/internal/atomic/atomic_ppc64x.go index 98101e3287823a0807a9bd5b204e82bf76a607c2..998d16e3f6862dcfae609432932ffe6dbf57cbe5 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/atomic_ppc64x.s b/src/runtime/internal/atomic/atomic_ppc64x.s index 226b3b62162ca8e1f58197b189c0c01fbf992464..04f0eadd065e6fb28519bb80fd304d95b9445581 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/atomic_test.go b/src/runtime/internal/atomic/atomic_test.go index c9c2eba248cf4221b3c5cad1d4d3b577117a60f9..2ae60b8507ef5831e2d5345514224696c0b85623 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/internal/atomic/bench_test.go b/src/runtime/internal/atomic/bench_test.go index 2476c06c52afbdfb24b702bdd87c9aeeb817a9fb..efc0531a0d3fd64cf234a1d9c18c7a0409478e45 100644 --- a/src/runtime/internal/atomic/bench_test.go +++ b/src/runtime/internal/atomic/bench_test.go @@ -9,7 +9,7 @@ import ( "testing" ) -var sink interface{} +var sink any func BenchmarkAtomicLoad64(b *testing.B) { var x uint64 diff --git a/src/runtime/internal/atomic/doc.go b/src/runtime/internal/atomic/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..08e6b6ce0bc88cb5597f6548bacd0eb19027bbfd --- /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/stubs.go b/src/runtime/internal/atomic/stubs.go index e7544ba4484f079143149056cec80021843ef127..7df8d9c86329ee49a3abd1f069d66608cb4ebd6d 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/sys_nonlinux_arm.s b/src/runtime/internal/atomic/sys_nonlinux_arm.s index 04036ca9702da4ce1d25cb16a8f4dcdb64be398c..b55bf908a260560d758e3d912cf987bbdb0e71b5 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/internal/atomic/types.go b/src/runtime/internal/atomic/types.go new file mode 100644 index 0000000000000000000000000000000000000000..1a240d7c9180863a63ee51c68a84fef4ec6dd35f --- /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 0000000000000000000000000000000000000000..43c1ba2709639dece82b4ef01cd1b168f2cf2524 --- /dev/null +++ b/src/runtime/internal/atomic/types_64bit.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 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) +} diff --git a/src/runtime/internal/math/math.go b/src/runtime/internal/math/math.go index b6bd12d3e8b66d5908b5c2d0da0bfe0d051ff263..c3fac366be0210979ce9beee890eb5394df909f5 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/internal/sys/consts.go b/src/runtime/internal/sys/consts.go new file mode 100644 index 0000000000000000000000000000000000000000..fffcf81d1f3b398d657ef9a7a1ff9fc1d764a23c --- /dev/null +++ b/src/runtime/internal/sys/consts.go @@ -0,0 +1,34 @@ +// 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" +) + +// AIX requires a larger stack for syscalls. +const StackGuardMultiplier = StackGuardMultiplierDefault*(1-goos.IsAix) + 2*goos.IsAix + +// 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 diff --git a/src/runtime/internal/sys/intrinsics.go b/src/runtime/internal/sys/intrinsics.go index e76d8dd064616a2866047dbb40c0408c40d70eb1..5af49011e9e65549e10829b6358617a0c6b20172 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_common.go b/src/runtime/internal/sys/intrinsics_common.go index 818d75ecc53ee6e8d5b2dd0639125b7966da7f75..48d9759ca9c54c77074cd98a8506fb3b24230b70 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/internal/sys/intrinsics_stubs.go b/src/runtime/internal/sys/intrinsics_stubs.go index bf1494d48aac7b787cdf381d7ba70c6f04876be5..a020652f7604b39c40798983b66fcfd03e210f9a 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/internal/sys/sys.go b/src/runtime/internal/sys/sys.go index 9d9ac4507f66447037acc3599f70640583a97cf4..694101d36fda4133c60640b714437198e35dce60 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 diff --git a/src/runtime/internal/sys/zgoarch_386.go b/src/runtime/internal/sys/zgoarch_386.go deleted file mode 100644 index 5b189e7e738f469258c7595343f0cf89cb09b73d..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_386.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build 386 -// +build 386 - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_amd64.go b/src/runtime/internal/sys/zgoarch_amd64.go deleted file mode 100644 index 312977d07923f85ea9e6b575162abdf7b0305509..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_amd64.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build amd64 -// +build amd64 - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_arm.go b/src/runtime/internal/sys/zgoarch_arm.go deleted file mode 100644 index 5781870324e0b900a42f890b6c3a4366330ae13f..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_arm.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build arm -// +build arm - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_arm64.go b/src/runtime/internal/sys/zgoarch_arm64.go deleted file mode 100644 index f72a1f2161c1df8713b0c84e1eea36c2bd8b7960..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_arm64.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build arm64 -// +build arm64 - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_arm64be.go b/src/runtime/internal/sys/zgoarch_arm64be.go deleted file mode 100644 index e8056460587ca1d55b176f97689e9e7f327a80e2..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_arm64be.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build arm64be -// +build arm64be - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_armbe.go b/src/runtime/internal/sys/zgoarch_armbe.go deleted file mode 100644 index d8d4e56d9a4e35cfdc7231b094f38b7538a2301b..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_armbe.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build armbe -// +build armbe - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_loong64.go b/src/runtime/internal/sys/zgoarch_loong64.go deleted file mode 100644 index 6f35eb44a3b8a6717266534b97fbc0fc7d1f7e13..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_loong64.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build loong64 -// +build loong64 - -package sys - -const GOARCH = `loong64` - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_mips.go b/src/runtime/internal/sys/zgoarch_mips.go deleted file mode 100644 index bd58a92a0e4e93f513f829e6827dbfee804f7f9c..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_mips.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build mips -// +build mips - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_mips64.go b/src/runtime/internal/sys/zgoarch_mips64.go deleted file mode 100644 index 8e4a3dcd526d854958bda84dc279c28530e0a87a..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_mips64.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build mips64 -// +build mips64 - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_mips64le.go b/src/runtime/internal/sys/zgoarch_mips64le.go deleted file mode 100644 index d8e00339ea81aa6f485d7e9f7424c6a9f9f6e5dc..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_mips64le.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build mips64le -// +build mips64le - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_mips64p32.go b/src/runtime/internal/sys/zgoarch_mips64p32.go deleted file mode 100644 index 8549cc0ba3443fa808cb9982b84047974767a53d..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_mips64p32.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build mips64p32 -// +build mips64p32 - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_mips64p32le.go b/src/runtime/internal/sys/zgoarch_mips64p32le.go deleted file mode 100644 index 667b6fe514b0bd4c0c324edd77a76aa266f11105..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_mips64p32le.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build mips64p32le -// +build mips64p32le - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_mipsle.go b/src/runtime/internal/sys/zgoarch_mipsle.go deleted file mode 100644 index 8bedb2bb9019699e4b8e992f83c9f7b4ad178f18..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_mipsle.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build mipsle -// +build mipsle - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_ppc.go b/src/runtime/internal/sys/zgoarch_ppc.go deleted file mode 100644 index fe2196a32789e51b4b90dde92ab6c45dea0edcc9..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_ppc.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build ppc -// +build ppc - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_ppc64.go b/src/runtime/internal/sys/zgoarch_ppc64.go deleted file mode 100644 index bd7cc43de3974d2041c98e87d3041dd62cbfa608..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_ppc64.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build ppc64 -// +build ppc64 - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_ppc64le.go b/src/runtime/internal/sys/zgoarch_ppc64le.go deleted file mode 100644 index e101892401650d3cfd342b47b2db890fc911c246..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_ppc64le.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build ppc64le -// +build ppc64le - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_riscv.go b/src/runtime/internal/sys/zgoarch_riscv.go deleted file mode 100644 index 559f86071a7ea83258d0b28b50615f4648e8c12b..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_riscv.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build riscv -// +build riscv - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_riscv64.go b/src/runtime/internal/sys/zgoarch_riscv64.go deleted file mode 100644 index 8485a94b3dd910dd00e79aee3a4cd73c9b2e8ae2..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_riscv64.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build riscv64 -// +build riscv64 - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_s390.go b/src/runtime/internal/sys/zgoarch_s390.go deleted file mode 100644 index 4c4569e3762159cc8b313628a7a71eacc798f019..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_s390.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build s390 -// +build s390 - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_s390x.go b/src/runtime/internal/sys/zgoarch_s390x.go deleted file mode 100644 index e50d2edbb5515c84f34c3eac907658c112abe16f..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_s390x.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build s390x -// +build s390x - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_sparc.go b/src/runtime/internal/sys/zgoarch_sparc.go deleted file mode 100644 index 0d08752c7bc5906e971eceae6ea834fb6f9e41ff..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_sparc.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build sparc -// +build sparc - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_sparc64.go b/src/runtime/internal/sys/zgoarch_sparc64.go deleted file mode 100644 index ba405bbf3557aa808e4435718d645c29481c00da..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_sparc64.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build sparc64 -// +build sparc64 - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoarch_wasm.go b/src/runtime/internal/sys/zgoarch_wasm.go deleted file mode 100644 index 7c3e5afd1ee2415c55065f21aec888dd0ec778ec..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoarch_wasm.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build wasm -// +build wasm - -package sys - -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 GoarchLoong64 = 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 diff --git a/src/runtime/internal/sys/zgoos_aix.go b/src/runtime/internal/sys/zgoos_aix.go deleted file mode 100644 index f3b907471f6e4ad68a933dbed7e25a45806e9052..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_aix.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build aix -// +build aix - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_android.go b/src/runtime/internal/sys/zgoos_android.go deleted file mode 100644 index e28baf7c48103e037941ebb03f55f485c7a3e3a4..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_android.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build android -// +build android - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_darwin.go b/src/runtime/internal/sys/zgoos_darwin.go deleted file mode 100644 index 3c7f7b543eecdd2d3559c832f920d8c0a3fbd865..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_darwin.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build !ios && darwin -// +build !ios,darwin - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_dragonfly.go b/src/runtime/internal/sys/zgoos_dragonfly.go deleted file mode 100644 index f844d29e2a1e552c11a1b9f57d44e9c01df97c47..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_dragonfly.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build dragonfly -// +build dragonfly - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_freebsd.go b/src/runtime/internal/sys/zgoos_freebsd.go deleted file mode 100644 index 8999a2797af0cbce96b97239bd4b3219dbf38e96..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_freebsd.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build freebsd -// +build freebsd - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_hurd.go b/src/runtime/internal/sys/zgoos_hurd.go deleted file mode 100644 index a546488bf8999df89df1e98ae3195e25d5c4b913..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_hurd.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build hurd -// +build hurd - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_illumos.go b/src/runtime/internal/sys/zgoos_illumos.go deleted file mode 100644 index 02a4ca06e82b1b54d064c1a15776f6868d332590..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_illumos.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build illumos -// +build illumos - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_ios.go b/src/runtime/internal/sys/zgoos_ios.go deleted file mode 100644 index 033eec623df05375589396351cf87311315ad58e..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_ios.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build ios -// +build ios - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_js.go b/src/runtime/internal/sys/zgoos_js.go deleted file mode 100644 index 28226ad60ad2dc94058da37c1a895f8e326d2f1f..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_js.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build js -// +build js - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_linux.go b/src/runtime/internal/sys/zgoos_linux.go deleted file mode 100644 index 01546e4b9f26165b15cdf5f08091e083660ef545..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_linux.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build !android && linux -// +build !android,linux - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_netbsd.go b/src/runtime/internal/sys/zgoos_netbsd.go deleted file mode 100644 index 9d658b20ee200d9b3759c8fc5da24ad29ef1e578..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_netbsd.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build netbsd -// +build netbsd - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_openbsd.go b/src/runtime/internal/sys/zgoos_openbsd.go deleted file mode 100644 index 0f55454a953fec156a7cb6c5f6bf6e982ba4fab1..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_openbsd.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build openbsd -// +build openbsd - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_plan9.go b/src/runtime/internal/sys/zgoos_plan9.go deleted file mode 100644 index d0347464d6d25dcf55cc1069a0128b600917b32e..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_plan9.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build plan9 -// +build plan9 - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_solaris.go b/src/runtime/internal/sys/zgoos_solaris.go deleted file mode 100644 index 05c3007e2c226077531804715ff5c386a10651eb..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_solaris.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build !illumos && solaris -// +build !illumos,solaris - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_windows.go b/src/runtime/internal/sys/zgoos_windows.go deleted file mode 100644 index 7d07fa3a451150875f9710dc020da8b74a37be92..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_windows.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build windows -// +build windows - -package sys - -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 diff --git a/src/runtime/internal/sys/zgoos_zos.go b/src/runtime/internal/sys/zgoos_zos.go deleted file mode 100644 index d6e5b9b0cb2b98b2e9edd9a678e39645723c7bb1..0000000000000000000000000000000000000000 --- a/src/runtime/internal/sys/zgoos_zos.go +++ /dev/null @@ -1,26 +0,0 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. - -//go:build zos -// +build zos - -package sys - -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 diff --git a/src/runtime/lfstack_32bit.go b/src/runtime/lfstack_32bit.go index c00f0965bd63b1f40e46e40bca929a7979079363..405923cc34e7425d8cfed647b0762c3471fd6131 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 4812dd1156572437938a16ad9c78ab96b5dce9a7..3f0e48089774a7ae561f47ac69758558bf93598d 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/lfstack_test.go b/src/runtime/lfstack_test.go index fb4b45992d8f489ed7b4c9735af4b87e4f48199e..d0a1b6ba0682efe592c940e0e4323748ffaec00d 100644 --- a/src/runtime/lfstack_test.go +++ b/src/runtime/lfstack_test.go @@ -24,7 +24,7 @@ func toMyNode(node *LFNode) *MyNode { return (*MyNode)(unsafe.Pointer(node)) } -var global interface{} +var global any func TestLFStack(t *testing.T) { stack := new(uint64) diff --git a/src/runtime/libfuzzer.go b/src/runtime/libfuzzer.go index 578bce04149baab781e738fa2779a14ec5d6ec6a..e7b3cdc46a9ea8b4c9c908dcbdf3154eb9d4568c 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/libfuzzer_amd64.s b/src/runtime/libfuzzer_amd64.s index 13645fc7af849ba8f99f148b091a52bc9b49dcfe..253fe15198120c86424a6a4e2bcc3a5f701cf6a1 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 4ad8242804eb1179559b7f2670ce3cb23f00193c..ae0efd8c9bf2e8d672cbabd65847e56264ae3ea9 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/lock_futex.go b/src/runtime/lock_futex.go index e4c8d01941d196d46ad670d66396ab8ee85f05fe..575df7a1d57086db73da1af1da4cd94237a663af 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 0ca3512baf3c8313542cfe214057ef11772e917c..80ee50da3513cf71541e358392e0358c250ea323 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 7a6af28b561399aa45913e034db07202033ce1da..db36df1f375b377c54627df90786c0e8be91b0e1 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.go b/src/runtime/lockrank.go index dde9f7c21a7f3aa0f6d1ab5a61128e890e56238e..4a16bc0ddb6e7c091fd95b0163230971461d8276 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 @@ -80,6 +80,7 @@ const ( // Memory-related leaf locks lockRankGlobalAlloc + lockRankPageAllocScav // Other leaf locks lockRankGFree @@ -131,9 +132,9 @@ var lockNames = []string{ lockRankReflectOffs: "reflectOffs", lockRankHchan: "hchan", + lockRankTraceBuf: "traceBuf", lockRankFin: "fin", lockRankNotifyList: "notifyList", - lockRankTraceBuf: "traceBuf", lockRankTraceStrings: "traceStrings", lockRankMspanSpecial: "mspanSpecial", lockRankProf: "prof", @@ -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", @@ -208,31 +210,32 @@ 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}, - 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}, - 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/lockrank_off.go b/src/runtime/lockrank_off.go index f3d2c009145766c448a9a71a5ca3d4c0cd1f6c96..daa45b542dd330d918a7f2594d89829032b57e50 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 fc8d2dc8d1179fd1813561ff0a6283550b7a0bfe..3c8c367c19fbb53700e3023e903f63b17b2703be 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/malloc.go b/src/runtime/malloc.go index cc22b0f276597e94b5e6138a4fcddb8d5e20bb5b..6ed6ceade2d4ca115c6ad8c87184377fc267fe8e 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -101,6 +101,8 @@ package runtime import ( + "internal/goarch" + "internal/goos" "runtime/internal/atomic" "runtime/internal/math" "runtime/internal/sys" @@ -150,7 +152,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*goos.IsWindows - 1*goos.IsPlan9 // heapAddrBits is the number of bits in a heap address. On // amd64, addresses are sign-extended beyond heapAddrBits. On @@ -199,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-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-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< typ.size { // Array allocation. If there are any @@ -1135,6 +1152,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 { @@ -1148,7 +1176,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 } @@ -1256,7 +1287,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") } @@ -1310,7 +1341,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 @@ -1328,7 +1359,7 @@ func nextSampleNoFP() uintptr { rate = 0x3fffffff } if rate != 0 { - return uintptr(fastrand() % uint32(2*rate)) + return uintptr(fastrandn(uint32(2 * rate))) } return 0 } @@ -1419,7 +1450,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 @@ -1508,3 +1539,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/malloc_test.go b/src/runtime/malloc_test.go index e028554b2386d5218194baac291b98a9f6a99149..8ff88687bd71c815f6e7d656f2842c40ef4e983f 100644 --- a/src/runtime/malloc_test.go +++ b/src/runtime/malloc_test.go @@ -33,14 +33,14 @@ func TestMemStats(t *testing.T) { st := new(MemStats) ReadMemStats(st) - nz := func(x interface{}) error { + nz := func(x any) error { if x != reflect.Zero(reflect.TypeOf(x)).Interface() { return nil } return fmt.Errorf("zero value") } - le := func(thresh float64) func(interface{}) error { - return func(x interface{}) error { + le := func(thresh float64) func(any) error { + return func(x any) error { // These sanity tests aren't necessarily valid // with high -test.count values, so only run // them once. @@ -54,8 +54,8 @@ func TestMemStats(t *testing.T) { return fmt.Errorf("insanely high value (overflow?); want <= %v", thresh) } } - eq := func(x interface{}) func(interface{}) error { - return func(y interface{}) error { + eq := func(x any) func(any) error { + return func(y any) error { if x == y { return nil } @@ -64,7 +64,7 @@ func TestMemStats(t *testing.T) { } // Of the uint fields, HeapReleased, HeapIdle can be 0. // PauseTotalNs can be 0 if timer resolution is poor. - fields := map[string][]func(interface{}) error{ + fields := map[string][]func(any) error{ "Alloc": {nz, le(1e10)}, "TotalAlloc": {nz, le(1e11)}, "Sys": {nz, le(1e10)}, "Lookups": {eq(uint64(0))}, "Mallocs": {nz, le(1e10)}, "Frees": {nz, le(1e10)}, "HeapAlloc": {nz, le(1e10)}, "HeapSys": {nz, le(1e10)}, "HeapIdle": {le(1e10)}, @@ -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) { diff --git a/src/runtime/map.go b/src/runtime/map.go index 111db56b01a2fe874767a6375b6c80d6588b3d4b..e91b25eaec501512170ebe101e3d70aa291b970e 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -54,9 +54,10 @@ package runtime // before the table grows. Typical tables will be somewhat less loaded. import ( + "internal/abi" + "internal/goarch" "runtime/internal/atomic" "runtime/internal/math" - "runtime/internal/sys" "unsafe" ) @@ -103,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. @@ -159,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). @@ -182,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 } @@ -205,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 { @@ -394,13 +395,16 @@ 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) } 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 @@ -452,13 +456,16 @@ 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) } 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 @@ -574,13 +581,16 @@ 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) } if msanenabled { msanread(key, t.key.size) } + if asanenabled { + asanread(key, t.key.size) + } if h.flags&hashWriting != 0 { throw("concurrent map writes") } @@ -685,13 +695,16 @@ 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) } 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 @@ -802,17 +815,17 @@ 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)) } + it.t = t if h == nil || h.count == 0 { 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 it.h = h // grab snapshot of bucket state @@ -852,7 +865,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 +991,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) } @@ -1280,11 +1293,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") } @@ -1323,22 +1336,41 @@ 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) *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 @@ -1363,7 +1395,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 +1407,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_benchmark_test.go b/src/runtime/map_benchmark_test.go index d0becc9ddb859654e6d524143ef5e8b8b6114065..b46d2a4727a752ac4ec3a3259bb6293a8e9c082b 100644 --- a/src/runtime/map_benchmark_test.go +++ b/src/runtime/map_benchmark_test.go @@ -488,20 +488,20 @@ func BenchmarkMapStringConversion(b *testing.B) { var BoolSink bool func BenchmarkMapInterfaceString(b *testing.B) { - m := map[interface{}]bool{} + m := map[any]bool{} for i := 0; i < 100; i++ { m[fmt.Sprintf("%d", i)] = true } - key := (interface{})("A") + key := (any)("A") b.ResetTimer() for i := 0; i < b.N; i++ { BoolSink = m[key] } } func BenchmarkMapInterfacePtr(b *testing.B) { - m := map[interface{}]bool{} + m := map[any]bool{} for i := 0; i < 100; i++ { i := i diff --git a/src/runtime/map_fast32.go b/src/runtime/map_fast32.go index 8d52dad217afb0fabce82c73c1a27ef52345eddd..e80caeef552702c853c9f1b17c2162d619161fa5 100644 --- a/src/runtime/map_fast32.go +++ b/src/runtime/map_fast32.go @@ -5,14 +5,15 @@ package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) 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 @@ -301,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 @@ -427,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 f1368dc774ec4de8cc6ec4071fe507ee2020d6c0..69d8872885a48ca9dcb1289314b4ed65533bffed 100644 --- a/src/runtime/map_fast64.go +++ b/src/runtime/map_fast64.go @@ -5,14 +5,15 @@ package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) 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 @@ -300,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. @@ -430,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 0673dd39c8ff6a87084668400febbf64520c0fa3..4dca882c6368779f5e22a9b2a1572a3cfbe90936 100644 --- a/src/runtime/map_faststr.go +++ b/src/runtime/map_faststr.go @@ -5,14 +5,15 @@ package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) 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]) @@ -26,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 { @@ -35,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 { @@ -51,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)) { @@ -68,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]) @@ -91,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)) } } } @@ -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 @@ -121,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 { @@ -130,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 { @@ -146,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)) { @@ -163,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 @@ -186,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 } } } @@ -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") @@ -245,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 } @@ -283,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") } @@ -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 @@ -324,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 @@ -334,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 { @@ -410,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. @@ -418,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 @@ -450,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 @@ -463,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 302b3c23c12b4280d5839584cc0566bdfc1d01bb..0c83dd4ddf8b4e704f8ec7469b40ad11808f6b3e 100644 --- a/src/runtime/map_test.go +++ b/src/runtime/map_test.go @@ -6,10 +6,10 @@ package runtime_test import ( "fmt" + "internal/goarch" "math" "reflect" "runtime" - "runtime/internal/sys" "sort" "strconv" "strings" @@ -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) } @@ -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++ { @@ -1050,7 +1050,7 @@ func BenchmarkMapDelete(b *testing.B) { func TestDeferDeleteSlow(t *testing.T) { ks := []complex128{0, 1, 2, 3} - m := make(map[interface{}]int) + m := make(map[any]int) for i, k := range ks { m[k] = i } @@ -1193,14 +1193,14 @@ func TestMapInterfaceKey(t *testing.T) { c64 complex64 c128 complex128 s string - i0 interface{} + i0 any i1 interface { String() string } a [4]string } - m := map[interface{}]bool{} + m := map[any]bool{} // Put a bunch of data in m, so that a bad hash is likely to // lead to a bad bucket, which will lead to a missed lookup. for i := 0; i < 1000; i++ { diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go index 4994347bdeb35610d1f45efb714b233004835105..0f8b2af5faea408c23266415104d9b4e3b0fb6e4 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" ) @@ -177,13 +177,17 @@ 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) msanread(src, typ.size) } + if asanenabled { + asanwrite(dst, typ.size) + asanread(src, typ.size) + } typedmemmove(typ, dst, src) } @@ -197,11 +201,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 +229,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) @@ -254,7 +258,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) } @@ -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/mbitmap.go b/src/runtime/mbitmap.go index 32b8db7a50282c70785615902af017232280bc35..1c6f3f959f9f3dca7bfac7f3ea1230fbc094b300 100644 --- a/src/runtime/mbitmap.go +++ b/src/runtime/mbitmap.go @@ -46,6 +46,7 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" "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 @@ -386,10 +387,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 @@ -416,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. @@ -557,7 +567,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 +602,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 +612,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 +635,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 +643,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 +663,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 +730,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 +761,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 +846,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 +872,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 +882,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 +1456,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 +1487,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 +1509,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 +1531,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 +1555,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 +1566,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 +1701,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 +1754,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 +1882,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) @@ -1942,10 +1952,10 @@ func getgcmaskcb(frame *stkframe, ctxt unsafe.Pointer) bool { // gcbits returns the GC type info for x, for testing. // The result is the bitmap entries (0 or 1), one entry per byte. //go:linkname reflect_gcbits reflect.gcbits -func reflect_gcbits(x interface{}) []byte { +func reflect_gcbits(x any) []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] } @@ -1955,7 +1965,7 @@ func reflect_gcbits(x interface{}) []byte { // Returns GC type info for the pointer stored in ep for testing. // If ep points to the stack, only static live information will be returned // (i.e. not for objects which are only dynamically live stack objects). -func getgcmask(ep interface{}) (mask []byte) { +func getgcmask(ep any) (mask []byte) { e := *efaceOf(&ep) p := e.data t := e._type @@ -1965,10 +1975,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 +1987,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 +2000,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 +2025,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/mcache.go b/src/runtime/mcache.go index a9e959109abaab7f4e624fe7fcc857f7572efcff..86a8958b9dc66347b227e360e84d84f158fcf0cd 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, @@ -184,32 +184,18 @@ 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 } // 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 +210,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") } @@ -233,30 +219,24 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) (*mspan, b 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. 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() { // 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 { @@ -273,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) @@ -290,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/mcentral.go b/src/runtime/mcentral.go index 6013c94c69808a9d728b9e4d67c9db1fa16dc91f..e4bdf3507170e7eefdadac422c238db139e039a5 100644 --- a/src/runtime/mcentral.go +++ b/src/runtime/mcentral.go @@ -102,56 +102,59 @@ 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. } - // See comment for partial unswept spans. + sweep.active.end(sl) } - sl.dispose() if trace.enabled { traceGCSweepDone() traceDone = true @@ -238,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/mcheckmark.go b/src/runtime/mcheckmark.go index ba80ac1bdf4d6070037a0a02ec46e2380797034b..1dd28585f1c03970f7e7030feb9cf7ed69b30b2e 100644 --- a/src/runtime/mcheckmark.go +++ b/src/runtime/mcheckmark.go @@ -13,8 +13,8 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "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/mem_bsd.go b/src/runtime/mem_bsd.go index dcbb9a1d51ee5222cc902776e54f54c909b66e02..b1525717921d1d588d27a7a9e73ee71bce95d283 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 fe940360c0e19a06243325d49bc0073477a842c3..4ca486ac4b74a41447fd3ba60d06c7f8162fc146 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/mem_linux.go b/src/runtime/mem_linux.go index 34368510911b4dea0a578ad7e43600adfc36bb8d..f8f9c531701f97ac9682315aa648f7a4b2871cb1 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/memclr_386.s b/src/runtime/memclr_386.s index 046c3441198bf5e4c44b29fe524e8e50d9ca17ca..a72e5f228dbb6bdf0ee56420439bf588c90e7512 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" @@ -30,8 +29,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/memclr_amd64.s b/src/runtime/memclr_amd64.s index a10f57bd8cbe3bf16d4ad7496b5f5bd478c8fb2a..700bbd7b9b0e2d865953fcfd2879eff690f04d3e 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" @@ -13,14 +12,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. @@ -37,9 +31,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/memclr_arm64.s b/src/runtime/memclr_arm64.s index c1a0dcef584fa1c03eba2f71fa99b1066b91dd69..b80cca6a1cd0bb8469a94173fc2fb74111b32282 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/memclr_mips64x.s b/src/runtime/memclr_mips64x.s index bc037013fe774f504608757c023c14529c9ac330..cf3a9c4ab4fb3696860c153e3eec3b14509c7fe4 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 3d21c3c414c2a0bfbc7abb53971055e20e6d1360..ee3009d46b8b6f521eac35a4ec020d7a1044b8dd 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 65639322b2a1cbb3872e16c530e4b35f8a0a36eb..64132cee96128c9a1319790a93ef2660a4f4b1b4 100644 --- a/src/runtime/memclr_ppc64x.s +++ b/src/runtime/memclr_ppc64x.s @@ -3,16 +3,17 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" // 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_386.s b/src/runtime/memmove_386.s index 1a43a1f724d7330f001c7fc5636356216ae8812c..6d7e17fcbcec879022b2e0e4e9ff02089c3e8408 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" @@ -55,8 +54,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/memmove_amd64.s b/src/runtime/memmove_amd64.s index 24c6529f58405471af326f95f9b2b311f1868df7..eeb5033fd9556effd46cf6bcce127377ef297e33 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" @@ -34,18 +33,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 @@ -254,10 +247,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 +288,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/memmove_arm64.s b/src/runtime/memmove_arm64.s index 43d27629e5bd13435107324502f43d0d70a7d792..bee3b00c47d81c2cefeb9a2e9df14c458d574014 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 diff --git a/src/runtime/memmove_mips64x.s b/src/runtime/memmove_mips64x.s index fef3c6be827f5644057d717f9fc702d22e877a61..b69178ccd38bd4785299cae57922b2d86a16d823 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 cd02fc25c4b41aa680a6c430a9597c453348da14..494288cf338cc58a6f7301960c2e24f743f9412e 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 fd16ad8129b3013010ffec54806304a3fc0949f8..e69e71a4a1872427a870ae3eae0fd728c55a9ee2 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" @@ -28,10 +27,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 diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go index c134a0f22d8e6f49d3b102218b4c92a0d6412437..e2ac5d4993b4e6353073e14ab75720941c310b40 100644 --- a/src/runtime/mfinal.go +++ b/src/runtime/mfinal.go @@ -8,8 +8,8 @@ package runtime import ( "internal/abi" + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "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 { @@ -200,7 +200,7 @@ func runfinq() { framesz = f.nret } else { // Need to pass arguments on the stack too. - framesz = unsafe.Sizeof((interface{})(nil)) + f.nret + framesz = unsafe.Sizeof((any)(nil)) + f.nret } if framecap < framesz { // The frame does not contain pointers interesting for GC, @@ -329,7 +329,7 @@ func runfinq() { // A single goroutine runs all finalizers for a program, sequentially. // If a finalizer must run for a long time, it should do so by starting // a new goroutine. -func SetFinalizer(obj interface{}, finalizer interface{}) { +func SetFinalizer(obj any, finalizer any) { if debug.sbrk != 0 { // debug.sbrk never frees memory, so no finalizers run // (and we don't have the data structures to record them). @@ -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() @@ -470,7 +470,7 @@ okarg: // Note: KeepAlive should only be used to prevent finalizers from // running prematurely. In particular, when used with unsafe.Pointer, // the rules for valid uses of unsafe.Pointer still apply. -func KeepAlive(x interface{}) { +func KeepAlive(x any) { // Introduce a use of x that the compiler can't eliminate. // This makes sure x is alive on entry. We need x to be alive // on entry for "defer runtime.KeepAlive(x)"; see issue 21402. diff --git a/src/runtime/mfinal_test.go b/src/runtime/mfinal_test.go index 3ca8d31c60598bed5bd691712e785331d0055855..04ba7a68309539ccc078ab4ee8929cc042be6118 100644 --- a/src/runtime/mfinal_test.go +++ b/src/runtime/mfinal_test.go @@ -34,14 +34,14 @@ func TestFinalizerType(t *testing.T) { } var finalizerTests = []struct { - convert func(*int) interface{} - finalizer interface{} + convert func(*int) any + finalizer any }{ - {func(x *int) interface{} { return x }, func(v *int) { finalize(v) }}, - {func(x *int) interface{} { return Tintptr(x) }, func(v Tintptr) { finalize(v) }}, - {func(x *int) interface{} { return Tintptr(x) }, func(v *int) { finalize(v) }}, - {func(x *int) interface{} { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }}, - {func(x *int) interface{} { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }}, + {func(x *int) any { return x }, func(v *int) { finalize(v) }}, + {func(x *int) any { return Tintptr(x) }, func(v Tintptr) { finalize(v) }}, + {func(x *int) any { return Tintptr(x) }, func(v *int) { finalize(v) }}, + {func(x *int) any { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }}, + {func(x *int) any { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }}, } for i, tt := range finalizerTests { @@ -85,7 +85,7 @@ func TestFinalizerInterfaceBig(t *testing.T) { go func() { v := &bigValue{0xDEADBEEFDEADBEEF, true, "It matters not how strait the gate"} old := *v - runtime.SetFinalizer(v, func(v interface{}) { + runtime.SetFinalizer(v, func(v any) { i, ok := v.(*bigValue) if !ok { t.Errorf("finalizer called with type %T, want *bigValue", v) diff --git a/src/runtime/mfixalloc.go b/src/runtime/mfixalloc.go index 293c16b38b1bc1ebc5eb7802757d7bcaf92b5e60..b701a09b40a9471ab9b04c9742d7fddc11630aee 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 @@ -50,12 +51,20 @@ 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 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 @@ -77,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) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 458566353536f5f0af5286aeb35ef971430fc6ff..8c8f7d936b80062c9923022a1a38566c55d6f6f7 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. @@ -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 } @@ -325,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 @@ -550,7 +554,7 @@ func (t gcTrigger) test() bool { // own write. return gcController.heapLive >= gcController.trigger case gcTriggerTime: - if gcController.gcPercent < 0 { + if gcController.gcPercent.Load() < 0 { return false } lastgc := int64(atomic.Load64(&memstats.last_gc_nanotime)) @@ -666,7 +670,9 @@ func gcStart(trigger gcTrigger) { work.cycles++ - gcController.startCycle() + // Assists and workers can start the moment we start + // the world. + gcController.startCycle(now, int(gomaxprocs)) work.heapGoal = gcController.heapGoal // In STW mode, disable scheduling of user Gs. This may also @@ -709,10 +715,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() @@ -896,7 +898,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) @@ -970,12 +972,13 @@ 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. gcController.commit(nextTriggerRatio) + gcPaceSweeper(gcController.trigger) + gcPaceScavenger(gcController.heapGoal, gcController.lastHeapGoal) // Update timing memstats now := nanotime() @@ -1026,8 +1029,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) }) @@ -1054,7 +1059,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 @@ -1088,6 +1093,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)") @@ -1292,15 +1299,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 @@ -1376,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. @@ -1420,30 +1426,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 @@ -1461,11 +1459,11 @@ func gcSweep(mode gcMode) { lock(&mheap_.lock) mheap_.sweepgen += 2 - mheap_.sweepDrained = 0 - mheap_.pagesSwept = 0 + sweep.active.reset() + mheap_.pagesSwept.Store(0) mheap_.sweepArenas = mheap_.allArenas - mheap_.reclaimIndex = 0 - mheap_.reclaimCredit = 0 + mheap_.reclaimIndex.Store(0) + mheap_.reclaimCredit.Store(0) unlock(&mheap_.lock) sweep.centralIndex.clear() @@ -1563,19 +1561,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/mgcmark.go b/src/runtime/mgcmark.go index 1fd0732d62dcc6b8a0831701d535bf322d08d9dc..a15c62cc491eee2c92ad87af5f09c0892266e781 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -7,6 +7,8 @@ package runtime import ( + "internal/goarch" + "internal/goexperiment" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -100,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) @@ -150,20 +153,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: @@ -183,15 +194,13 @@ func markroot(gcw *gcWork, i uint32) { default: // the rest is scanning goroutine stacks - 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 { + workCounter = &gcController.stackScanWork + 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 @@ -229,7 +238,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) @@ -238,14 +247,25 @@ 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) { - if rootBlockBytes%(8*sys.PtrSize) != 0 { +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") } @@ -255,10 +275,10 @@ 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*sys.PtrSize)))) + ptrmask := (*uint8)(add(unsafe.Pointer(ptrmask0), uintptr(shard)*(rootBlockBytes/(8*goarch.PtrSize)))) n := uintptr(rootBlockBytes) if off+n > n0 { n = n0 - off @@ -266,6 +286,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. @@ -372,7 +393,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) } @@ -399,8 +420,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 { @@ -544,7 +565,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, @@ -586,8 +607,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, @@ -639,7 +658,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) @@ -673,7 +692,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) } @@ -682,6 +701,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. @@ -691,7 +717,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") @@ -702,7 +728,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") @@ -714,6 +740,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) @@ -737,7 +772,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. @@ -750,26 +785,23 @@ 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. - scanblock(uintptr(unsafe.Pointer(&d.fn)), sys.PtrSize, &oneptrmask[0], gcw, &state) + // Scan the func value, which could be a stack allocated closure. + // See issue 30453. + 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 { @@ -807,7 +839,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 @@ -856,6 +888,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. @@ -913,13 +946,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. @@ -927,7 +960,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 { @@ -941,7 +975,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) } } } @@ -987,7 +1021,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. @@ -1010,7 +1044,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 } @@ -1049,14 +1083,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 @@ -1069,12 +1103,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 } } @@ -1098,20 +1132,15 @@ 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() } - // 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() @@ -1125,26 +1154,27 @@ 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 } } // No heap or root jobs. break } + 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 } } @@ -1152,14 +1182,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 @@ -1172,9 +1202,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++ { @@ -1190,7 +1220,7 @@ func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork, stk *stackScanState) } } bits >>= 1 - i += sys.PtrSize + i += goarch.PtrSize } } } @@ -1202,6 +1232,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 @@ -1251,7 +1287,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 { @@ -1283,7 +1319,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 @@ -1300,7 +1336,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 '$' @@ -1325,9 +1361,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) @@ -1336,10 +1372,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 { @@ -1401,7 +1437,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) @@ -1440,12 +1476,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) } @@ -1473,13 +1509,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 } @@ -1522,7 +1558,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 9338359de7d7719151489d47329ab9c4286ba8a0..6df8af45a8b71234db3b59ad25fa81e59ba0ddcb 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,12 @@ const ( gcOverAssistWork = 64 << 10 // defaultHeapMinimum is the value of heapMinimum for GOGC==100. - defaultHeapMinimum = 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. + scannableStackSizeSlack = 8 << 10 ) func init() { @@ -72,8 +84,9 @@ func init() { var gcController gcControllerState type gcControllerState struct { - // Initialized from $GOGC. GOGC=off means no GC. - gcPercent int32 + + // Initialized from GOGC. GOGC=off means no GC. + gcPercent atomic.Int32 _ uint32 // padding so following 64-bit values are 8-byte aligned @@ -100,6 +113,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. @@ -114,6 +129,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. // @@ -156,28 +196,73 @@ 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. + // + // Updated only while the world is stopped. + stackScan uint64 + + // 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 + + // 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 // 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 @@ -222,24 +307,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 @@ -253,19 +328,45 @@ 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 } 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, + + // 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) @@ -274,13 +375,17 @@ 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() { - c.scanWork = 0 +func (c *gcControllerState) startCycle(markStartTime int64, procs int) { + c.heapScanWork.Store(0) + c.stackScanWork.Store(0) + c.globalsScanWork.Store(0) c.bgScanCredit = 0 c.assistTime = 0 c.dedicatedMarkTime = 0 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 @@ -289,8 +394,14 @@ func (c *gcControllerState) startCycle() { // 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, @@ -298,7 +409,7 @@ func (c *gcControllerState) startCycle() { // 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 @@ -311,14 +422,14 @@ func (c *gcControllerState) startCycle() { // 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 } @@ -333,7 +444,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, "->", @@ -365,7 +476,7 @@ func (c *gcControllerState) startCycle() { // is when assists are enabled and the necessary statistics are // available). func (c *gcControllerState) revise() { - gcPercent := 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. @@ -373,32 +484,80 @@ 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. + 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 + // 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 extHeapGoal > hardGoal { + extHeapGoal = hardGoal + } + heapGoal = extHeapGoal + } + 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. @@ -439,14 +598,96 @@ 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. +// 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(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 + + // 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. + // Period for this is 1 GC cycle. + oldConsMark := c.consMark + c.consMark = c.consMarkController.next(c.consMark, currentConsMark, 1.0) + + 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 @@ -473,15 +714,6 @@ 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 - - // 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)) - } - triggerError := goalGrowthRatio - c.triggerRatio - utilization/gcGoalUtilization*(actualGrowthRatio-c.triggerRatio) // Finally, we adjust the trigger for next time by this error, @@ -500,7 +732,7 @@ func (c *gcControllerState) endCycle(userForced bool) float64 { 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, @@ -636,9 +868,82 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g { return gp } -// commit sets the trigger ratio and updates everything -// derived from it: the absolute trigger, the heap goal, mark pacing, -// and sweep pacing. +// 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.heapScanWork.Load()) + c.lastHeapScan = uint64(c.heapScanWork.Load()) + + // 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") + } +} + +func (c *gcControllerState) update(dHeapLive, dHeapScan int64) { + if dHeapLive != 0 { + atomic.Xadd64(&gcController.heapLive, dHeapLive) + if trace.enabled { + // gcController.heapLive changed. + traceHeapAlloc() + } + } + // 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. + c.revise() + } +} + +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 + } +} + +func (c *gcControllerState) addGlobals(amount int64) { + atomic.Xadd64(&c.globalsScan, amount) +} + +// 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. @@ -648,19 +953,147 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g { // // 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) + } + + 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 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. + 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) { + 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 >= 0 { - goal = c.heapMarked + c.heapMarked*uint64(c.gcPercent)/100 + if gcPercent >= 0 { + goal = c.heapMarked + c.heapMarked*uint64(gcPercent)/100 } // Set the trigger ratio, capped to reasonable bounds. - if c.gcPercent >= 0 { - scalingFactor := float64(c.gcPercent) / 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 @@ -700,7 +1133,7 @@ func (c *gcControllerState) commit(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 gcPercent >= 0 { trigger = uint64(float64(c.heapMarked) * (1 + triggerRatio)) // Don't trigger below the minimum heap size. minTrigger := c.heapMinimum @@ -741,42 +1174,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 := atomic.Load64(&mheap_.pagesSwept) - pagesInUse := atomic.Load64(&mheap_.pagesInUse) - 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. - atomic.Store64(&mheap_.pagesSweptBasis, pagesSwept) - } - } - - gcPaceScavenger() } // effectiveGrowthRatio returns the current effective heap growth @@ -789,7 +1186,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 { @@ -802,16 +1201,20 @@ 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) + if !c.test { + assertWorldStoppedOrLockHeld(&mheap_.lock) + } - out := c.gcPercent + out := c.gcPercent.Load() if in < 0 { in = -1 } - c.gcPercent = in - c.heapMinimum = defaultHeapMinimum * uint64(c.gcPercent) / 100 + c.heapMinimum = defaultHeapMinimum * uint64(in) / 100 + c.gcPercent.Store(in) // Update pacing in response to gcPercent change. c.commit(c.triggerRatio) @@ -824,6 +1227,8 @@ 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) }) @@ -846,3 +1251,35 @@ func readGOGC() int32 { } return 100 } + +type piController struct { + kp float64 // Proportional constant. + ti float64 // Integral time constant. + tt float64 // Reset time. + + 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, period 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*period/c.ti)*(setpoint-input) + (period/c.tt)*(output-rawOutput) + } + return output +} diff --git a/src/runtime/mgcpacer_test.go b/src/runtime/mgcpacer_test.go new file mode 100644 index 0000000000000000000000000000000000000000..9ec0e5172b08a4e3616d27da7ff94eaeb3d6ced5 --- /dev/null +++ b/src/runtime/mgcpacer_test.go @@ -0,0 +1,717 @@ +// Copyright 2021 The Go Authors. 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" + "internal/goexperiment" + "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 { + 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", + 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) + } + }, + }, + { + // 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. + 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) + 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) + } + } + }, + }, + { + // 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) + 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) + } + } + }, + }, + { + // 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) + 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) + } + } + }, + }, + // 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) { + 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 + } +} diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index 7578129f9d13965eca8cff1456f12caf2a8a147d..c27e189af92f9ef86a109afbb7b1b697aaae1771 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -56,6 +56,7 @@ package runtime import ( + "internal/goos" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -90,7 +91,7 @@ const ( // // This ratio is used as part of multiplicative factor to help the scavenger account // for the additional costs of using scavenged memory in its pacing. - scavengeCostRatio = 0.7 * (sys.GoosDarwin + sys.GoosIos) + scavengeCostRatio = 0.7 * (goos.IsDarwin + goos.IsIos) // scavengeReservationShards determines the amount of memory the scavenger // should reserve for scavenging at a time. Specifically, the amount of @@ -104,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. @@ -112,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 { - mheap_.scavengeGoal = ^uint64(0) + if lastHeapGoal == 0 { + atomic.Store64(&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 @@ -151,10 +157,10 @@ func gcPaceScavenger() { // 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. @@ -249,7 +255,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) @@ -257,56 +263,93 @@ func bgscavenge() { scavenge.parked = true scavenge.timer = new(timer) - scavenge.timer.f = func(_ interface{}, _ uintptr) { + scavenge.timer.f = func(_ any, _ uintptr) { wakeScavenger() } - gcenable_setup <- 1 + 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. - // - // 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) + // idealFraction is the ideal % of overall application CPU time that we + // spend scavenging. + idealFraction := float64(scavengePercent) / 100.0 + // 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) - - // 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) - + // 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(), mheap_.scavengeGoal + retained, goal := heapRetained(), atomic.Load64(&mheap_.scavengeGoal) if retained <= goal { - unlock(&mheap_.lock) - return + break } - // Scavenge one page, and measure the amount of time spent scavenging. + // 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, true) - mheap_.pages.scav.released += released - crit = float64(nanotime() - start) + r := mheap_.pages.scavenge(scavengeQuantum) + atomic.Xadduintptr(&mheap_.pages.scav.released, r) + end := nanotime() - unlock(&mheap_.lock) - }) + // 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(r/physPageSize) + } else { + crit += float64(end - start) + } + released += r + + // When using fake time just do one loop. + if faketime != 0 { + break + } + } if released == 0 { lock(&scavenge.lock) @@ -323,18 +366,13 @@ func bgscavenge() { 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 @@ -345,41 +383,19 @@ func bgscavenge() { // 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 - } + // 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 scavengeEWMA by merging in the new crit/slept ratio. - const alpha = 0.5 - scavengeEWMA = alpha*fraction + (1-alpha)*scavengeEWMA + // Update the critSleepRatio, adjusting until we reach our ideal fraction. + critSleepRatio = critSleepController.next(cpuFraction, idealFraction, float64(slept)+crit) } } @@ -389,16 +405,7 @@ func bgscavenge() { // 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 @@ -410,9 +417,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. @@ -450,8 +459,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) @@ -481,9 +491,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 @@ -492,14 +503,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) @@ -507,7 +513,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 @@ -518,28 +525,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 @@ -553,15 +558,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 { @@ -593,40 +593,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. // @@ -665,37 +637,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 } @@ -706,38 +702,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 3b12a2e1e631524e4ea267025214f34966fa42a0..0659293c602f017194162ddf33147ec597000e05 100644 --- a/src/runtime/mgcscavenge_test.go +++ b/src/runtime/mgcscavenge_test.go @@ -6,6 +6,7 @@ package runtime_test import ( "fmt" + "internal/goos" "math/rand" . "runtime" "testing" @@ -408,7 +409,9 @@ func TestPageAllocScavenge(t *testing.T) { }, }, } - if PageAlloc64Bit != 0 { + // Disable these tests on iOS since we have a small address space. + // See #46860. + if PageAlloc64Bit != 0 && goos.IsIos == 0 { tests["ScavAllVeryDiscontiguous"] = setup{ beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {}, @@ -430,12 +433,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 +446,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/mgcstack.go b/src/runtime/mgcstack.go index 92d58485f6f7a250d50a106fd77a378ef39a6e2e..49dc54e16524ce873609222ba1ea697640b1fddf 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/mgcsweep.go b/src/runtime/mgcsweep.go index 8fe3a6534077946f4d4c5222206340f9ba828728..fdbec30cf121d88f792e49059e98cd4f61fd521d 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 @@ -153,13 +268,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 { @@ -183,15 +298,11 @@ func bgsweep() { } } -// 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, " 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 { @@ -291,7 +370,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 @@ -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 { @@ -408,7 +490,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 @@ -481,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() @@ -501,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() @@ -719,17 +804,17 @@ 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 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 } - if atomic.Load64(&mheap_.pagesSweptBasis) != sweptBasis { + if mheap_.pagesSweptBasis.Load() != sweptBasis { // Sweep pacing changed. Recompute debt. goto retry } @@ -748,3 +833,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) + } + } +} diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go index 667c7afa97197ddd3d190fafaf928385595447dd..9c3f7fd223a943716dbab8549f1d638696fe6d74 100644 --- a/src/runtime/mgcwork.go +++ b/src/runtime/mgcwork.go @@ -5,8 +5,8 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "unsafe" ) @@ -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 } } @@ -322,7 +323,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 84c00ce8f85cd1e13047f4fae9536b67bdae08d3..ecbd0a3a492a33fede00394babd9b813de530e11 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -10,8 +10,8 @@ package runtime import ( "internal/cpu" + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "unsafe" ) @@ -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. @@ -82,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 // @@ -96,23 +94,25 @@ 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 atomic.Uint64 // pages swept this cycle + 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 // compiler can't 8-byte align fields. // 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 @@ -123,16 +123,13 @@ 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 // 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 @@ -497,13 +494,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") } @@ -739,7 +736,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 } @@ -756,23 +753,23 @@ 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 } // 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 } @@ -788,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 } } @@ -818,7 +815,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()] @@ -864,7 +864,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. @@ -896,10 +896,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. @@ -912,17 +911,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. @@ -1011,7 +1000,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 @@ -1131,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 @@ -1176,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 } @@ -1200,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,7 +1322,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 @@ -1322,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. @@ -1347,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 { @@ -1407,19 +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. - if retained := heapRetained(); retained+uint64(totalGrowth) > h.scavengeGoal { - todo := totalGrowth - if overage := uintptr(retained + uint64(totalGrowth) - h.scavengeGoal); todo > overage { - todo = overage - } - h.pages.scavenge(todo, false) - } - return true + return totalGrowth, true } // Free the span back into the heap. @@ -1432,6 +1431,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) }) @@ -1468,7 +1473,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()) @@ -1503,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) @@ -1519,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 { @@ -1822,7 +1833,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/mkduff.go b/src/runtime/mkduff.go index da191cc594c0de6daadd0dddca70070f38395341..e8a85702c6088bdd1fc0ff746189f10e2e984fe8 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 @@ -154,7 +153,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 +166,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)") @@ -180,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) } @@ -188,23 +186,26 @@ 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) { fmt.Fprintln(w) fmt.Fprintln(w, "//go:build mips64 || mips64le") - fmt.Fprintln(w, "// +build mips64 mips64le") fmt.Fprintln(w) } diff --git a/src/runtime/mkfastlog2table.go b/src/runtime/mkfastlog2table.go index 8d78a3923a094be383eaebbbce64d519c579c45a..a55f54751c91bc4ada7a7c434f4d506d5fc389d2 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 6c980540f5776019e82ccd5939775723edfd86e1..17c9b75d6958b07aa7fe8ebd2a5999a7937dcf14 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. @@ -124,15 +123,13 @@ 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") - 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{}) { +func p(f string, args ...any) { fmted := fmt.Sprintf(f, args...) fmt.Fprintf(out, "\t%s\n", strings.ReplaceAll(fmted, "\n", "\n\t")) } @@ -201,6 +198,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++ { @@ -210,13 +209,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) @@ -505,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/mksizeclasses.go b/src/runtime/mksizeclasses.go index b1b10e9e0230a9976968a4b7cf84a9ee2d746eda..64ed84432923081e04e2be0ee429cb612b80154c 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 7460eb31046fa895127156e2f68c11e593a5ef7a..3280a62e8dd9e43806c12dfeefc22af261205493 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.go b/src/runtime/mpagealloc.go index 071f1fc27499cf9f9c043c80c2049f10b1e0c568..2725e3b7c7b59b4d7f8d3ab36b823533c82d4454 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. @@ -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 diff --git a/src/runtime/mpagealloc_32bit.go b/src/runtime/mpagealloc_32bit.go index fceb4e7a187b7a6d3a0ff060da84ea92a02e8277..8c83b934123b91f875d43308ebe4f74e89814e79 100644 --- a/src/runtime/mpagealloc_32bit.go +++ b/src/runtime/mpagealloc_32bit.go @@ -2,20 +2,13 @@ // Use of this source code is governed by a BSD-style // 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 +//go:build 386 || arm || mips || mipsle || wasm // 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 // pointer always has its top 32 bits as zero, so the effective heap address // space is only 2^32 bytes in size (see heapAddrBits). -// ios/arm64 is treated as a 32-bit architecture for the purposes of the -// page allocator, even though it has 64-bit pointers and a 33-bit address -// space (see heapAddrBits). The 33 bit address space cannot be rounded up -// to 64 bits because there are too many summary levels to fit in just 33 -// bits. - package runtime import "unsafe" diff --git a/src/runtime/mpagealloc_64bit.go b/src/runtime/mpagealloc_64bit.go index 16577346a7fbe2c30742875f56b4c6b6d4cac0af..1bacfbe0fa511f717ae59217eefedac15f32855d 100644 --- a/src/runtime/mpagealloc_64bit.go +++ b/src/runtime/mpagealloc_64bit.go @@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style // 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. +//go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x package runtime diff --git a/src/runtime/mpagealloc_test.go b/src/runtime/mpagealloc_test.go index 5d979fa95b9ef55a9beabe0404cf1a178d621f6a..f2b82e3f506a583f7676594e53fb3584c310136f 100644 --- a/src/runtime/mpagealloc_test.go +++ b/src/runtime/mpagealloc_test.go @@ -6,6 +6,7 @@ package runtime_test import ( "fmt" + "internal/goos" . "runtime" "testing" ) @@ -165,7 +166,9 @@ func TestPageAllocGrow(t *testing.T) { }, }, } - if PageAlloc64Bit != 0 { + // Disable these tests on iOS since we have a small address space. + // See #46860. + if PageAlloc64Bit != 0 && goos.IsIos == 0 { tests["ExtremelyDiscontiguous"] = test{ chunks: []ChunkIdx{ BaseChunkIdx, @@ -571,7 +574,9 @@ func TestPageAllocAlloc(t *testing.T) { }, }, } - if PageAlloc64Bit != 0 { + // Disable these tests on iOS since we have a small address space. + // See #46860. + if PageAlloc64Bit != 0 && goos.IsIos == 0 { const chunkIdxBigJump = 0x100000 // chunk index offset which translates to O(TiB) // This test attempts to trigger a bug wherein we look at unmapped summary diff --git a/src/runtime/mpagecache.go b/src/runtime/mpagecache.go index 4b5c66d8d6e14f1fd158e17b27acee91e553217a..7206e2dbdb763a0df7278660d2ef3ec6dcae6273 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 2ed0c0aa6a0ba82da5c78a1601514120840b5b0b..6cb0620f7b883c7c27eeec9cedf73d6027dc8c7b 100644 --- a/src/runtime/mpagecache_test.go +++ b/src/runtime/mpagecache_test.go @@ -5,6 +5,7 @@ package runtime_test import ( + "internal/goos" "math/rand" . "runtime" "testing" @@ -261,17 +262,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 +282,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 +300,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,12 +351,31 @@ 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 { + // Disable these tests on iOS since we have a small address space. + // See #46860. + if PageAlloc64Bit != 0 && goos.IsIos == 0 { const chunkIdxBigJump = 0x100000 // chunk index offset which translates to O(TiB) // This test is similar to the one with the same name for @@ -359,11 +384,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 +397,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 +406,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 +415,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 ff112300c37365ac962bccc560623c5642b0db63..f63164becd392b2c8b0f0ffda8dfe817ac80e376 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. diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index 5235b898e4f56cdcf4613ee91803e8377c39192d..569c17f0a7cf4b9ee8f5c3ad3e4f9b5eb52338eb 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "unsafe" ) @@ -141,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 { @@ -621,11 +622,14 @@ 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)) } + 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 @@ -674,11 +678,14 @@ 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)) } + 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 @@ -798,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/mranges.go b/src/runtime/mranges.go index 84a2c06dbb2e66fcb1810e91640403e8281196e9..e0be1e134ed71b9585d7df38a87887c95901563f 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/msan.go b/src/runtime/msan.go index 25aaf94e26cec2a46c4672b9bcc612a7ee96bd3d..902a1e9e744b3d4ed38fc53b55a610d61e58e31b 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/msan/msan.go b/src/runtime/msan/msan.go index c81577dddac08ca2992ccafb349df182a86561d7..f1bf4e1065cf96c2fc40c8a51afb3f29c252e8d0 100644 --- a/src/runtime/msan/msan.go +++ b/src/runtime/msan/msan.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build msan,linux -// +build amd64 arm64 +//go:build msan && linux && (amd64 || arm64) package msan diff --git a/src/runtime/msan0.go b/src/runtime/msan0.go index b1096a6750e5d249dc132c92acf755ed7fe7fcce..2f5fd2d98216e542040e3bdab59c9084bd9037ab 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/msan_amd64.s b/src/runtime/msan_amd64.s index 1bb57a3b7e80b8edcb96adf646b20eb22dffa22c..89ed3048d0ed5c281ba13f39bc8d230515aa346e 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 93ade8dd8970f88be503a60a9759165a2f9f267a..b9eff34ab606a01a4a5947a71c1f012367554340 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/mspanset.go b/src/runtime/mspanset.go index 10d2596c38ccb350a1416cd72398a0ecec687df8..29f14910ccdbb6211321bd3a5cbf925f9648226d 100644 --- a/src/runtime/mspanset.go +++ b/src/runtime/mspanset.go @@ -6,8 +6,8 @@ package runtime import ( "internal/cpu" + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "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 eeb2a7b4bc73be09eca70a7fbd0cbb7083a25f32..c2303e5b8ec0617f9777f63248e4a8d5e797af2c 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -7,8 +7,8 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "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. @@ -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) diff --git a/src/runtime/mwbbuf.go b/src/runtime/mwbbuf.go index 6efc00007d5f0eb8dafb72f6265e9400ddb09dd0..78d9382620bedc7436c0175e182e0e9466ac4042 100644 --- a/src/runtime/mwbbuf.go +++ b/src/runtime/mwbbuf.go @@ -23,8 +23,8 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "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/nbpipe_fcntl_libc_test.go b/src/runtime/nbpipe_fcntl_libc_test.go index 076a722eb73eba50eef9eb4a3a7ed4e501c51da5..a9c8987438defec3b430b7657db746d16dbf3de9 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 6d5e4ff0215a082f70556fe607981e82ef2c9a8d..97607fa2cf7a1bca191c01b10bc2072a73ff2f6c 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 b17257e9ec3649ba4cf5eebe671f5897648d5e88..408e1ec410fec434b125060d6470fe597d71b01a 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 f22b2b591fd592806ba7b4df5de67222464a51a2..6a555bcd9970d9640780ee6984d0fe92cddb8d06 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 1d6a9b525c8850e29074bba7b931a650433cb1dd..36342cfde832aa3150bbf97d4dbfbb24df47b0f0 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 6c26fdbbeb8765baed5574f329d5a0e97642c40f..322a6f3637cd4013fb2134cc05adb9904503bfde 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 @@ -78,6 +77,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 +86,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 +147,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 +180,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 +209,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 +421,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,23 +431,25 @@ 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 // 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 @@ -459,7 +467,7 @@ func netpollunblock(pd *pollDesc, mode int32, ioready bool) *g { } for { - old := *gpp + old := atomic.Loaduintptr(gpp) if old == pdReady { return nil } @@ -521,15 +529,15 @@ func netpolldeadlineimpl(pd *pollDesc, seq uintptr, read, write bool) { } } -func netpollDeadline(arg interface{}, seq uintptr) { +func netpollDeadline(arg any, seq uintptr) { netpolldeadlineimpl(arg.(*pollDesc), seq, true, true) } -func netpollReadDeadline(arg interface{}, seq uintptr) { +func netpollReadDeadline(arg any, seq uintptr) { netpolldeadlineimpl(arg.(*pollDesc), seq, true, false) } -func netpollWriteDeadline(arg interface{}, seq uintptr) { +func netpollWriteDeadline(arg any, seq uintptr) { netpolldeadlineimpl(arg.(*pollDesc), seq, false, true) } @@ -562,7 +570,7 @@ func (c *pollCache) alloc() *pollDesc { // a conversion requires an allocation because pointers to // go:notinheap types (which pollDesc is) must be stored // in interfaces indirectly. See issue 42076. -func (pd *pollDesc) makeArg() (i interface{}) { +func (pd *pollDesc) makeArg() (i any) { x := (*eface)(unsafe.Pointer(&i)) x._type = pdType x.data = unsafe.Pointer(&pd.self) @@ -570,6 +578,6 @@ func (pd *pollDesc) makeArg() (i interface{}) { } var ( - pdEface interface{} = (*pollDesc)(nil) - pdType *_type = efaceOf(&pdEface)._type + pdEface any = (*pollDesc)(nil) + pdType *_type = efaceOf(&pdEface)._type ) diff --git a/src/runtime/netpoll_epoll.go b/src/runtime/netpoll_epoll.go index 371ac59f8e2ec06327069c328fb77d5ddf2e3627..e0fb877d50858ba869df51e3e3205fc2dee8ef86 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 8366f289144cf4f377d6e7ed94271d3caadca56c..de1dcae7acf8123e8a1dc0fe3ab2634a6d289960 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 80d1b0cf18a17a9ab786599d91c44fb59f69db99..2f7f2848d296a6ee2c3fc035452cfe2d3297314c 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 33ab8eba58cc48a36f81763b8559f67b26b9a858..d0a63bca866f66680cd80ac2c762a693ab0d9f1d 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 94b7c7a46777d81adf4a0059b81e20887531c324..b188a2e88b7c8c24077a2f1dd75d5813697a07f8 100644 --- a/src/runtime/norace_linux_test.go +++ b/src/runtime/norace_linux_test.go @@ -4,11 +4,11 @@ // The file contains tests that cannot run under race detector for some reason. //go:build !race -// +build !race package runtime_test import ( + "internal/abi" "runtime" "testing" "time" @@ -25,7 +25,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/norace_test.go b/src/runtime/norace_test.go index 9ad5dde3829924d338010a2e7df96b70a8784d3f..d49f2ec0dfd9187e2b9a27db1c6590f975c9bcf7 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/os3_plan9.go b/src/runtime/os3_plan9.go index c5dc23de8b60898ee02c8c796c7517222648a635..a06d74e279fd6fc9f5e5b2eb78778cae3de826d8 100644 --- a/src/runtime/os3_plan9.go +++ b/src/runtime/os3_plan9.go @@ -5,7 +5,8 @@ package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) @@ -92,15 +93,15 @@ 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) } } if usesLR { - c.setpc(funcPC(sigpanictramp)) + c.setpc(abi.FuncPCABI0(sigpanictramp)) } else { - c.setpc(funcPC(sigpanic0)) + c.setpc(abi.FuncPCABI0(sigpanic0)) } return _NCONT } diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index 39ef831acfef8723bd1fd3ab4826ca166a46984b..2e946656d018955b3690830316ee6b26c66386aa 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -5,7 +5,8 @@ package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "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() @@ -241,8 +242,8 @@ 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) + 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 sigaction(i, &sa, nil) @@ -288,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 { @@ -315,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") @@ -336,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") @@ -390,6 +404,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)) @@ -598,7 +613,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_aix.go b/src/runtime/os_aix.go index 4fb1c8e845c87c5793a77c0f0bab6cca8b2e55fb..aeff593d50b39e5f6845d0c61ab6af2b55d16647 100644 --- a/src/runtime/os_aix.go +++ b/src/runtime/os_aix.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. //go:build aix -// +build aix package runtime import ( + "internal/abi" "unsafe" ) @@ -48,7 +48,7 @@ func semacreate(mp *m) { //go:nosplit func semasleep(ns int64) int32 { - _m_ := getg().m + mp := getg().m if ns >= 0 { var ts timespec @@ -62,17 +62,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 } @@ -267,7 +267,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 @@ -322,6 +322,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 079be107d719a24891fdcef303b41bb115808ada..0f0eb6c6fdcfa609b7dc753f8ea5a526d2d1d27b 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -369,7 +369,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 { @@ -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 5c688a31096a6b6aa51175a7d5b8fa702a210a62..cba2e42ab052d056e4e057f3d82e6059cbad0961 100644 --- a/src/runtime/os_dragonfly.go +++ b/src/runtime/os_dragonfly.go @@ -5,7 +5,8 @@ package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) @@ -147,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 @@ -226,8 +227,8 @@ 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) { - fn = funcPC(sigtramp) + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go + fn = abi.FuncPCABI0(sigtramp) } sa.sa_sigaction = fn sigaction(i, &sa, nil) @@ -267,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 @@ -278,7 +292,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 09dd50ce59477583ff418da334e3769f191890a4..c63b0e3d69dc0609d1ca425ff0ec2cfd7b4d2630 100644 --- a/src/runtime/os_freebsd.go +++ b/src/runtime/os_freebsd.go @@ -5,7 +5,8 @@ package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) @@ -116,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) @@ -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, @@ -236,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, @@ -379,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 @@ -391,7 +405,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_freebsd2.go b/src/runtime/os_freebsd2.go index fde6fbf1b144eb609559d4662d9bf054636405aa..3eaedf0b8b99a805a732a1799d305edada6c4ea1 100644 --- a/src/runtime/os_freebsd2.go +++ b/src/runtime/os_freebsd2.go @@ -3,18 +3,19 @@ // license that can be found in the LICENSE file. //go:build freebsd && !amd64 -// +build freebsd,!amd64 package runtime +import "internal/abi" + //go:nosplit //go:nowritebarrierrec 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) { - fn = funcPC(sigtramp) + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go + 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 dc0bb9ff96fd33ca40cb21ee59ee1a2ea6631010..b179383eacc769316ab7a2c45b719e2a2a9c89b3 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 @@ -12,11 +14,11 @@ 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 = funcPC(cgoSigtramp) + fn = abi.FuncPCABI0(cgoSigtramp) } else { - fn = funcPC(sigtramp) + fn = abi.FuncPCABI0(sigtramp) } } sa.sa_handler = fn diff --git a/src/runtime/os_freebsd_noauxv.go b/src/runtime/os_freebsd_noauxv.go index 8fe0cb6718f14d2f62577146058f35115e8e8e50..1d9452bda5fc33b5650a225a97e977bdb56fcfe8 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 52b64e76027648239fe16ed75a6a95334bc82f2e..9ed916705bc517e906f1f1618fc0e58ae3492277 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.go b/src/runtime/os_linux.go index c8b29e396c7128cdab84057c2782694bcd793e5f..32a1e1b4f7d9bc7c22e53d1a767b741c9e697dd5 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -5,11 +5,23 @@ package runtime import ( - "runtime/internal/sys" + "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 @@ -142,14 +154,14 @@ 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 // 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 { @@ -205,7 +217,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 } @@ -394,6 +406,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) @@ -419,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) { @@ -429,13 +455,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 fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go if iscgo { - fn = funcPC(cgoSigtramp) + fn = abi.FuncPCABI0(cgoSigtramp) } else { - fn = funcPC(sigtramp) + fn = abi.FuncPCABI0(sigtramp) } } sa.sa_handler = fn @@ -507,3 +533,134 @@ func tgkill(tgid, tid, sig int) func signalM(mp *m, sig int) { tgkill(getpid(), int(mp.procid), sig) } + +// 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. +// 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) { + mp := getg().m + mp.profilehz = hz + + 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 + 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. + 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/os_linux_arm64.go b/src/runtime/os_linux_arm64.go index 5260f22f57396b44468b699cf849b254884963a9..2daa56fce75e533b8546f9dd75603bc5d8137243 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 498d7cec6d8e4502f01c91c992516d7939460071..537515fcf25a8f166a4e043a828f3348d2af9c4d 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 fe1973dbde6ce06a3bd359d3e53a4edbd9f30acc..bed9e66e156e2c72e1cd30f71b40fb790343908d 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 bd76442dbd843219bff013e64d5662436bb002f3..188db0103481d769d0c96d57b59a3bcad4fdc64c 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 ef8b3f7d4348230ad17663105c3966880661044d..73016f81d91b7c8beb375870f63acf2f2bb84448 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 59b5aacaebc318a142d4e8cc0bcdcf143c5ac66e..7b84f713d64c3bcf6e1e2ddf4cec81b3ec66d928 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 8104f63627f7486b462adbac1c9f8f8cddf48c9c..b06716dc6a1c7e1e568800ecaddfcb0c8e0138db 100644 --- a/src/runtime/os_linux_novdso.go +++ b/src/runtime/os_linux_novdso.go @@ -2,8 +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 && !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 package runtime diff --git a/src/runtime/os_linux_ppc64x.go b/src/runtime/os_linux_ppc64x.go index c093d2ec0f593013d479a8c8f10fe958b4940d12..25d7ccc0356c1659ec7e464f88bee6c8d6d3d9a2 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 5667774d82f055569923a94cef5f1081660a4339..c88f61fa2e99e681fe93838ae20e53ab67369af5 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_netbsd.go b/src/runtime/os_netbsd.go index 6fbb3aa6947bad99357103f6adb00364ed5b9a02..cd9508c7063f94218ff5259cb006a598b52cc944 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -5,8 +5,9 @@ package runtime import ( + "internal/abi" + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "unsafe" ) @@ -100,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 @@ -137,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) { } @@ -215,7 +226,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) @@ -251,6 +262,7 @@ func osinit() { if physPageSize == 0 { physPageSize = getPageSize() } + needSysmonWorkaround = getOSRev() < 902000000 // NetBSD 9.2 } var urandom_dev = []byte("/dev/urandom\x00") @@ -318,8 +330,8 @@ 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) { - fn = funcPC(sigtramp) + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go + fn = abi.FuncPCABI0(sigtramp) } sa.sa_sigaction = fn sigaction(i, &sa, nil) @@ -359,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 @@ -371,7 +396,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_netbsd_386.go b/src/runtime/os_netbsd_386.go index 037f7e36dc6ae730321f68e2b9f2c777cd49a06b..ac89b9852c7f64a268615180b3d885f56b88d488 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 5118b0c4ffda78c82406ef194c5575f7d445cbbe..74eea0ceabc4d9562af9f3e6ae120e08418ac34f 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 b5ec23e45b0a8833154279d37920e42ad6673802..5fb4e08d66a9158755227d0d9f53cc13132e9a0e 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 8d21b0a430f9abeecc833cf6dcb4f1e459f698b0..2dda9c9274d73bdcd44b145bf67d9379995932b1 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_nonopenbsd.go b/src/runtime/os_nonopenbsd.go index 6134b6c02f20683f7f1d35e37e1e0e8a08c4485b..a5775961e8fa876ff437b80df538ceecb3ee3175 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 3829683c807186b38ae75c84bccb22a641658ac4..0c72500674f72e1bbb48b22dbcbb0ee915ff7c3b 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.go b/src/runtime/os_openbsd.go index 6259b96c22b84e05eb2d5ac203496c3381f8cf36..2d0e71de53b5ee3c1851608843df511d52e6149c 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" ) @@ -191,8 +192,8 @@ 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) { - fn = funcPC(sigtramp) + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go + fn = abi.FuncPCABI0(sigtramp) } sa.sa_sigaction = fn sigaction(i, &sa, nil) @@ -232,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/os_openbsd_libc.go b/src/runtime/os_openbsd_libc.go index 0a342e553398a6f4d34df1030371204ad81a73a5..ff21eccb4b5759d0f31cbe9df243964023fb5564 100644 --- a/src/runtime/os_openbsd_libc.go +++ b/src/runtime/os_openbsd_libc.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 package runtime import ( + "internal/abi" "unsafe" ) @@ -48,7 +48,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/os_openbsd_syscall.go b/src/runtime/os_openbsd_syscall.go index 3cdcb6c707bfe2dfb08986e19ade174ca717d742..8128c20453b8242629d0a996a2605a9f6d32c1c7 100644 --- a/src/runtime/os_openbsd_syscall.go +++ b/src/runtime/os_openbsd_syscall.go @@ -3,12 +3,12 @@ // license that can be found in the LICENSE file. //go:build openbsd && mips64 -// +build openbsd,mips64 package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) @@ -28,12 +28,12 @@ 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 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/os_openbsd_syscall1.go b/src/runtime/os_openbsd_syscall1.go index c20ee8300e3001a8771133b6d73c2b5ad38fade0..d32894ba6a38b29d70afd6ad4f777237c2aaf684 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 af1997131feba964e06521a75f99ae5a2d8d0486..99542fb2de161786d8974b17fb96d3476205b99e 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/os_plan9.go b/src/runtime/os_plan9.go index 4d428346f0e37de08ef4763700abdc06b939c499..975d460a7da924ede62917c0b6800d826cfdf4c5 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))) } } diff --git a/src/runtime/os_solaris.go b/src/runtime/os_solaris.go index 89129e5f1acfa164f55efae7ebc6e3a4bcda98f0..8ac1b08f690a8ab59851fb5f0bc3c1406e9b2ae9 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/os_windows.go b/src/runtime/os_windows.go index f0935264ac6604b852960f2fea4164fc23e90173..c76add78025a26bb72455dc4a8728f449ade88ed 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -5,8 +5,9 @@ package runtime import ( + "internal/abi" + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "unsafe" ) @@ -322,7 +323,7 @@ func monitorSuspendResume() { if powerRegisterSuspendResumeNotification == nil { return // Running on Windows 7, where we don't need it anyway. } - var fn interface{} = func(context uintptr, changeType uint32, setting uintptr) uintptr { + var fn any = func(context uintptr, changeType uint32, setting uintptr) uintptr { for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink { if mp.resumesema != 0 { stdcall1(_SetEvent, mp.resumesema) @@ -543,7 +544,7 @@ func initLongPathSupport() { } func osinit() { - asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall)) + asmstdcallAddr = unsafe.Pointer(abi.FuncPCABI0(asmstdcall)) setBadSignalMsg() @@ -681,7 +682,7 @@ func goenvs() { // We call these all the way here, late in init, so that malloc works // for the callback functions these generate. - var fn interface{} = ctrlHandler + var fn any = ctrlHandler ctrlHandlerPC := compileCallback(*efaceOf(&fn), true) stdcall2(_SetConsoleCtrlHandler, ctrlHandlerPC, 1) @@ -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 { @@ -1193,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 } @@ -1303,18 +1306,13 @@ func setThreadCPUProfiler(hz int32) { atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz)) } -const preemptMSupported = GOARCH == "386" || GOARCH == "amd64" +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") } @@ -1385,19 +1383,42 @@ 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") 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) - } + 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) + + 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))) } } diff --git a/src/runtime/panic.go b/src/runtime/panic.go index f6c38aafcc825d30f55a92832ff10bf64de8c993..6600410cb6c5ebfb9fb22ff5d85e888d51bcff0e 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -5,8 +5,7 @@ package runtime import ( - "internal/abi" - "internal/goexperiment" + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -31,7 +30,7 @@ import ( // pc should be the program counter of the compiler-generated code that // triggered this panic. func panicCheck1(pc uintptr, msg string) { - if sys.GoarchWasm == 0 && hasPrefix(funcname(findfunc(pc)), "runtime.") { + if goarch.IsWasm == 0 && hasPrefix(funcname(findfunc(pc)), "runtime.") { // Note: wasm can't tail call, so we can't get the original caller's pc. throw(msg) } @@ -226,47 +225,27 @@ 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 func()) { gp := getg() if gp.m.curg != gp { // go code on the system stack can't defer throw("defer on system stack") } - if goexperiment.RegabiDefer && 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 - // 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() if d._panic != nil { throw("deferproc: d.panic != nil after newdefer") } d.link = gp._defer gp._defer = d 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)) - } + 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 @@ -280,12 +259,10 @@ func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn } // 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. -// 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() @@ -293,10 +270,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 { - 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 @@ -327,132 +301,37 @@ 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") - } - } -} - -// 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 !goexperiment.RegabiDefer { - throw("requires GOEXPERIMENT=regabidefer") - } - var fn func() - *(**funcval)(unsafe.Pointer(&fn)) = d.fn - return fn -} - -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] + mp := acquirem() + pp := mp.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) } + 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+args. - systemstack(func() { - total := roundupsize(totaldefersize(uintptr(siz))) - d = (*_defer)(mallocgc(total, deferType, true)) - }) + // Allocate new defer. + d = new(_defer) } - d.siz = siz d.heap = true return d } @@ -460,11 +339,16 @@ func newdefer(siz int32) *_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. +// 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() } @@ -474,53 +358,36 @@ func freedefer(d *_defer) { if !d.heap { return } - sc := deferclass(uintptr(d.siz)) - if sc >= uintptr(len(p{}.deferpool)) { - return - } - pp := getg().m.p.ptr() - if len(pp.deferpool[sc]) == cap(pp.deferpool[sc]) { + + 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[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] - 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[sc] - sched.deferpool[sc] = 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 - // started causing a nosplit stack overflow via typedmemmove. - d.siz = 0 - 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) - pp.deferpool[sc] = append(pp.deferpool[sc], d) + releasem(mp) + mp, pp = nil, nil } // Separate function so that it can split stack. @@ -535,66 +402,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. -// -// 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 - 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() } - - // 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 - 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 - 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 the stack trace can be incorrect in that case - see - // issue #8153). - _ = fn.fn - jmpdefer(fn, argp) } // Goexit terminates the goroutine that calls it. No other goroutine is affected. @@ -655,15 +495,9 @@ func Goexit() { addOneOpenDeferFrame(gp, 0, nil) } } else { - if goexperiment.RegabiDefer { - // 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, d.fn) } if p.aborted { // We had a recursive panic in the defer d we started, and @@ -726,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 @@ -774,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 @@ -783,8 +641,7 @@ func addOneOpenDeferFrame(gp *g, pc uintptr, sp unsafe.Pointer) { throw("missing deferreturn") } - maxargsize, _ := readvarintUnsafe(fd) - d1 := newdefer(int32(maxargsize)) + d1 := newdefer() d1.openDefer = true d1._panic = nil // These are the pc/sp to set after we've @@ -793,7 +650,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, @@ -845,57 +702,29 @@ 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 goexperiment.RegabiDefer && argWidth != 0 { - throw("defer with non-empty frame") - } if deferBits&(1<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 diff --git a/src/runtime/panic32.go b/src/runtime/panic32.go index acbdd1ff458d6210d96a08c3b564d72a2b39b023..fa3f2bf2f8bdf12f8a4d0af251425e84083b9782 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/plugin.go b/src/runtime/plugin.go index cd7fc5f8489a988a52affb35d62aec12353f7f81..a61dcc3b5d2d9ec7cc32994ce5cc6e1990ad7098 100644 --- a/src/runtime/plugin.go +++ b/src/runtime/plugin.go @@ -7,7 +7,7 @@ package runtime import "unsafe" //go:linkname plugin_lastmoduleinit plugin.lastmoduleinit -func plugin_lastmoduleinit() (path string, syms map[string]interface{}, errstr string) { +func plugin_lastmoduleinit() (path string, syms map[string]any, errstr string) { var md *moduledata for pmd := firstmoduledata.next; pmd != nil; pmd = pmd.next { if pmd.bad { @@ -76,11 +76,11 @@ func plugin_lastmoduleinit() (path string, syms map[string]interface{}, errstr s // Because functions are handled specially in the plugin package, // function symbol names are prefixed here with '.' to avoid // a dependency on the reflect package. - syms = make(map[string]interface{}, len(md.ptab)) + syms = make(map[string]any, len(md.ptab)) for _, ptab := range md.ptab { symName := resolveNameOff(unsafe.Pointer(md.types), ptab.name) t := (*_type)(unsafe.Pointer(md.types)).typeOff(ptab.typ) - var val interface{} + var val any valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&val)) (*valp)[0] = unsafe.Pointer(t) @@ -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(md.ftab[i].entryoff) if md.minpc <= entry && entry <= md.maxpc { continue } @@ -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/pprof/mprof_test.go b/src/runtime/pprof/mprof_test.go index b4680fbdee99ecb6c79a32e6e591745ec2664175..665487a7c4fc946a535b36afc190468e6d41a8db 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 @@ -18,7 +17,7 @@ import ( "unsafe" ) -var memSink interface{} +var memSink any func allocateTransient1M() { for i := 0; i < 1024; i++ { @@ -86,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 { @@ -105,31 +93,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.go b/src/runtime/pprof/pprof.go index 99eda10f1c1adac61215004db6bda8488ad37a85..d75efce7a8b9ff22a536f0b4bf36f78cc7148cfa 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" @@ -133,7 +134,7 @@ import ( type Profile struct { name string mu sync.Mutex - m map[interface{}][]uintptr + m map[any][]uintptr count func() int write func(io.Writer, int) error } @@ -216,7 +217,7 @@ func NewProfile(name string) *Profile { } p := &Profile{ name: name, - m: map[interface{}][]uintptr{}, + m: map[any][]uintptr{}, } profiles.m[name] = p return p @@ -276,7 +277,7 @@ func (p *Profile) Count() int { // Passing skip=0 begins the stack trace at the call to Add inside rpc.NewClient. // Passing skip=1 begins the stack trace at the call to NewClient inside mypkg.Run. // -func (p *Profile) Add(value interface{}, skip int) { +func (p *Profile) Add(value any, skip int) { if p.name == "" { panic("pprof: use of uninitialized Profile") } @@ -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() @@ -302,7 +303,7 @@ func (p *Profile) Add(value interface{}, skip int) { // Remove removes the execution stack associated with value from the profile. // It is a no-op if the value is not in the profile. -func (p *Profile) Remove(value interface{}) { +func (p *Profile) Remove(value any) { p.mu.Lock() defer p.mu.Unlock() delete(p.m, value) diff --git a/src/runtime/pprof/pprof_norusage.go b/src/runtime/pprof/pprof_norusage.go index e175dd380cfb62d51f2a48a8baa83a642a977c79..cbc5176cfa063b3b09e52ebfb7150fb714798922 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 269f21bc2f93c520d7b280af186318ad2a431627..46263fedd965da6d97598d81527ed1475ce1b3e7 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 7c71d8263be8b8e7799ea856f65f0dcbdef1dcce..d32046379a2693f5e8738c8fdacd489274078645 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 @@ -11,6 +10,7 @@ import ( "bytes" "context" "fmt" + "internal/abi" "internal/profile" "internal/testenv" "io" @@ -20,6 +20,7 @@ import ( "os/exec" "regexp" "runtime" + "runtime/debug" "strings" "sync" "sync/atomic" @@ -78,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 { @@ -88,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) @@ -106,17 +113,137 @@ func TestCPUProfileMultithreaded(t *testing.T) { }) } +func TestCPUProfileMultithreadMagnitude(t *testing.T) { + if runtime.GOOS != "linux" { + 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 + // 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) + + // 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 + 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) + }) + + 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 { +func containsInlinedCall(f any, maxBytes int) bool { _, found := findInlinedCall(f, maxBytes) return found } // 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))) +func findInlinedCall(f any, maxBytes int) (pc uint64, found bool) { + fFunc := runtime.FuncForPC(uintptr(abi.FuncPCABIInternal(f))) if fFunc == nil || fFunc.Entry() == 0 { panic("failed to locate function entry") } @@ -148,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) }) @@ -198,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) }) @@ -283,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() @@ -324,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 } @@ -349,6 +478,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 { @@ -370,35 +509,18 @@ 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) { 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) { - 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()) @@ -421,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). @@ -565,12 +725,11 @@ 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. 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 { @@ -599,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 { @@ -1132,11 +1292,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 } @@ -1216,22 +1375,23 @@ 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) { - 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) }) @@ -1242,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 { @@ -1261,6 +1422,67 @@ 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) { + 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, gogc) + }() + } + + time.Sleep(dur) + close(stop) + 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 +// samples end up running on systemstack. +func labelHog(stop chan struct{}, gogc int) { + for i := 0; ; i++ { + select { + case <-stop: + return + default: + debug.SetGCPercent(gogc) + } + } +} + // 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) { @@ -1367,6 +1589,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. }{{ @@ -1376,6 +1599,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"}, }, @@ -1392,6 +1616,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}}}, @@ -1405,6 +1630,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}}}, @@ -1423,6 +1649,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"}}, @@ -1436,6 +1663,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"}, { @@ -1459,6 +1687,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}}}, @@ -1471,6 +1700,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}}}, @@ -1483,6 +1713,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}}}, @@ -1498,6 +1729,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"}, @@ -1510,7 +1742,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) } @@ -1543,3 +1775,39 @@ 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. + + if runtime.GOOS == "android" { + // Flaky on Android, issue 48655. VDSO may not be enabled. + testenv.SkipFlaky(t, 48655) + } + + matches := matchAndAvoidStacks(stackContains, []string{"time.now"}, avoidFunctions()) + p := testCPUProfile(t, matches, 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/pprof/proto.go b/src/runtime/pprof/proto.go index bdb4454b6e1cc8d4c46f7ceead5bf9e2f01a77cc..073a076802d6ec291780aede57c11f57f5845527 100644 --- a/src/runtime/pprof/proto.go +++ b/src/runtime/pprof/proto.go @@ -8,10 +8,12 @@ import ( "bytes" "compress/gzip" "fmt" + "internal/abi" "io" "os" "runtime" "strconv" + "strings" "time" "unsafe" ) @@ -21,11 +23,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 { @@ -269,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 @@ -285,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. @@ -309,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 @@ -325,11 +326,15 @@ 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) } + + if len(tags) != 0 { + return fmt.Errorf("mismatched profile records and tags") + } return nil } @@ -585,6 +590,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 @@ -611,37 +619,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 5eb1aab14012a1d9167a8535c763788a783637db..84a051a5360d3a84eafb49d1cafc4b9dd9f23019 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" @@ -16,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() @@ -35,7 +40,7 @@ func translateCPUProfile(data []uint64) (*profile.Profile, error) { // fmtJSON returns a pretty-printed JSON form for x. // It works reasonbly well for printing protocol-buffer // data structures like profile.Profile. -func fmtJSON(x interface{}) string { +func fmtJSON(x any) string { js, _ := json.MarshalIndent(x, "", "\t") return string(js) } @@ -45,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) } @@ -97,11 +102,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} @@ -119,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) } @@ -273,11 +278,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" } @@ -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) } diff --git a/src/runtime/pprof/rusage_test.go b/src/runtime/pprof/rusage_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b0d651e0ebb20197e2e4601464f9990871e9c58e --- /dev/null +++ b/src/runtime/pprof/rusage_test.go @@ -0,0 +1,39 @@ +// 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 + +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())) +} diff --git a/src/runtime/pprof/uname_linux_test.go b/src/runtime/pprof/uname_linux_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8374c83f740af79f81bf44f35c9deebb29280197 --- /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 0000000000000000000000000000000000000000..327640755bd4dd689b9bef13f51a10f61f107661 --- /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") +} diff --git a/src/runtime/preempt.go b/src/runtime/preempt.go index 1d5aae1363193d01383b9dbb06a48e2e9b13cdde..da24f5042c0707eb9e7611196904843e0c8177e7 100644 --- a/src/runtime/preempt.go +++ b/src/runtime/preempt.go @@ -53,9 +53,9 @@ package runtime import ( + "internal/abi" + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" - "unsafe" ) type suspendGState struct { @@ -315,12 +315,12 @@ func asyncPreempt2() { var asyncPreemptStack = ^uintptr(0) func init() { - f := findfunc(funcPC(asyncPreempt)) + 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 + 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. @@ -398,18 +398,15 @@ 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). 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? @@ -450,9 +447,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 } - -var no_pointers_stackmap uint64 // defined in assembly, for NO_LOCAL_POINTERS macro diff --git a/src/runtime/preempt_386.s b/src/runtime/preempt_386.s index a803b24dc6f0b06bec126b4dc3f1904d94a28f07..d57bc3d37c061e17d6f5fed474d3005057ad8851 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 @@ -15,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) @@ -25,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 @@ -37,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 diff --git a/src/runtime/preempt_amd64.s b/src/runtime/preempt_amd64.s index dc7af806d32f3e390dab0173db9e3442265b47c1..31f7c8b66f502b6cbeccc90b7c695214614eb6b2 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 bbc9fbb1eae1d6e19640f049c2e0e87dc17ffebd..8f243c0dcd608191507494e86bac08e921241c3b 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 2b70a28479dd3572314bbf59fc48f0d8c125e7ef..36ee13282c777630eaa6e19310b236e7ada65634 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 b755425bc5d3275e6c7700d63f41e35e4120c20a..996b592ae06eb06299034fddd2fd4484bd4aa438 100644 --- a/src/runtime/preempt_mips64x.s +++ b/src/runtime/preempt_mips64x.s @@ -1,13 +1,11 @@ // Code generated by mkpreempt.go; DO NOT EDIT. //go:build mips64 || mips64le -// +build mips64 mips64le #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 c1bff60859610ce4e333d4d8b097fb026011393a..7b169acd99991bace9acef60140754edac66d3b9 100644 --- a/src/runtime/preempt_mipsx.s +++ b/src/runtime/preempt_mipsx.s @@ -1,13 +1,11 @@ // Code generated by mkpreempt.go; DO NOT EDIT. //go:build mips || mipsle -// +build mips mipsle #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_nonwindows.go b/src/runtime/preempt_nonwindows.go index 365e86a611a4daa8c56ff827b7ceed5c2ce5887e..d6a2408cb7cd2edb30f6df876abf60c8fd0e523e 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/preempt_ppc64x.s b/src/runtime/preempt_ppc64x.s index 70bd91982bfa89eff10177aeef5c66eed7f516eb..2c4d02edfe2abce01a1daccda9bbb9df6af8afe2 100644 --- a/src/runtime/preempt_ppc64x.s +++ b/src/runtime/preempt_ppc64x.s @@ -1,13 +1,11 @@ // Code generated by mkpreempt.go; DO NOT EDIT. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #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 d4f9cc277f4b62b27a8c33002fb587c53795bd43..56df6c30e07e44b8a95321c2c11b18314d01b65c 100644 --- a/src/runtime/preempt_riscv64.s +++ b/src/runtime/preempt_riscv64.s @@ -3,128 +3,125 @@ #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 - 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) +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 + 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/preempt_s390x.s b/src/runtime/preempt_s390x.s index c6f11571df77885bf1d1d9f9f0dd44a9f00262c7..ca9e47cde1791340c6df2b7ef2740ccb6fb6c225 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 da90e8aa6dd311c7049b2da5134399249f4b9147..0cf57d3d2265bbf9b5cc14623216097c15fa3cf6 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/print.go b/src/runtime/print.go index f15296cf024587f1b655ae7e75eb1103d1cb91d8..b2a642bb862f00a049757bb5d2cbf0616f9fd255 100644 --- a/src/runtime/print.go +++ b/src/runtime/print.go @@ -5,8 +5,8 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "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() @@ -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/proc.go b/src/runtime/proc.go index a144b36ec80b75cea5a41c7dabadceeaa18e9fcb..7509f7632f47037ca129c1823fe4d1eaf40d26fe 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -7,7 +7,7 @@ package runtime import ( "internal/abi" "internal/cpu" - "internal/goexperiment" + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -152,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 @@ -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") @@ -559,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) @@ -568,7 +570,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. @@ -634,13 +636,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: @@ -687,13 +694,14 @@ 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 + stkobjinit() // must run before GC starts sigsave(&_g_.m.sigmask) initSigmask = _g_.m.sigmask @@ -794,11 +802,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 { @@ -989,17 +994,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 @@ -2027,7 +2033,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 @@ -2045,7 +2051,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) @@ -2238,10 +2244,13 @@ 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)) } + if asanenabled { + asanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts)) + } execLock.rlock() // Prevent process clone. asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts)) execLock.runlock() @@ -3632,8 +3641,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 +3666,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 @@ -3664,7 +3675,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 } @@ -3672,7 +3683,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 @@ -4116,7 +4127,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 @@ -4133,14 +4147,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. @@ -4151,13 +4161,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 @@ -4232,27 +4235,14 @@ 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. -// -// 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(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) @@ -4263,24 +4253,10 @@ 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. -// -// 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 goexperiment.RegabiDefer && 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") - } - +// 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. +func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g { _g_ := getg() if fn == nil { @@ -4288,16 +4264,6 @@ func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerp throw("go of nil func value") } acquirem() // disable preemption because it can be holding p in a local var - siz := narg - siz = (siz + 7) &^ 7 - - // We could allocate a larger initial stack if necessary. - // Not worth it: this is almost always an error. - // 4*PtrSize: extra space added below - // PtrSize: caller's LR (arm) or return address (x86, in gostartcall). - if siz >= _StackMin-4*sys.PtrSize-sys.PtrSize { - throw("newproc: function arguments too large for new goroutine") - } _p_ := _g_.m.p.ptr() newg := gfget(_p_) @@ -4314,8 +4280,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*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 if usesLR { @@ -4324,24 +4290,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 @@ -4364,6 +4312,7 @@ func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerp 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, @@ -4504,6 +4453,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 } @@ -4717,6 +4669,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 @@ -4734,12 +4687,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 { @@ -4749,72 +4702,40 @@ 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". 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 } } } if prof.hz != 0 { - cpuprof.add(gp, stk[:n]) - } - 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, - funcPC(_ExternalCode) + sys.PCQuantum, + // 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.addNonGo(stk) + cpuprof.add(tagPtr, stk[:n]) } + getg().m.mallocing-- } // setcpuprofilerate sets the CPU profiling rate to hz times per second. @@ -4861,9 +4782,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 { @@ -4940,12 +4859,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. @@ -5308,6 +5225,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 @@ -5416,7 +5337,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 @@ -5951,7 +5872,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 } @@ -6064,14 +5985,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 { @@ -6236,7 +6155,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 { @@ -6470,7 +6389,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) } @@ -6491,9 +6410,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() } @@ -6503,7 +6422,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(abi.FuncPCABIInternal(f))) var sbuf [24]byte print("init ", pkg, " @") diff --git a/src/runtime/proc_test.go b/src/runtime/proc_test.go index 53cafe8907fc0962f5b13cd3df15fa1dbfb2dc88..cc899a24c677acbd83a7cee7a9437f0f58677554 100644 --- a/src/runtime/proc_test.go +++ b/src/runtime/proc_test.go @@ -119,6 +119,10 @@ 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)) + // 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) x := uint32(0) @@ -163,6 +167,10 @@ 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)) + // 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 { // Create P goroutines and wait until they all run. @@ -623,6 +631,10 @@ 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)) + // 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) if testing.Short() { diff --git a/src/runtime/race.go b/src/runtime/race.go index ce6b5b54681533bee45a198fccd9ad884b9aa642..e019923bb5c67109f0fad3f6d0bd6dd219d50426 100644 --- a/src/runtime/race.go +++ b/src/runtime/race.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. //go:build race -// +build race package runtime import ( + "internal/abi" "unsafe" ) @@ -361,7 +361,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/README b/src/runtime/race/README index 3b188a03619fc72a9e8c450fab63351c130c89d9..d3c55182ef9c1cb8853277713fa7e8a03bb2c10c 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/output_test.go b/src/runtime/race/output_test.go index 99052071d0089d6a716e065c704fbbfa16b93e1f..46cdfcd0e98b65d7825ccbfd46fdba46fc58083f 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 @@ -148,7 +147,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 +161,7 @@ func main() { package main func main() { done := make(chan bool) - x := 0 + x := 0; _ = x go func() { x = 42 done <- true @@ -178,7 +177,7 @@ func main() { package main func main() { done := make(chan bool) - x := 0 + x := 0; _ = x go func() { x = 42 done <- true diff --git a/src/runtime/race/race.go b/src/runtime/race/race.go index 84050e877111818583a9ac4d074989418a7ef2a5..63fa83ff146c922e78a1b8a9e71e7c31c7e6cdf1 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_darwin_amd64.syso b/src/runtime/race/race_darwin_amd64.syso index 3f95ecc8eef955f005a017f3820ae1f3556f9826..6fbe140026f0a8391d3dfb4581d37a16dacbd375 100644 Binary files a/src/runtime/race/race_darwin_amd64.syso and b/src/runtime/race/race_darwin_amd64.syso differ diff --git a/src/runtime/race/race_darwin_arm64.syso b/src/runtime/race/race_darwin_arm64.syso index f6eaa62ae3a88744f0f79d1ed6e9645909d1110c..207099eb1d0808327960892de7712c7845d42337 100644 Binary files a/src/runtime/race/race_darwin_arm64.syso and b/src/runtime/race/race_darwin_arm64.syso differ diff --git a/src/runtime/race/race_linux_test.go b/src/runtime/race/race_linux_test.go index 9c0d48d6bda6c589cb6961f70f7b11704ac0c591..e8a2d0fd8c91c44e0c9b3aa100b97280e21a02e8 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 8c880b857007a1157a66131fa07dadd8d943e694..4fe61683eb02d7f624d8953b05342b9d66105d61 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. @@ -188,7 +187,7 @@ func runTests(t *testing.T) ([]byte, error) { func TestIssue8102(t *testing.T) { // If this compiles with -race, the test passes. type S struct { - x interface{} + x any i int } c := make(chan int) diff --git a/src/runtime/race/race_unix_test.go b/src/runtime/race/race_unix_test.go index acd6e47f9827645b6b82d56694382f9bf33e621b..6cc0730589f33b37aa6a00699237d2df635f3a4b 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 e490d766dd05ddb91880abf05b0421a3fdc9f2d2..143b483f97f8903c3e76c38843c9730bbbd0ec67 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 e904ebd20d8c1c699407e374404acaff217aedb2..9fe83ea11d35e5acb03aa199f9e62e9e57179a82 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 f5095737a4f632e97770c953094c3ac4ae17f236..2f1a91cab1d9c12b5d7b02481f77b1e512217c2c 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/testdata/issue12664_test.go b/src/runtime/race/testdata/issue12664_test.go index c9f790edc853622b5a4ad85c4af2d6082b9517a0..714e83d318b2568cdbb42e2e386908689202d055 100644 --- a/src/runtime/race/testdata/issue12664_test.go +++ b/src/runtime/race/testdata/issue12664_test.go @@ -56,7 +56,7 @@ func TestRaceIssue12664_3(t *testing.T) { close(c) }() var r MyT - var i interface{} = r + var i any = r issue12664_3 = i.(MyT) <-c } diff --git a/src/runtime/race/testdata/mop_test.go b/src/runtime/race/testdata/mop_test.go index 5d25ed4bb64f5f0c039823ea9edba9631ee3d34d..2d093739dfbd5e792b6c846b3bb4c14b0111a525 100644 --- a/src/runtime/race/testdata/mop_test.go +++ b/src/runtime/race/testdata/mop_test.go @@ -255,7 +255,7 @@ func TestRaceCaseIssue6418(t *testing.T) { func TestRaceCaseType(t *testing.T) { var x, y int - var i interface{} = x + var i any = x c := make(chan int, 1) go func() { switch i.(type) { @@ -270,7 +270,7 @@ func TestRaceCaseType(t *testing.T) { func TestRaceCaseTypeBody(t *testing.T) { var x, y int - var i interface{} = &x + var i any = &x c := make(chan int, 1) go func() { switch i := i.(type) { @@ -288,8 +288,8 @@ func TestRaceCaseTypeIssue5890(t *testing.T) { // spurious extra instrumentation of the initial interface // value. var x, y int - m := make(map[int]map[int]interface{}) - m[0] = make(map[int]interface{}) + m := make(map[int]map[int]any) + m[0] = make(map[int]any) c := make(chan int, 1) go func() { switch i := m[0][1].(type) { @@ -758,7 +758,7 @@ func TestRaceStructFieldRW3(t *testing.T) { } func TestRaceEfaceWW(t *testing.T) { - var a, b interface{} + var a, b any ch := make(chan bool, 1) go func() { a = 1 @@ -810,7 +810,7 @@ func TestRaceEfaceConv(t *testing.T) { c := make(chan bool) v := 0 go func() { - go func(x interface{}) { + go func(x any) { }(v) c <- true }() @@ -1127,7 +1127,7 @@ func TestRaceRune(t *testing.T) { func TestRaceEmptyInterface1(t *testing.T) { c := make(chan bool) - var x interface{} + var x any go func() { x = nil c <- true @@ -1138,7 +1138,7 @@ func TestRaceEmptyInterface1(t *testing.T) { func TestRaceEmptyInterface2(t *testing.T) { c := make(chan bool) - var x interface{} + var x any go func() { x = &Point{} c <- true @@ -1579,7 +1579,7 @@ func TestRaceAddrExpr(t *testing.T) { func TestRaceTypeAssert(t *testing.T) { c := make(chan bool, 1) x := 0 - var i interface{} = x + var i any = x go func() { y := 0 i = y diff --git a/src/runtime/race/testdata/pool_test.go b/src/runtime/race/testdata/pool_test.go index 161f4b7c23b53678e7db638cc76f33065ab2b176..a96913e3814a534b4aad61bddad61822b1073a8d 100644 --- a/src/runtime/race/testdata/pool_test.go +++ b/src/runtime/race/testdata/pool_test.go @@ -15,7 +15,7 @@ func TestRacePool(t *testing.T) { // Repeat so that at least one iteration gets reuse. for i := 0; i < 10; i++ { c := make(chan int) - p := &sync.Pool{New: func() interface{} { return make([]byte, 10) }} + p := &sync.Pool{New: func() any { return make([]byte, 10) }} x := p.Get().([]byte) x[0] = 1 p.Put(x) @@ -31,7 +31,7 @@ func TestRacePool(t *testing.T) { func TestNoRacePool(t *testing.T) { for i := 0; i < 10; i++ { - p := &sync.Pool{New: func() interface{} { return make([]byte, 10) }} + p := &sync.Pool{New: func() any { return make([]byte, 10) }} x := p.Get().([]byte) x[0] = 1 p.Put(x) diff --git a/src/runtime/race/timer_test.go b/src/runtime/race/timer_test.go index f11f8456a0fd4a95ae6417ac813fba6c112ca03e..dd59005564273abc0749742c99bd3bdb8151d495 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 0e431b8103e060323b4080a096aa59451335cf28..f36d4387c74fe2bd46178982f00d4fe9ab322df6 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/race_amd64.s b/src/runtime/race_amd64.s index 8d4813eadddd5e68a9303a2658d7c7920c22d056..f055acf77dd3edd69b38f9eadd0fb93b152d34b5 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" @@ -46,11 +45,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 +71,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 +122,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 @@ -161,10 +147,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 +174,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 +186,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 +344,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 +355,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 +382,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 @@ -441,9 +403,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/race_arm64.s b/src/runtime/race_arm64.s index c6d5b91edc0f3ee8a7bd29f081b9f78d639d46ad..798e23294a0237663aec88a4da08e4c4d2bb2a25 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" @@ -43,8 +42,14 @@ // 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 +#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 @@ -66,8 +71,14 @@ 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 +#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 @@ -89,9 +100,16 @@ 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 +#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 @@ -114,9 +132,16 @@ 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 +#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 diff --git a/src/runtime/race_ppc64le.s b/src/runtime/race_ppc64le.s index 963e57099c9c4c3b0ca283fe6172b79a5e00cc7b..68cc5c880578296ee996f6d43e7cf64cbb40a69c 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" @@ -43,8 +42,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 +67,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 +92,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 +120,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 diff --git a/src/runtime/relax_stub.go b/src/runtime/relax_stub.go index 5b92879c20bc5ce3dba3b9063349c527e235bbc2..e507702fc10e83a94b4205b6540ebd3b699cfb3e 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/rt0_linux_mips64x.s b/src/runtime/rt0_linux_mips64x.s index fabd8570b57970f599aef2f7cb2524c8124f0f85..e9328b73263199ddbbc478288e986ee69ee5d6d6 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 9f5842b51a28b3145cf1be2dcbc6bb931aaf9499..3cbb7fc37713c7d5c65574364c2a0569df890ee9 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/rt0_linux_riscv64.s b/src/runtime/rt0_linux_riscv64.s index f31f7f75e5153e3645fc2f85df6ad48fd6ab0c6d..d6b8ac85dca6468065b71d11e831fca5c1722356 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 diff --git a/src/runtime/runtime-gdb.py b/src/runtime/runtime-gdb.py index 8d96dfb6094ae077734592528db84afcc36d1feb..5bb605cc37b567abfd90457b24be15718fb27b6a 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] diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go index 8c76a9123c69ef7ec7f57fe9beebfa8cdbc8631b..63d3160ee47716196e748d990cc4518ddfd88fc6 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 @@ -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) diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index b238da8f514e42b7973a0c148621a0ebb1e6e249..65e1e0eebca1c1ded1e54c6fad41a5fb6b0cfa29 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -6,8 +6,8 @@ package runtime import ( "internal/bytealg" + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "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 { @@ -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() { diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 5051ec4d3e95eed3f46fde743261d9f19628d385..ec34e7ac1ae873b97a8a70d0336f0029d2381171 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -5,8 +5,8 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "unsafe" ) @@ -209,7 +209,7 @@ type eface struct { data unsafe.Pointer } -func efaceOf(ep *interface{}) *eface { +func efaceOf(ep *any) *eface { return (*eface)(unsafe.Pointer(ep)) } @@ -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 { @@ -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 @@ -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 @@ -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 @@ -795,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. @@ -858,8 +864,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 { - entry 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,8 +885,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 uint32 // set to ^0 to distinguish from _func + entry uintptr // entry of the real (the "outermost") frame name string file string line int @@ -924,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 @@ -934,25 +940,24 @@ 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/reflectdata/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 // 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 - link *_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 // 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 @@ -977,7 +982,7 @@ type _defer struct { // adjustment takes care of them. type _panic struct { argp unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink - arg interface{} // argument to panic + arg any // argument to panic link *_panic // link to earlier panic pc uintptr // where to return to in runtime if this panic is bypassed sp unsafe.Pointer // where to return to in runtime if this panic is bypassed @@ -1129,7 +1134,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 ) diff --git a/src/runtime/runtime_linux_test.go b/src/runtime/runtime_linux_test.go index cd59368cb2af4311ee0bca69cd64aade889350f9..a753aeea583d66e549faa192421f9134d5febc20 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) + } +} diff --git a/src/runtime/runtime_mmap_test.go b/src/runtime/runtime_mmap_test.go index f71f8afa5746aeb115bf233a3d238de8ee61ec06..9323c093557da405d35b45b569210d64f749cd1f 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_test.go b/src/runtime/runtime_test.go index 4572a25195d3e6fbf3843f09762b1032213c3db6..1ca1fa2f05ebe971bfd090dfa623a7d1879a4eb5 100644 --- a/src/runtime/runtime_test.go +++ b/src/runtime/runtime_test.go @@ -53,8 +53,8 @@ func BenchmarkIfaceCmpNil100(b *testing.B) { } } -var efaceCmp1 interface{} -var efaceCmp2 interface{} +var efaceCmp1 any +var efaceCmp2 any func BenchmarkEfaceCmpDiff(b *testing.B) { x := 5 diff --git a/src/runtime/runtime_unix_test.go b/src/runtime/runtime_unix_test.go index 0251c676e6df6b171c38752a4e2f9671a29bc2be..642a9462803a998d8ecaf13a8af46d0dce508b0c 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/rwmutex_test.go b/src/runtime/rwmutex_test.go index 291a32ea5ec31975231223b13cfce74319db943a..f15d367b326fb9552f1e7f431cae77b18913afb7 100644 --- a/src/runtime/rwmutex_test.go +++ b/src/runtime/rwmutex_test.go @@ -55,6 +55,11 @@ 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)) + // 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) doTestParallelReaders(3) doTestParallelReaders(4) diff --git a/src/runtime/select.go b/src/runtime/select.go index 06edb69f429ba0c1ac01279de0204d10e71bda8a..e18b2f14c08cc1b3b5bf838dca6899a3975cea00 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) { @@ -405,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 @@ -420,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 { @@ -443,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 { @@ -481,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/semasleep_test.go b/src/runtime/semasleep_test.go index 905e932b7d857efb1643e9fc314b7693a1222a45..d56733c0cf195b46080926bf2a31ebfc18a7754e 100644 --- a/src/runtime/semasleep_test.go +++ b/src/runtime/semasleep_test.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. //go:build !plan9 && !windows && !js -// +build !plan9,!windows,!js package runtime_test import ( + "io" "os/exec" "syscall" "testing" @@ -21,43 +21,83 @@ 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 { 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. + 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) + } + + // 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 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(ready) > timeout { + t.Error("Program failed to return on time and has to be killed, issue #27520 still exists") + // 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 + } + // 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(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.") } return diff --git a/src/runtime/sigaction.go b/src/runtime/sigaction.go index 30050efcc78a022bead6ffa9961a9b425a7fe29b..05f44f65dbcd5614499fd1a0e2393ffdb0bc213b 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 5824eaddb5630d5b2dc49bc68532c974cde09d81..aa66032caa361a163cbb8d04eecf9f2c0c531ad3 100644 --- a/src/runtime/signal_386.go +++ b/src/runtime/signal_386.go @@ -3,12 +3,12 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) @@ -42,17 +42,17 @@ 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))) } } 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 a0becd431ebdf6728d93449ada1eca644606cbf9..c6cb91a0a25731e06804ef9552f3d3219ae1852f 100644 --- a/src/runtime/signal_aix_ppc64.go +++ b/src/runtime/signal_aix_ppc64.go @@ -3,12 +3,11 @@ // license that can be found in the LICENSE file. //go:build aix -// +build aix package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -82,5 +81,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 e45fbb4a87a39f8c95973d209c1d93c07b00fd59..67a21950d715b37f33a0924fc5dfcb43eb1b3652 100644 --- a/src/runtime/signal_amd64.go +++ b/src/runtime/signal_amd64.go @@ -3,13 +3,12 @@ // 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 import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) @@ -70,17 +69,17 @@ 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))) } } 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_arm.go b/src/runtime/signal_arm.go index 4d9c6224a29d1e6a64174b38fadcf22f8995b3c1..fff302f4d4b92b9cfac520b7660ea8c4a1a11ab3 100644 --- a/src/runtime/signal_arm.go +++ b/src/runtime/signal_arm.go @@ -3,11 +3,13 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) func dumpregs(c *sigctxt) { print("trap ", hex(c.trap()), "\n") @@ -61,7 +63,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 f04750084f4b011e5028ed08375548530a4d0318..771585a8f9b392e58c9dda4cd4968c2c8ebba60a 100644 --- a/src/runtime/signal_arm64.go +++ b/src/runtime/signal_arm64.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. //go:build darwin || freebsd || linux || netbsd || openbsd -// +build darwin freebsd linux netbsd openbsd package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -77,7 +77,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_386.go b/src/runtime/signal_linux_386.go index 13d9df407102e5fc366fc598d7988fc6127c1547..321518c18e3f50a681280270b8e50910e6716735 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 210e8967e5da299c473920af3cee344e77eaf084..573b11839740de5c436482202fc89a07141ad3fe 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 876b505917394fc9875fdc81ce637d7d2a0f6365..eb107d68d1b181937ead1fa64089b647d5b0b931 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 2075f253d7d0f848e897bee7ba74015a3762dde7..4ccc03079235465e3301365c7e6cf7f156549c21 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 f0a75ac3ea571598ab610b547b0c2d1109c234e0..9c2a286001660308f566c0fa72997df63df9197b 100644 --- a/src/runtime/signal_linux_mips64x.go +++ b/src/runtime/signal_linux_mips64x.go @@ -3,13 +3,11 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -75,5 +73,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_mipsx.go b/src/runtime/signal_linux_mipsx.go index f3969c5aac4a7468fd275ca2ea6617c36a9664ce..f11bfc9b3a2c79072f6d57a8d5b84fd8e60fc1c4 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 d9d3e55ec2000976a2935b4962018fbc61f2ad44..31754289ece3674ec3d0dfd6c5ae3ec1d775a102 100644 --- a/src/runtime/signal_linux_ppc64x.go +++ b/src/runtime/signal_linux_ppc64x.go @@ -3,13 +3,11 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -79,5 +77,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 9f68e5c548fb45b44300fc26efad510d6e6c5f97..b26450dbfac5cdbc2cfc4d1a236e41f4ab2bc0e7 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 12d5c315931c89c5764e6813edbf55485b9c58be..18c3b115efc87f05b249d2ba51173d4388fdba2e 100644 --- a/src/runtime/signal_linux_s390x.go +++ b/src/runtime/signal_linux_s390x.go @@ -5,6 +5,8 @@ package runtime import ( + "internal/abi" + "internal/goarch" "runtime/internal/sys" "unsafe" ) @@ -53,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) { @@ -107,7 +109,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 1616b570278a0ce8f91e0f702007b4f5677aba81..cee1bf7a1b23dcd1d566fe77138c9d343120c592 100644 --- a/src/runtime/signal_mips64x.go +++ b/src/runtime/signal_mips64x.go @@ -3,13 +3,12 @@ // license that can be found in the LICENSE file. //go:build (linux || openbsd) && (mips64 || mips64le) -// +build linux openbsd -// +build mips64 mips64le package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) @@ -68,7 +67,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() @@ -80,7 +79,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 dcc7f1e9dd5e035e4caae63fbef5d181be917d2d..ba92655152e84b2dc791892d6da9228f8669e8f6 100644 --- a/src/runtime/signal_mipsx.go +++ b/src/runtime/signal_mipsx.go @@ -3,12 +3,11 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -78,7 +77,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 f2225da9a1771d53decc142e532630605f8a5da4..bdd354026cb0ad04c8eb61b78692cf4ed3d7a3c4 100644 --- a/src/runtime/signal_ppc64x.go +++ b/src/runtime/signal_ppc64x.go @@ -3,12 +3,11 @@ // license that can be found in the LICENSE file. //go:build (aix || linux) && (ppc64 || ppc64le) -// +build aix linux -// +build ppc64 ppc64le package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -83,8 +82,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 e6b1b14130e53b3960f57152d5b8926da2781759..5eeb227aa05862f92a801865e464f785f4d281f3 100644 --- a/src/runtime/signal_riscv64.go +++ b/src/runtime/signal_riscv64.go @@ -3,12 +3,12 @@ // license that can be found in the LICENSE file. //go:build linux && riscv64 -// +build linux,riscv64 package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) @@ -63,7 +63,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() @@ -76,7 +76,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) { @@ -84,7 +84,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/signal_unix.go b/src/runtime/signal_unix.go index 6096760b50c2420cf8bd39ec4ea62e92ec668917..dbcbfc67bca3af97ba65e694faf66fd4b3941979 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -3,12 +3,13 @@ // 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 import ( + "internal/abi" "runtime/internal/atomic" + "runtime/internal/sys" "unsafe" ) @@ -143,7 +144,7 @@ func initsig(preinit bool) { } handlingSig[i] = 1 - setsig(i, funcPC(sighandler)) + setsig(i, abi.FuncPCABIInternal(sighandler)) } } @@ -166,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 } @@ -194,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)) } } } @@ -262,16 +263,16 @@ 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) { atomic.Storeuintptr(&fwdSig[_SIGPROF], getsig(_SIGPROF)) - setsig(_SIGPROF, funcPC(sighandler)) + setsig(_SIGPROF, abi.FuncPCABIInternal(sighandler)) } var it itimerval @@ -308,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 } @@ -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) } } @@ -382,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. @@ -422,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 { @@ -464,6 +469,56 @@ 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. +// +// 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(sig uint32, info *siginfo, ctx unsafe.Pointer) { + if prof.hz != 0 { + 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]) + } + } + + 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. @@ -539,7 +594,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 } @@ -627,9 +687,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. @@ -843,7 +905,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/signal_windows.go b/src/runtime/signal_windows.go index b720ddcf164ea51482ddaca0dd58f080dda6d433..16c36d07f14cd7a976f17ec95384ee5273b7ddce 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 } @@ -217,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/signal_windows_test.go b/src/runtime/signal_windows_test.go index 1b7cb9d4c453aeb930fbe11a5403205a1b643ace..7c88ab573eab2ad033a5d087f2736e30b4664e2a 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 6c91fb3fb3538c7202451ffd2960c2c3fb9fb40e..7b84a0ef65742d211baeebcd6d22f6f8e13814b4 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 e23446bea47b776bf48189390f2906f3a24f0176..fb1a517fa5733078880642f5baf3d2566a6484e8 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 dc1debddab3c4f4d90a4187dc15cfdc4999fa8ec..fe93bbafb5988ae65990f9452882296f05882f59 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 af9c7e56eb907c48785b7ae2f715ea9e51cab00c..295ced5bbbbe48b6910da6135a9b39f6ef265bc4 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/sizeof_test.go b/src/runtime/sizeof_test.go index bbbd1becf7a070ecb197193921b1081cc7b3259d..ebf544ad3b96cf2f22bd17dd707602173f3e0d68 100644 --- a/src/runtime/sizeof_test.go +++ b/src/runtime/sizeof_test.go @@ -17,9 +17,9 @@ func TestSizeof(t *testing.T) { const _64bit = unsafe.Sizeof(uintptr(0)) == 8 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 }{ {runtime.G{}, 236, 392}, // g, but exported for testing {runtime.Sudog{}, 56, 88}, // sudog, but exported for testing diff --git a/src/runtime/slice.go b/src/runtime/slice.go index 01cdcaeee3b0b1e0b7d0395ed339f970be4f2036..ac0b7d5fefc51e95b77fe4764f0b5225c18413c2 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -5,6 +5,8 @@ package runtime import ( + "internal/abi" + "internal/goarch" "runtime/internal/math" "runtime/internal/sys" "unsafe" @@ -68,12 +70,15 @@ 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 { msanread(from, copymem) } + if asanenabled { + asanread(from, copymem) + } memmove(to, from, copymem) @@ -113,16 +118,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 > maxAlloc || len < 0 { + if overflow || mem > -uintptr(ptr) { + if ptr == nil { + panic(errorString("unsafe.Slice: ptr is nil and len is not zero")) + } panicunsafeslicelen() } } @@ -162,11 +166,14 @@ 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))) } + if asanenabled { + asanread(old.array, uintptr(old.len*int(et.size))) + } if cap < old.cap { panic(errorString("growslice: cap out of range")) @@ -183,13 +190,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. @@ -212,15 +223,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 { @@ -298,7 +309,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) } @@ -306,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/softfloat64.go b/src/runtime/softfloat64.go index 13bee6c1d7a06499d838ef6cf2356f1dd3db9774..42ef0092970b3e2525b65fa1c4cf5559d51b44d7 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 { @@ -562,36 +582,46 @@ 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 { + 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) } diff --git a/src/runtime/softfloat64_test.go b/src/runtime/softfloat64_test.go index 7347aff8f13c7c08753880da3958ebf6578fab3a..3f53e8bc55810cfb9cbd67961cbd958d9a7b2067 100644 --- a/src/runtime/softfloat64_test.go +++ b/src/runtime/softfloat64_test.go @@ -127,7 +127,7 @@ func fromint64sw(f float64) float64 { var nerr int -func err(t *testing.T, format string, args ...interface{}) { +func err(t *testing.T, format string, args ...any) { t.Errorf(format, args...) // cut errors off after a while. diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 6e0d157630b47ad540d8f0e7967748ba4b628da0..edc37d4878fb2dd42bedeaf4268e953a01a677f2 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -7,6 +7,8 @@ package runtime import ( "internal/abi" "internal/cpu" + "internal/goarch" + "internal/goos" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -67,7 +69,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 = goos.IsWindows*512*goarch.PtrSize + goos.IsPlan9*512 + goos.IsIos*goarch.IsArm64*1024 // The minimum size of stack used by Go code _StackMin = 2048 @@ -125,7 +127,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. @@ -142,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. @@ -422,6 +427,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") } @@ -459,6 +467,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 @@ -599,14 +610,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 +666,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 goarch.ArchFamily == goarch.AMD64 && frame.argp-frame.varp == 2*goarch.PtrSize { if stackDebug >= 3 { print(" saved bp\n") } @@ -689,7 +700,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 { @@ -703,15 +715,15 @@ 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 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)) } } @@ -753,11 +765,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) { @@ -854,6 +861,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)) @@ -969,7 +981,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", @@ -990,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. @@ -1004,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. @@ -1017,9 +1030,9 @@ 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 -= 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", @@ -1071,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). @@ -1114,7 +1127,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)) } @@ -1201,7 +1214,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) @@ -1244,7 +1256,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 @@ -1262,8 +1274,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 @@ -1298,7 +1310,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. } @@ -1320,17 +1332,17 @@ 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" || 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 - // on amd64. - objs = methodValueCallFrameObjs + // 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) 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: @@ -1343,23 +1355,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 any = 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. @@ -1368,10 +1390,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 { @@ -1386,6 +1408,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/stack_test.go b/src/runtime/stack_test.go index 43fc5cac55fba1911ff313bcec98f5ee3f0e4166..4c2671b31f0fd6a3db79dc008ee908d506ad6654 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 { @@ -851,7 +879,7 @@ func deferHeapAndStack(n int) (r int) { } // Pass a value to escapeMe to force it to escape. -var escapeMe = func(x interface{}) {} +var escapeMe = func(x any) {} // Test that when F -> G is inlined and F is excluded from stack // traces, G still appears. diff --git a/src/runtime/string.go b/src/runtime/string.go index d6030a1dca433b0d168d62665d930ba34b06965e..980a9866e669516540bb41773c6852043baf481b 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -5,8 +5,9 @@ package runtime import ( + "internal/abi" "internal/bytealg" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -88,14 +89,17 @@ 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)) } + if asanenabled { + asanread(unsafe.Pointer(ptr), uintptr(n)) + } if n == 1 { p := unsafe.Pointer(&staticuint64s[*ptr]) - if sys.BigEndian { + if goarch.BigEndian { p = add(p, 7) } stringStructOf(&str).str = p @@ -152,11 +156,14 @@ 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)) } + if asanenabled && n > 0 { + asanread(unsafe.Pointer(ptr), uintptr(n)) + } stringStructOf(&str).str = unsafe.Pointer(ptr) stringStructOf(&str).len = n return @@ -203,11 +210,14 @@ 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])) } + 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/stubs.go b/src/runtime/stubs.go index 16d758320294509575295ad3388b747d5e159d85..ad78363bb67b1184a51eb75be1efff5f489c979a 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -6,7 +6,9 @@ package runtime import ( "internal/abi" + "internal/goarch" "internal/goexperiment" + "runtime/internal/math" "unsafe" ) @@ -118,20 +120,32 @@ 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 { 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 } @@ -142,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() } @@ -176,8 +190,6 @@ func cgocallback(fn, frame, ctxt uintptr) func gogo(buf *gobuf) -//go:noescape -func jmpdefer(fv *funcval, argp uintptr) func asminit() func setg(gg *g) func breakpoint() @@ -421,12 +433,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) diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go index 525b324c8163bd29ad5485ea53bda1397f5a22f6..9aa965454d991a4fda9dd84c786d65f5d9f94f8d 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 b895be4c707519940dc354a892cc69f37b63ea45..891663b1109b1981bb664d3d284c9ea8ac347937 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_arm64.go b/src/runtime/stubs_arm64.go index f5e3bb4854083c5ef80f7b8d251c8a10865ba195..bd0533d158125a88eae804607274b40200eeba62 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() diff --git a/src/runtime/stubs_linux.go b/src/runtime/stubs_linux.go index ba267009ca11f8b5e86d1b4871f1b51316be7017..06c14e21601d65c5aac0d5fee111af9fd7a97eb2 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 05a4d0d38d5f87d0d9312958f06b93eab6d1896e..a9ddfc02568caeeac512a481ec15f39bcea98fb7 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 9bffb35b67e9200e41ba154baa1a04199875af73..d48f9b88e82ecfb9203082255d1a4cead272a9f1 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 f9b98595fc4403a2ea796a7728cdfc42248bf335..1a06d7cc1d6dc05027be682cf4676eecb013159b 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 f692947109abbb6445d9065934b6be2d885e0efb..07127629d19f6839280c251ab1231e7f876abda7 100644 --- a/src/runtime/stubs_ppc64.go +++ b/src/runtime/stubs_ppc64.go @@ -3,14 +3,9 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux 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 59% rename from src/runtime/stubs_ppc64le.go rename to src/runtime/stubs_ppc64x.go index 5b733136e3b57a5722f85ac57b8eb4500bf348a6..95e43a5162adb430bcb7aa183f5041b1f6ef16e4 100644 --- a/src/runtime/stubs_ppc64le.go +++ b/src/runtime/stubs_ppc64x.go @@ -2,9 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go: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() diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 999300a58ec3404baf8ec991b522ffe942b096fe..21dd95a3974e8993891b42446413c40c7ee17400 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -205,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 } @@ -271,8 +272,26 @@ func (f *Func) raw() *_func { } func (f *Func) funcInfo() funcInfo { - fn := f.raw() - return funcInfo{fn, findmoduledatap(fn.entry)} + 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(f)) + 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{f, mod} } // PCDATA and FUNCDATA table indexes. @@ -282,6 +301,7 @@ const ( _PCDATA_UnsafePoint = 0 _PCDATA_StackMapIndex = 1 _PCDATA_InlTreeIndex = 2 + _PCDATA_ArgLiveIndex = 3 _FUNCDATA_ArgsPointerMaps = 0 _FUNCDATA_LocalsPointerMaps = 1 @@ -289,6 +309,7 @@ const ( _FUNCDATA_InlTree = 3 _FUNCDATA_OpenCodedDeferInfo = 4 _FUNCDATA_ArgInfo = 5 + _FUNCDATA_ArgLiveInfo = 6 _ArgsSizeUnknown = -0x80000000 ) @@ -330,7 +351,6 @@ const ( funcID_gogo funcID_gopanic funcID_handleAsyncEvent - funcID_jmpdefer funcID_mcall funcID_morestack funcID_mstart @@ -365,26 +385,30 @@ 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. 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. + 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 - 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 } // 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 { @@ -405,6 +429,8 @@ type moduledata struct { noptrbss, enoptrbss uintptr end, gcdata, gcbss uintptr types, etypes uintptr + rodata uintptr + gofunc uintptr // go.func.* textsectmap []textsect typelinks []int32 // offsets from types @@ -503,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)) } } @@ -529,15 +558,15 @@ func modulesinit() { } type functab struct { - entry uintptr - funcoff uintptr + entryoff uint32 // relative to runtime.text + funcoff uint32 } // Mapping information for secondary text sections type textsect struct { vaddr uintptr // prelinked section vaddr - length uintptr // section length + end uintptr // vaddr + section length baseaddr uintptr // relocated section address } @@ -568,33 +597,28 @@ 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 { - 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 != 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, "pcHeader.textStart=", hex(hdr.textStart), + "text=", hex(datap.text), "pluginpath=", datap.pluginpath) + throw("invalid function symbol table") } // ftab is lookup table for function by program counter. 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) } - 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 offset:", hex(datap.ftab[i].entryoff), funcname(f1), ">", hex(datap.ftab[i+1].entryoff), 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].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") @@ -603,8 +627,10 @@ func moduledataverify1(datap *moduledata) { } } - if datap.minpc != datap.ftab[0].entry || - datap.maxpc != datap.ftab[nftab].entry { + min := datap.textAddr(datap.ftab[0].entryoff) + 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") } @@ -616,6 +642,69 @@ 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 ends to determine the containing section. +// Then the section relative offset is added to the section's +// relocated baseaddr to compute the function address. +// +// It is nosplit because it is part of the findfunc implementation. +//go:nosplit +func (md *moduledata) textAddr(off32 uint32) uintptr { + off := uintptr(off32) + res := md.text + off + if len(md.textsectmap) > 1 { + 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 + } + } + 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 +} + +// 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. // @@ -637,7 +726,8 @@ func FuncForPC(pc uintptr) *Func { name := funcnameFromNameoff(f, inltree[ix].func_) file, line := funcline(f, pc) fi := &funcinl{ - entry: f.entry, // entry of the real (the outermost) function. + ones: ^uint32(0), + entry: f.entry(), // entry of the real (the outermost) function. name: name, file: file, line: int(line), @@ -654,7 +744,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 } @@ -664,11 +754,11 @@ 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 } - return fn.entry + return fn.funcInfo().entry() } // FileLine returns the file name and line number of the @@ -677,7 +767,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 } @@ -715,6 +805,16 @@ 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.entryoff == ^uint32(0) // see comment for funcinl.ones +} + +// entry returns the entry PC for f. +func (f funcInfo) entry() uintptr { + return f.datap.textAddr(f.entryoff) +} + // findfunc looks up function metadata for a PC. // // It is nosplit because it's part of the isgoexception @@ -728,44 +828,24 @@ 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) 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) + // Find the ftab entry. + for datap.ftab[idx+1].entryoff <= pcOff { + idx++ } - if pc < datap.ftab[idx].entry { - // 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 { - 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 { - idx++ - } - } funcoff := datap.ftab[idx].funcoff - if funcoff == ^uintptr(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} } @@ -786,7 +866,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. @@ -819,19 +899,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") + println("runtime: no module data for", hex(f.entry())) 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 } @@ -845,7 +925,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, @@ -868,11 +948,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 } @@ -955,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&(sys.PtrSize-1) != 0 { - print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n") + 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 } @@ -965,12 +1046,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 } @@ -1009,18 +1090,24 @@ 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 } - p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4) - if sys.PtrSize == 8 && uintptr(p)&4 != 0 { - if uintptr(unsafe.Pointer(f._func))&4 != 0 { - println("runtime: misaligned func", f._func) - } - p = add(p, 4) + 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 + if off == ^uint32(0) { + mask = 1 } - return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize)) + mask-- + raw := base + uintptr(off) + return unsafe.Pointer(raw & mask) } // step advances to the next pc, value pair in the encoded table. diff --git a/src/runtime/symtab_test.go b/src/runtime/symtab_test.go index ffa07c7f3a9f8dca3ab1323bdfe6cbd5269a2c39..99ff0d4420b1caa9a246cc98368109533a89ee7d 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) + } + } + }) +} diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 0f91685d6ca14d18433959f511ac18259273be1c..80dd1a0378c20b7c3a3aa92060269a29e8e47921 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() @@ -156,7 +166,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 @@ -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_amd64.s b/src/runtime/sys_darwin_amd64.s index 3bd027f98242f06d189643af0af0c3e8a1931b6c..5d89cda8e68901a668fec3e3b7bb7f30e21b3e57 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_darwin_arm64.go b/src/runtime/sys_darwin_arm64.go index 9c14f33a1ce2389778dd17c144c59dcd20b95fa3..6170f4fddab51e5617cd7f546bf6adb7f1f0f7f9 100644 --- a/src/runtime/sys_darwin_arm64.go +++ b/src/runtime/sys_darwin_arm64.go @@ -5,7 +5,8 @@ package runtime import ( - "runtime/internal/sys" + "internal/abi" + "internal/goarch" "unsafe" ) @@ -14,14 +15,16 @@ 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)) + ret := asmcgocall(unsafe.Pointer(abi.FuncPCABI0(pthread_key_create_trampoline)), unsafe.Pointer(&k)) + KeepAlive(k) + return ret } 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() @@ -53,7 +56,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_freebsd_amd64.s b/src/runtime/sys_freebsd_amd64.s index 71a60cae65c23668ba2638592566a96b2e383914..165e97c60d735881ea3797df151f5c3aa79f9409 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_libc.go b/src/runtime/sys_libc.go index b1a9f8b5365709d2862057877815ff4056cb942c..7012b4167e969f0065c93df970f22a88fe487fc6 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_linux_386.s b/src/runtime/sys_linux_386.s index 3ae5a9099f096aaa01f10b676dc41bad1437f7dc..6df812234c3f9cf4591a83375a2dc39b4745662f 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 33cc670b641590e6ff7a26dde2505a1cb5f2583e..f0e58e11db36ec56ed0bf2de730f198a64cec0a3 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 @@ -215,13 +244,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 +259,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 @@ -328,9 +347,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() @@ -346,10 +364,26 @@ 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. -// 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 +426,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 @@ -414,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 @@ -428,8 +462,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_linux_arm.s b/src/runtime/sys_linux_arm.s index 02a5d4a6427402cdc0981364caf157bcd82d77a0..ca443b699fdcf3b2cf6b3866fadad8a008ff5c57 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 @@ -259,8 +288,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 @@ -330,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 @@ -351,8 +382,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 @@ -424,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) diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s index 69ac16027800f3df0e61100b3278ee6357ed9f82..1276c077d701f2c8bf894d780a79d8938d05268e 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 @@ -221,8 +250,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 +334,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 e18d29144563fed07dfecfcb859c5f1257de0782..0df25979939357b4b464e0aaa44586903ef7be44 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 @@ -41,6 +39,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 +205,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 @@ -229,8 +256,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 +326,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_mipsx.s b/src/runtime/sys_linux_mipsx.s index b3970be9cf8f746a0f6cf2e2eb5bf212009b68be..2207e9ab98f702fb0a2b43ddf6d2a6d19a1d668d 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 @@ -43,6 +41,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 +210,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 005fa4d2b4d002acfb2a946ff72b2369580ae08a..dc3d89fae741c7ff808cf38bc253e2287ef91d4c 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 @@ -44,6 +42,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 +177,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 @@ -205,8 +229,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 +322,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 @@ -715,6 +741,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 diff --git a/src/runtime/sys_linux_riscv64.s b/src/runtime/sys_linux_riscv64.s index 2389f1cc182489971fb050fcc9209fbbd470e474..a3da46d1362fbcd615ff4378cbc229b302d6e644 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 @@ -25,7 +27,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 @@ -47,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 @@ -132,15 +136,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 @@ -209,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 @@ -220,8 +244,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 @@ -232,13 +316,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 @@ -247,6 +380,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/sys_linux_s390x.s b/src/runtime/sys_linux_s390x.s index 916dfada8d58e68d6f91d5097d53d80d3b76bacb..886add8b543b3c927db0e362f535a1c90ec6d1cb 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 diff --git a/src/runtime/sys_mips64x.go b/src/runtime/sys_mips64x.go index 842a4a7084ffe6303cd7fa6f1fda7bd2c781ebc4..b71538409c6fcf38ecc8f3b94dbee1dceb946417 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 2038eb7d794f9a7b27534b2c9654b319d8fb482d..b60135f9649d449a083cac512b723dfcf2684994 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 66821b1f76b06dfe7bee306c66d3cb7cbbd05a06..653f1c999f0ad936843163d6fb01c7d9c99f0476 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 ab3149558b3087156446c32d9f01a958019d2ad8..c4b8489612a5db3e1d1377522c3f64b0c68bbb0d 100644 --- a/src/runtime/sys_openbsd.go +++ b/src/runtime/sys_openbsd.go @@ -3,11 +3,13 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 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 +17,47 @@ 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)) + 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(funcPC(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(funcPC(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(funcPC(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(funcPC(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 cb5d35879cdef6a7049271e13575c630c9eaed0c..d852e3c58ae0d5277f81cb90e251993171590a17 100644 --- a/src/runtime/sys_openbsd1.go +++ b/src/runtime/sys_openbsd1.go @@ -3,35 +3,40 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 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)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(thrsleep_trampoline)), unsafe.Pointer(&ident)) + KeepAlive(tsp) + KeepAlive(abort) + return ret } 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 cd1a4e879fb2df8bc946548b4cb7e917cfed0652..4d50b4f6b136f23d5c615acadf1ad28748e130cc 100644 --- a/src/runtime/sys_openbsd2.go +++ b/src/runtime/sys_openbsd2.go @@ -3,25 +3,27 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 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,21 +31,21 @@ 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() // 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 @@ -53,7 +55,8 @@ 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)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. return args.ret1, args.ret2 } func mmap_trampoline() @@ -61,42 +64,50 @@ 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)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } 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)) + 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(funcPC(open_trampoline)), unsafe.Pointer(&name)) + ret = libcCall(unsafe.Pointer(abi.FuncPCABI0(open_trampoline)), unsafe.Pointer(&name)) + KeepAlive(name) + return } 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)) + 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(funcPC(write_trampoline)), unsafe.Pointer(&fd)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(write_trampoline)), unsafe.Pointer(&fd)) + KeepAlive(p) + return ret } func write_trampoline() @@ -110,7 +121,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 +129,41 @@ 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)) + KeepAlive(new) + KeepAlive(old) } 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)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(sysctl_trampoline)), unsafe.Pointer(&mib)) + KeepAlive(mib) + KeepAlive(out) + KeepAlive(size) + KeepAlive(dst) + return ret } 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 +174,13 @@ func nanotime1() int64 { clock_id int32 tp unsafe.Pointer }{_CLOCK_MONOTONIC, unsafe.Pointer(&ts)} - libcCall(unsafe.Pointer(funcPC(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() @@ -168,42 +192,60 @@ 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)) + 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) } //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)) + 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 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)) + KeepAlive(new) + KeepAlive(old) } 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)) + // 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() //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)) + KeepAlive(new) + KeepAlive(old) } func sigaltstack_trampoline() diff --git a/src/runtime/sys_openbsd3.go b/src/runtime/sys_openbsd3.go index 8d77a4b216e93136d8bcecc550aaf6fd1ef69f99..269bf86f10de43ca22e0f868d777492f556adafd 100644 --- a/src/runtime/sys_openbsd3.go +++ b/src/runtime/sys_openbsd3.go @@ -3,11 +3,13 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 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 +22,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 +33,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 +44,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 +55,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 +66,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 +77,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 +87,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 +95,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 +103,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 +111,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_386.s b/src/runtime/sys_openbsd_386.s index 7830b61b7d0eff6fd2c3f03260cb3495224a1683..890b96b673d434aeeef210be85718204091d1449 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 522e98cf4f5ab024294dc01fc4825e7f2de25574..fc6d5dc387dd2c05500890e799dc4110fed3698e 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() @@ -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 143fcf0518422152c90269b762c6d16c238d3eaf..a9cb1fbafe1f276c0b63e751efe99fa00f0efba0 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 9b4acc90a58c88e3abc08d18b7d476a267c67692..3fa7e1ede25baedba45ef5181273d46acb65b066 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 diff --git a/src/runtime/sys_plan9_386.s b/src/runtime/sys_plan9_386.s index b3d2f1376d624c8b97e9e37ab95e53ee74fcf84e..bdcb98e19e0bbf083dd1a8511e3507f4fa0bad69 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 731306ab448463217fd5a8dd1a5ab273d081e386..638300dfb935481b786d84beeaa4716a1cf01536 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 @@ -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 diff --git a/src/runtime/sys_ppc64x.go b/src/runtime/sys_ppc64x.go index 69bd99fa09e11de792dc517de2de61bb75992557..56c5c9575e550371827abf5a60f99adf598356eb 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_wasm.go b/src/runtime/sys_wasm.go index 057ed4ccd90a7513ff8211f00a7685d450bfeef5..e6e7f471eea9f80c082977e1e5bb165728ac310b 100644 --- a/src/runtime/sys_wasm.go +++ b/src/runtime/sys_wasm.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/goarch" "runtime/internal/sys" "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_windows_386.s b/src/runtime/sys_windows_386.s index 0b3933502ab3f4f42b8d6e8b2844724bf7a7ab96..cf3a439523c74196e54d44b498e2568d82f08f2e 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 e7782846b25c7c3b6f97391bd75c90eeb56adcc8..1467b4d57bf01b9d7ef50c80f3dac851094a287e 100644 --- a/src/runtime/sys_windows_amd64.s +++ b/src/runtime/sys_windows_amd64.s @@ -8,12 +8,8 @@ #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 +TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 // asmcgocall will put first argument into CX. PUSHQ CX // save for later MOVQ libcall_fn(CX), AX @@ -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 @@ -179,15 +175,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 +208,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 +241,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() @@ -348,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 48f8c7dedffd5ec8afa7fc22e7156aafc8de5de8..e5b1b7e9f358f21e6684e2a4dc468a4729b2fb62 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 @@ -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 7a2e11f5ae29832d6536a1fd11a03a2bdff553b2..87f8f0d2183a22d1beaa4988383f3284ca5e3767 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,21 +290,21 @@ TEXT sigresume<>(SB),NOSPLIT|NOFRAME,$0 MOVD R0, RSP B (R1) -TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·exceptionhandler(SB), R1 +TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 + MOVD $runtime·exceptionhandler(SB), R1 B sigtramp<>(SB) -TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·firstcontinuehandler(SB), R1 +TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0 + 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 -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 @@ -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) @@ -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 @@ -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/sys_x86.go b/src/runtime/sys_x86.go index 0866e3140e09d092245c323cc1c554fd4a44d726..9fb36c2a661d5c3d9c2505e1aeb950d905f19a33 100644 --- a/src/runtime/sys_x86.go +++ b/src/runtime/sys_x86.go @@ -3,12 +3,11 @@ // license that can be found in the LICENSE file. //go:build amd64 || 386 -// +build amd64 386 package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -16,7 +15,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_solaris.go b/src/runtime/syscall_solaris.go index 094516927f3f495ad9b4817772fa510db3e35bf9..e270e271c0ac3d47257eba3d2b95d8d9aff34e07 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)), @@ -303,11 +312,14 @@ 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 } //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)), diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index 4763a440e7ef1c47ba322727dfd7bee3bcbb482f..e76b403ade6a4df2083256f04a119b26267ac5b2 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: @@ -232,10 +232,10 @@ 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 +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 @@ -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 @@ -468,84 +472,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 e3f772ac4bb9457a5ed94ff944cfc466b67afca2..101e94107c5f5b50b86bb6520553165f90bfc8d9 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 { @@ -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,51 @@ 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) { + 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/runtime/testdata/testprog/badtraceback.go b/src/runtime/testdata/testprog/badtraceback.go index d558adceec3f95b971c8b78f998265bc5bc68bf8..09aa2b877ecf5a108812479ee0cde2c525d1da9e 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/checkptr.go b/src/runtime/testdata/testprog/checkptr.go index 9c5561396e5d43b335c3b270201025809c307f1c..b27e5f74f868f3db8c31d60d745feac20f085cc8 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] +} diff --git a/src/runtime/testdata/testprog/gc.go b/src/runtime/testdata/testprog/gc.go index 74732cd9f4b1b2e124a67db1125453e31e99ef14..215228ea05b11a9abaab2a06a879467f8ffad121 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 { @@ -132,81 +132,88 @@ 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 + // The total amount of memory we're willing to allocate. + allocTotal = 32 << 20 // 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. - debug.SetGCPercent(100) - procs := runtime.GOMAXPROCS(-1) - if procs > maxProcs { - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) - procs = runtime.GOMAXPROCS(-1) + + // 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 } - // 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++ { + allocs := allocTotal / allocChunk + + // Set GC percent just so this test is a little more consistent in the + // face of varying environments. + debug.SetGCPercent(100) + + // 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, subtracting it out once is 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 +223,14 @@ 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. + // 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. // - // 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) + // 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 @@ -243,6 +245,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. @@ -263,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/numcpu_freebsd.go b/src/runtime/testdata/testprog/numcpu_freebsd.go index aff36ec702b0660ce2b5d4597cea9c093f13fc50..7209f67959a0a293705c36a147bd1a8be900774d 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/preempt.go b/src/runtime/testdata/testprog/preempt.go index 1c74d0e435238afa383b9e93ad8e3807d43cc9d3..fb6755a37253a90ef3c72f20b943a8db745560dd 100644 --- a/src/runtime/testdata/testprog/preempt.go +++ b/src/runtime/testdata/testprog/preempt.go @@ -20,6 +20,10 @@ 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. 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. var ready, ready2 uint32 diff --git a/src/runtime/testdata/testprog/signal.go b/src/runtime/testdata/testprog/signal.go index 417e105c68a5b97b6c2ce1cc84a8ae7d53e16667..cc5ac8af58d8176b5568a93ed2e8ab5faf36461c 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/sleep.go b/src/runtime/testdata/testprog/sleep.go index 86e2f6cfe6ce7f5387acda3161b91d5142e76e63..b230e60181793915cce9defbc687ef5663b0b674 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) } diff --git a/src/runtime/testdata/testprog/syscalls_none.go b/src/runtime/testdata/testprog/syscalls_none.go index 7f8ded3994f18efa788fbd39b4ef913c1edbd564..068bb59af37d11fcf3ab32e2162ff0ecc8fa1a40 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/testprog/traceback_ancestors.go b/src/runtime/testdata/testprog/traceback_ancestors.go index 0ee402c4bdc60837db2f12d20c53d001f9a51f5c..1d0d00bab7d4ae48cc8fd81d7bd33e9e90e3debe 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/runtime/testdata/testprogcgo/callback.go b/src/runtime/testdata/testprogcgo/callback.go index be0409f39d241275921acdb89bd63d4371f1c74c..a2d8a492a47a8fa1fecde9ba5173d189c1fed6fc 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 55a606d1bc854db2bc4400bd6ece42e120373e1d..c722d40a196a9fa6da2828e61fa22cc52f42ba03 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 9e782f504fe12b2ef1f772b478b0dfa5d88c1eaf..700b7fa0c23e58d5f8d4e866c25b907a1afde441 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 1722a75eb9a49c530f03978cbfb1e2fc0ba8197c..b35b280a76ed0ec5d4904a0b8f37f8d2762e3428 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 15723c73695bdfda1262445d25c0478a729a1306..c268bcd9b281e933012528fc8628b312a03d1199 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/gprof.go b/src/runtime/testdata/testprogcgo/gprof.go new file mode 100644 index 0000000000000000000000000000000000000000..d453b4d0ce330ae1b2ee9c888f24125c30ebe69a --- /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 0000000000000000000000000000000000000000..5c7cd77022113313245855c1bf3bffb6a838fa94 --- /dev/null +++ b/src/runtime/testdata/testprogcgo/gprof_c.c @@ -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. + +// 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. + volatile int i; + for (i = 0; i < 123456789; i++); +} + +void CallGoSleep() { + GoSleep(); +} diff --git a/src/runtime/testdata/testprogcgo/lockosthread.go b/src/runtime/testdata/testprogcgo/lockosthread.go index 36423d9eb0cf3152c2a9dfa49e425a641b9a26ce..8fcea35f524a862fe4214f8d5eddbf7607cada42 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 5a9c359006d7af6a26dd0e39110c2775fb3cfce2..b95ec7746895b2f8c433036dad3ff639a1f368cc 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 5bdfe52ed41b4d64a99f0ad7b3305f23c3afc43f..1b9f202f46c827c5fa87d391921e46cf04915695 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/panic.c b/src/runtime/testdata/testprogcgo/panic.c new file mode 100644 index 0000000000000000000000000000000000000000..deb5ed5a6054f8895ab96e97aa54c1126d5b6031 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..57ac89540ec0151569bbad48e6b42b223bf1df5c --- /dev/null +++ b/src/runtime/testdata/testprogcgo/panic.go @@ -0,0 +1,23 @@ +package main + +// This program will crash. +// We want to test unwinding from a cgo callback. + +/* +void call_callback(void); +*/ +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/pprof.go b/src/runtime/testdata/testprogcgo/pprof.go index 3b73fa0bdd9d8a9728794e39f3daaccad3e13476..8870d0c415745186a3935b1b598e91fb82203722 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/raceprof.go b/src/runtime/testdata/testprogcgo/raceprof.go index f7ca629789be7f9a44aaf33c7eafd6bfca995cb7..c098e16196d1edea0d0dc00fefbce0a7942991d7 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 a079b3fd1a531e4642914e916f64a5beb748b578..93526797146bec160de1a4f036dd65de84928afc 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 3237a8c69c6f36d491a05159794fc25710b17907..0632475228d9b0c709098b3d616f9ebf53c18ebc 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 21b668d6c0096510ab9527bd4943a635b471fe92..12ca661033b36fc8926aa92bd1f4f8eb3f31451d 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/sigthrow.go b/src/runtime/testdata/testprogcgo/sigthrow.go new file mode 100644 index 0000000000000000000000000000000000000000..665e3b02df191aa149c96e5bfdfbb9c42f07f439 --- /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() +} diff --git a/src/runtime/testdata/testprogcgo/threadpanic.go b/src/runtime/testdata/testprogcgo/threadpanic.go index f9b48a9026da4ce4b9f71c69097546f702a8d1b8..2d24fe68eaa3683d5420f5ba11be243f0b6d8c23 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 feb774ba59a91c22146ef13e1298617bda524610..ec5e750da9dd27014450eee0ac9aabb93b9bfd07 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 @@ -33,8 +34,6 @@ void cpuHogThread() { void cpuHogThread2() { } -static int cpuHogThreadCount; - struct cgoTracebackArg { uintptr_t context; uintptr_t sigContext; @@ -49,13 +48,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))) { @@ -73,6 +65,7 @@ void runCPUHogThread(void) { import "C" import ( + "context" "fmt" "os" "runtime" @@ -107,12 +100,16 @@ 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() + }) - t0 := time.Now() - for C.getCPUHogThreadCount() < 2 && time.Since(t0) < time.Second { - time.Sleep(100 * time.Millisecond) - } + time.Sleep(1 * time.Second) pprof.StopCPUProfile() diff --git a/src/runtime/testdata/testprogcgo/threadprof.go b/src/runtime/testdata/testprogcgo/threadprof.go index 2d4c1039fb737fb2b3e00c2712dc81033781ff9e..8081173c0f45e24cba315e93fb5bc2d1135aa7a9 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 4d2de79d97c03377967570535170aa8264f52c84..dfa2e10e7ab9350f5ed0915c2c6c6dc832f99615 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 4a988ef6c1da2441b810cb3f526956fa2e71ef5d..62ebce7176f2206d34d7a3726f2a7347405a4ac0 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 400eaa1c82dfa8efc0e11c82a4f9a6eae0569c64..025ef913e5e9702d56a589f2bcb082596fd0d940 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 666b2423164162fd96d1beed5ba6544fe0f6fe71..a9ad62077644eed6af2560985d03dcc46169860b 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" @@ -27,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. @@ -231,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) } @@ -366,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 { @@ -380,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. @@ -418,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") } @@ -674,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) { @@ -690,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() @@ -819,7 +824,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)) } @@ -1043,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() } @@ -1063,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/runtime/time_fake.go b/src/runtime/time_fake.go index c790faba3d6b75744b7a9afdba58e2c22183ede0..b5e04635883d9eae46312b693002147a411bd8b5 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, @@ -42,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. diff --git a/src/runtime/time_linux_amd64.s b/src/runtime/time_linux_amd64.s index 0dd791989685cd1235d7445b3c20895cdbe9d1c8..1416d232304f39d1eaf2bbab1158c229b6194d61 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" @@ -12,19 +11,10 @@ #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. -#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 // Set vdsoPC and vdsoSP for SIGPROF traceback. // Save the old values on stack and restore them on exit, @@ -34,25 +24,23 @@ 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) -#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 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 @@ -64,25 +52,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: diff --git a/src/runtime/time_nofake.go b/src/runtime/time_nofake.go index 5a4ceaf43d280ceacd4fec036405316ae0f32ea1..70a2102b22e84c2f43c904a1bb302823220363c3 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 @@ -20,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) } diff --git a/src/runtime/time_windows.h b/src/runtime/time_windows.h index cd16fd163bb42963272f07fa512ed95a21fd33b7..7c2e65c328b82a1d8b8468e1271033b2a04eb661 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_386.s b/src/runtime/time_windows_386.s index 19ce6910d73b59e9cdc58c3844df3846a995f57d..b8b636ef306bb753c7db7dab5596591ce014bb0e 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 93ab960b067cd5a810d27effdb31cf84712792bd..226f2b5136e020c5c71a5e27634b29d41350b8d9 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" @@ -12,33 +11,20 @@ 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 // 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_arm.s b/src/runtime/time_windows_arm.s index 7c763b66edd2f6b4716f67bc5987a2f5e69ab915..711af88307207355846c5093555f8f20070d65fa 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" @@ -17,7 +16,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 +35,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 ef52ce4c99441eb02c5c00a933e9d0be44fffc88..e0c7d28e153f72912fdc4221bf533412ef278b29 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" @@ -13,34 +12,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 @@ -48,17 +31,14 @@ wall: // 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 diff --git a/src/runtime/timeasm.go b/src/runtime/timeasm.go index 468ff8a0d33dcdbcdd2c0c6c37c23101e59fa8ca..0421388686a253fa4e19dd6d1ccf55f22f56886c 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 6f16c70b8160b18a0d1131230914c6a63a5ea88a..1d2926b43dc3d4c2447ba3af6961249c7f29b318 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 800a2a94e0a0d8b757f350d81fe17aa9fe0beb2d..b9a5cc6345ee2d393882bc18ed9f4d37c0c90e88 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_arm.s b/src/runtime/tls_arm.s index 879caac9e16743c227bbcfe5cf06a5538a44ce60..83fd37e6ecb4fa8d74898023e376e4e5b6d68b85 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 779d64ba31ab248a617cefca70db48eb0c8a2a2d..ec2748e5b22f034cb882b1a372795cb4578da425 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 ada8d06a9e743b93d74ade93f7ba5d7171faf64b..acc3eb5a17854d44c1bf061ebc1871e02fa93b8e 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 7e935d0eb295919bbcf2dc10137060fc8ae7f2c8..17aec9fc1e3cb5ccd512ad46326659fb24565a8e 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/tls_riscv64.s b/src/runtime/tls_riscv64.s index 22b550b76114b642029be87b0771af4feac8a4a4..397919aeba23635de78464a453de036d84a39ea9 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 diff --git a/src/runtime/tls_stub.go b/src/runtime/tls_stub.go index 95dafd007c130cc44e14f495e4be00447dd64a7f..7bdfc6b89a614986cd4dc027612f7a46edfe1c7d 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/trace.go b/src/runtime/trace.go index 1530178c853d01765def102386e1827abd97a65b..5b14a5f553922526b1667c71e067cddec43dbbfc 100644 --- a/src/runtime/trace.go +++ b/src/runtime/trace.go @@ -13,6 +13,7 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -85,7 +86,7 @@ const ( // and ppc64le. // Tracing won't work reliably for architectures where cputicks is emulated // by nanotime, so the value doesn't matter for those architectures. - traceTickDiv = 16 + 48*(sys.Goarch386|sys.GoarchAmd64) + traceTickDiv = 16 + 48*(goarch.Is386|goarch.IsAmd64) // Maximum number of PCs in a single stack trace. // Since events contain only stack id rather than whole stack trace, // we can allow quite large values here. @@ -550,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 { @@ -652,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< uintptr(len(a.head.ptr().data)) { if n > uintptr(len(a.head.ptr().data)) { throw("trace: alloc too large") diff --git a/src/runtime/trace/annotation.go b/src/runtime/trace/annotation.go index 6e18bfb75554b5d433ee3c2fc5357dee99292034..d05b5e22613098975b280c8651c885b3edf0623f 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/runtime/traceback.go b/src/runtime/traceback.go index 814c3236345404e63f7d37c11e0076b67d824d52..73bd0e11a9c9778b7184f1c3a25ca29a9636491d 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -6,6 +6,7 @@ package runtime import ( "internal/bytealg" + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -21,41 +22,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 = 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.continpc = frame.pc - if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) { - return - } - } -} - // Generic traceback. Handles runtime stack prints (pcbuf == nil), // the runtime.Callers function (pcbuf != nil), as well as the garbage // collector (callback != nil). A little clunky to merge these, but avoids @@ -126,10 +92,24 @@ 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 } } + // 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 { @@ -207,7 +187,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 @@ -248,7 +228,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))) } } @@ -279,7 +259,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 @@ -300,7 +280,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. @@ -331,7 +311,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 @@ -367,7 +347,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-- @@ -391,7 +371,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 } } @@ -418,7 +398,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. @@ -446,7 +426,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) { @@ -461,11 +441,11 @@ 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 { - 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)) @@ -574,7 +554,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. @@ -598,18 +578,39 @@ 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 irrelavant bits + // mask out irrelevant bits if sz < 8 { shift := 64 - sz*8 - if sys.BigEndian { + if goarch.BigEndian { x = x >> shift } else { x = x << shift >> shift } } print(hex(x)) + if !isLive(off, slotIdx) { + print("?") + } } start := true @@ -619,6 +620,7 @@ func printArgs(f funcInfo, argp unsafe.Pointer) { } } pi := 0 + slotIdx := uint8(0) // register arg spill slot index printloop: for { o := p[pi] @@ -643,7 +645,10 @@ printloop: printcomma() sz := p[pi] pi++ - print1(o, sz) + print1(o, sz, slotIdx) + if o >= startOffset { + slotIdx++ + } } start = false } @@ -700,16 +705,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 { + 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 } @@ -762,13 +767,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") } @@ -811,16 +816,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) } @@ -876,8 +888,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") } @@ -1045,8 +1057,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. @@ -1392,6 +1404,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))) } @@ -1414,5 +1429,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/runtime/traceback_test.go b/src/runtime/traceback_test.go index 83b86a7e909acd3095f3a1c2c4f4c392823c6da6..7d8b04e14b732e2b1615f115cf563d92d9f1c4dd 100644 --- a/src/runtime/traceback_test.go +++ b/src/runtime/traceback_test.go @@ -6,13 +6,29 @@ package runtime_test import ( "bytes" + "internal/goexperiment" + "internal/testenv" "runtime" + "strings" "testing" ) var testTracebackArgsBuf [1000]byte func TestTracebackArgs(t *testing.T) { + 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 + } + tests := []struct { fn func() int expect string @@ -105,6 +121,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 +352,72 @@ 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 { + 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 +} + +// 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 + return runtime.Stack(testTracebackArgsBuf[:], false) +} + +// 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 { + 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. +// 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 + 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} +} diff --git a/src/runtime/type.go b/src/runtime/type.go index 4039273695b106746a0582386c8834c72d6b4f15..da471478973b01b8d707bcfee1797edf14625136 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 @@ -285,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(uint32(off)) return unsafe.Pointer(res) } diff --git a/src/runtime/vdso_elf32.go b/src/runtime/vdso_elf32.go index 456173b0f51c147de0fc8bf8ea912c081de10652..1b8afbedf45792444a7e8a9fe16b76ef8dbd22c0 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 9923bd46971e5f2bc971c3cd448e5bfc7ccc19c1..d46d6f8c34da7599191832ab451830b18031763d 100644 --- a/src/runtime/vdso_elf64.go +++ b/src/runtime/vdso_elf64.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. -//go:build linux && (amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le) -// +build linux -// +build amd64 arm64 mips64 mips64le ppc64 ppc64le +//go:build linux && (amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64) package runtime diff --git a/src/runtime/vdso_freebsd.go b/src/runtime/vdso_freebsd.go index 7ca7b2810bf0de4920f35cec583e14061dcd9452..0fe21cf647044689327ebcec71a80df8d8c16564 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 23a5a8c322707a3b94201d47db6c86f0e3841a60..5324a3d4cb3206390a33826cf72839e174a6c92c 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 c66fbf821669fd6425e3739c07b1df0b9643c0a3..618bd39b42b0f79a82cba8632d758e8dd142729c 100644 --- a/src/runtime/vdso_in_none.go +++ b/src/runtime/vdso_in_none.go @@ -2,8 +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 && !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 package runtime diff --git a/src/runtime/vdso_linux.go b/src/runtime/vdso_linux.go index ae211f96b1b058c2766c923b3001b395682d9f57..cff2000767f598dc9d2140b622e94c49b98b715d 100644 --- a/src/runtime/vdso_linux.go +++ b/src/runtime/vdso_linux.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. -//go:build linux && (386 || amd64 || arm || arm64 || mips64 || mips64le || ppc64 || ppc64le) -// +build linux -// +build 386 amd64 arm arm64 mips64 mips64le ppc64 ppc64le +//go:build linux && (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 395ddbba69a730aab8872b3e6e2a6c810c0910ce..1444f8e5246aec9e8ee33f093b77915c5742cee1 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 b741dbfcdc527d9f9a55fdb37c36acdb110c0cb9..09c8d9d20ed8a87d4218e606fa115467a15609ab 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/vdso_linux_riscv64.go b/src/runtime/vdso_linux_riscv64.go new file mode 100644 index 0000000000000000000000000000000000000000..f427124c3c4951bdf21705a61940f101166497e3 --- /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 diff --git a/src/runtime/vlrt.go b/src/runtime/vlrt.go index cf631bdcca7d245c749f4ccb76c48b1b50ee37c1..1dcb125aef548dc862330a60c8c9b9b450da4101 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 @@ -59,6 +58,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)) diff --git a/src/runtime/wincallback.go b/src/runtime/wincallback.go index a7a787d8f6d694579f7e7827f7838f74b67ce6df..442a98470837b84a7b0b5c1971ccce6d5eccaa3a 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. @@ -23,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 @@ -33,7 +31,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 +59,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 +87,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/write_err.go b/src/runtime/write_err.go index a4656fd72810d7b8d9a30695a732a5cdd11918aa..81ae872e9c035d7f75783b3cfd2eed7d887004dc 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/runtime/zcallback_windows.s b/src/runtime/zcallback_windows.s index e451c2b9d0508bb5d46deaf3ff4c17a78a936ef5..bd23d71333ba064c60d10e07a02a3550eee7c98d 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 @@ -11,7 +10,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 a73a813acb3c5d9095699165125f139a7fde9554..f943d84cbfe5fddfd47ae7090658db059d70f6c8 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 2a6bda0990c108d3c180929ddcfe31ff34dba166..69fb05788cdab23883725e7b41cbf6a7f325692e 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 diff --git a/src/sort/slice.go b/src/sort/slice.go index 992ad1559df58c8052555e58a68fd7bb78b9cf9c..ba5c2e2f3d3f11d06aacee6cd93028af4b6bb1ba 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 5d5949f3cade56f2df3cf32a8a3f48417e58d3a5..e4773676185bca9ea403f1cfccb338ade1bc85fa 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/sort/sort.go b/src/sort/sort.go index cbaa8c3aac20f187acb42aa11a3f98e44bd6df5c..749310764aff2b7e00f0e6c89781f2d7d306c753 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. diff --git a/src/strconv/fp_test.go b/src/strconv/fp_test.go index 39dd9c4a581539376c5421ce88728e690fa01955..fd73958c97d29eb174e19044c714ed0e31b75f1e 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/strconv/ftoaryu.go b/src/strconv/ftoaryu.go index 1c61288b9ffa8ebaa7b7d294bc9d238700e7da3a..f2e74bed1779400c87820a9dbc9c127fdd0a9a4f 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/src/strconv/quote.go b/src/strconv/quote.go index b3bbb1612b9f634e930fc169bc329e87d1c8858d..d2814b92da795b77ceb1a4757748cf7d25ca6ea2 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 4750be27408a65dfd4c2f51864abda3862d60250..81fc8f79e147499f14798d1831bb8d61d6b55ce2 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) { diff --git a/src/strings/clone.go b/src/strings/clone.go new file mode 100644 index 0000000000000000000000000000000000000000..edd1497d9e58811add83d1fd72378912a5396e87 --- /dev/null +++ b/src/strings/clone.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 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. +// 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 new file mode 100644 index 0000000000000000000000000000000000000000..a9ba8add2355245a532f57b7cefa93998b3ee4fa --- /dev/null +++ b/src/strings/clone_test.go @@ -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.ß + +package strings_test + +import ( + "reflect" + "strings" + "testing" + "unsafe" +) + +var emptyString string + +func TestClone(t *testing.T) { + var cloneTests = []string{ + "", + strings.Clone(""), + strings.Repeat("a", 42)[:0], + "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 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) + } + } +} + +func BenchmarkClone(b *testing.B) { + var str = strings.Repeat("a", 42) + b.ReportAllocs() + for i := 0; i < b.N; i++ { + stringSink = strings.Clone(str) + } +} diff --git a/src/strings/compare.go b/src/strings/compare.go index 1fe6b8d89a3f94439a80ed2aa68456be4cba241b..2bd4a243db2f83ca77d4f41eeea12e16c7174329 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 diff --git a/src/strings/example_test.go b/src/strings/example_test.go index 375f9cac6502e89a0124315a04c1700b8cbd13ae..94aa167f90900c57be37a90d484455f88c7e5468 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/export_test.go b/src/strings/export_test.go index b39cee6b1ded1601fdfbee6b849fb527a7cef586..81d1cab9d0064e77dd582bf8d5cab6df2df580a9 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 5adea6f7ab2b322cc0d6bdb5b2d29980addebd05..dc99f9c24858169a183589385fc43291dcdf2701 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/strings/replace.go b/src/strings/replace.go index e28d42887930b9d852bdd2129c28f4ebf3bd8c8b..ee728bb22b655259247ad7b871ae9983b28fac72 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) { diff --git a/src/strings/strings.go b/src/strings/strings.go index b429735feadf9d26d29c22d52440f9eb5a749d7f..c5a29e95f6dd5ac7602e9544fc1c8ffdc73bc865 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 @@ -797,6 +798,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,28 +810,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 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)) - } - } - 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 @@ -837,7 +826,13 @@ func Trim(s, cutset string) string { if s == "" || cutset == "" { return s } - return TrimFunc(s, makeCutsetFunc(cutset)) + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0]) + } + 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 @@ -848,7 +843,44 @@ func TrimLeft(s, cutset string) string { if s == "" || cutset == "" { return s } - return TrimLeftFunc(s, makeCutsetFunc(cutset)) + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimLeftByte(s, cutset[0]) + } + if as, ok := makeASCIISet(cutset); ok { + return trimLeftASCII(s, &as) + } + return trimLeftUnicode(s, cutset) +} + +func trimLeftByte(s string, c byte) string { + for len(s) > 0 && s[0] == c { + s = s[1:] + } + 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 @@ -859,7 +891,44 @@ func TrimRight(s, cutset string) string { if s == "" || cutset == "" { return s } - return TrimRightFunc(s, makeCutsetFunc(cutset)) + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimRightByte(s, cutset[0]) + } + if as, ok := makeASCIISet(cutset); ok { + return trimRightASCII(s, &as) + } + return trimRightUnicode(s, cutset) +} + +func trimRightByte(s string, c byte) string { + for len(s) > 0 && s[len(s)-1] == c { + s = s[:len(s)-1] + } + 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 @@ -1100,3 +1169,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 09e5b27cc3857a6a98a0ef0b19cd05f1e9d536da..0f30ca738e6754728fe28fe66e4ed046d08afe89 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"}, @@ -1577,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) } } } @@ -1860,6 +1885,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} { diff --git a/src/sync/atomic/asm.s b/src/sync/atomic/asm.s index 7b8c9b9430ef402c4df820b67a08a0aad281efad..2022304665ef91bc98c71f11d6085cb3e32ef801 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/atomic_test.go b/src/sync/atomic/atomic_test.go index eadc962f70634b12feac91930b44198ae1bb8be8..8a53094cb787e5f1b97491fd1942c42c6b01beda 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" @@ -31,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() }() @@ -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 diff --git a/src/sync/atomic/race.s b/src/sync/atomic/race.s index 0866487cc71a9035eef7bc2958d82bd3e24dfc17..90bd69f32153fd3441175b2b42e81c023fdfe379 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/sync/atomic/value.go b/src/sync/atomic/value.go index 3500cd22f4e74e7991d4f9cfca1ea6856695b722..f18b7ee095e07817b293a0ccf3abe7faec9661eb 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,10 +25,10 @@ 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 || uintptr(typ) == ^uintptr(0) { + if typ == nil || typ == unsafe.Pointer(&firstStoreInProgress) { // First store not yet completed. return nil } @@ -39,10 +39,12 @@ 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). -func (v *Value) Store(val interface{}) { +func (v *Value) Store(val any) { if val == nil { panic("sync/atomic: store of nil value into Value") } @@ -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. @@ -86,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") } @@ -131,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") } @@ -178,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 a5e717d6e0ccd1e3e5ff0c2165e54716df6a1c0d..721da965e35800a8a9ba72259bcd2e880d839544 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 8288d41e8c08431504b30e9bf4674f176f899232..2fb4c1e6b913bed549af5f4223a28965876d3d5d 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/example_test.go b/src/sync/example_test.go index bdd3af6fedaa4bb25b7cb6b2990a5aa171209612..f009a68cf21f25427d2bcca48194fa0f33233ac2 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. diff --git a/src/sync/export_test.go b/src/sync/export_test.go index ffbe56746406288ae48cda2173346ed0b7f25d2d..c020ef737da4025ede3ada3cc07f05892aafc597 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 dfb62dd3e801cc8717ab7791b0a0e31f4ec43a1c..2fa3253429114f457986f80b44770e2ef53099c1 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 } } } @@ -311,12 +311,13 @@ 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. -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 @@ -365,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 cf0a3d7fdedc898caf689f73b17450a2c0f1fb97..e7b0e6039c44d13edd7df73896e3dc5d03d3032c 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 d105a24e926e3ccf3370f659455748a8c23a0cc9..1122b40b9b835942582eb2dcd04175c58f67910b 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 7f163caa5c95d111845844e41fa401065b4a9766..8352471104381cb0dcd38b16fe69dd15575bf2ab 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) @@ -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 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) { + 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 any) bool { + length++ + return true + }) + + if length != 0 { + t.Fatalf("Unexpected sync.Map size, got %v want %v", length, 0) + } +} diff --git a/src/sync/mutex.go b/src/sync/mutex.go index 3028552f743d1fce5e916244b1e141c83079ee0f..18b2cedba72f80ce2770929f25409c021526c994 100644 --- a/src/sync/mutex.go +++ b/src/sync/mutex.go @@ -81,6 +81,30 @@ 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 { + 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 true +} + func (m *Mutex) lockSlow() { var waitStartTime int64 starving := false diff --git a/src/sync/mutex_test.go b/src/sync/mutex_test.go index 98c1bf2a5f9bc2fb7386c7eafd5b58907ae0a56e..cca0986a30975ebd9c51cf37d97037b43b666dae 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/pool.go b/src/sync/pool.go index 1ae70127ac24ec137906c7c87dfc28e6ab02d413..d1abb6a8b716136ccd2a5594692b76ec2e460186 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 { @@ -71,7 +71,7 @@ type poolLocal struct { } // from runtime -func fastrand() uint32 +func fastrandn(n uint32) uint32 var poolRaceHash [128]uint64 @@ -80,19 +80,19 @@ 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 } if race.Enabled { - if fastrand()%4 == 0 { + if fastrandn(4) == 0 { // Randomly drop x on floor. 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 65666daab48e66fb3522ccd1bac095e893b4dca7..bb20043a5439174bb21beb75791eeb454897f452 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 @@ -65,7 +64,7 @@ func TestPoolNew(t *testing.T) { i := 0 p := Pool{ - New: func() interface{} { + New: func() any { i++ return i }, @@ -144,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 @@ -271,7 +270,27 @@ func BenchmarkPoolOverflow(b *testing.B) { }) } -var globalSink interface{} +// 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 any func BenchmarkPoolSTW(b *testing.B) { // Take control of GC. @@ -284,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) } @@ -319,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 @@ -329,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 9be83e9a433ef293534447ae6ca3a2556edcc50e..631f2c15fda267d470e7ac90b88e9125cc071edc 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< 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 + } + } + + // 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 { + _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(pipe), F_DUP2FD_CLOEXEC, uintptr(nextfd)) + if err1 != 0 { + goto childerror + } + 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_FCNTL, uintptr(fd[i]), F_DUP2FD_CLOEXEC, uintptr(nextfd)) + if err1 != 0 { + goto childerror + } + 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) + } +} diff --git a/src/syscall/exec_libc.go b/src/syscall/exec_libc.go index 8a84954051a1dc42526fe78e85004d158aac5738..c8549c496444e47e6e659e0948bb339c7bae37b6 100644 --- a/src/syscall/exec_libc.go +++ b/src/syscall/exec_libc.go @@ -3,13 +3,13 @@ // 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. package syscall import ( + "runtime" "unsafe" ) @@ -197,11 +197,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 +218,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/exec_libc2.go b/src/syscall/exec_libc2.go index b999754c2e81bf33c15accea3ab169841af96284..b05f053bbf3fa75cac478f50955454f624f521de 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 @@ -117,14 +116,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. diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index ccc0e39e30bda23cb5f7093b750c6562af14bc40..0f0dee8ea5a90cfba5620dcece364b0349ee2ef7 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 @@ -46,7 +45,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. @@ -448,13 +447,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 +459,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 +484,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 } @@ -553,19 +540,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 { diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index 85b59ad00d94650368e0305ba62b507c0b8824b0..80440ca4d6612703e179c0ec1aa5ffc2672aadca 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 @@ -111,14 +110,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 +192,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) { @@ -526,9 +509,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/syscall/exec_pdeathsig_test.go b/src/syscall/exec_pdeathsig_test.go new file mode 100644 index 0000000000000000000000000000000000000000..96ae27b494ec0e84e861759b0bc592b918e8529b --- /dev/null +++ b/src/syscall/exec_pdeathsig_test.go @@ -0,0 +1,134 @@ +// 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 + +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/exec_solaris_test.go b/src/syscall/exec_solaris_test.go index f54fc8385d59200e6933d4dfcc49e7d07e6a37c3..90e5349bf458db4eeb5996888081dcc1bc63aabd 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 54b18dccd73e266e680d9a5e3250be18ce08ead4..0e41959ffe54301ff0bec90a39ddb174b02f0079 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. @@ -153,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 { @@ -205,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() @@ -244,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. diff --git a/src/syscall/exec_unix_test.go b/src/syscall/exec_unix_test.go index 866671ba2aca759a4c959f8695c775acdc5c71e8..b7ae77552bac68e9b68d22996cebc0e26a858a7b 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 @@ -14,7 +13,6 @@ import ( "os" "os/exec" "os/signal" - "runtime" "syscall" "testing" "time" @@ -328,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) diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go index 18d15028c3d3bba9812e58ea0555f618f6e5a07c..9d10d6a51271f62c2b7daa86db0c774dff5084b6 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 diff --git a/src/syscall/export_unix_test.go b/src/syscall/export_unix_test.go index 2d2c67673d7887fc0b81c04bb12ee99445efd316..2f678d25664bc3283b8977a756be939559c57615 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 3b43b6aeded16e928baba8bcb46874e2c89ad4eb..8cb8f16153a9be79e86c823f608b778a56b8f6be 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 2f3277497cd577946fba274ee5b53aaa01782b14..76a09fc47e3fa823e4d4b8cf7f126fb5961f0cd1 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 79cbdf4150f5354fb3ccb913019ded8a656ace5e..6f7d29ce67aea1597649d08e1eeed3f4506531ed 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 e57240c156157a033e4211157049c467c17b84b6..312244c0d8ab0c604b917c0b72c4652ebe58ef1f 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 0170516201473f85afc8e7ecc49a92ba65194b91..3541446b0bd31ac1a7b75b94bf45fd5a9462f658 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 @@ -492,14 +491,14 @@ func Pipe(fd []int) error { return ENOSYS } -func fsCall(name string, args ...interface{}) (js.Value, error) { +func fsCall(name string, args ...any) (js.Value, error) { type callResult struct { val js.Value err error } c := make(chan callResult, 1) - f := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + f := js.FuncOf(func(this js.Value, args []js.Value) any { var res callResult if len(args) >= 1 { // on Node.js 8, fs.utimes calls the callback without any arguments diff --git a/src/syscall/getdirentries_test.go b/src/syscall/getdirentries_test.go index 814e656649b8eda0ae780ce63ddbafc682a9205b..ddd8208c15483766dfae78dde39d6cdce13fd6e5 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/js/export_test.go b/src/syscall/js/export_test.go index 1b5ed3ce8491c2838e5b430ad4a57bfc5fc48ce7..fb61daea7cea00f4732496c8a0a344e73ccbe345 100644 --- a/src/syscall/js/export_test.go +++ b/src/syscall/js/export_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. -// +build js,wasm +//go:build js && wasm package js diff --git a/src/syscall/js/func.go b/src/syscall/js/func.go index da4cf68774ddcd6ebd25aaaf1c93f548595883cb..cc9497236450bb829f90dce982b577eef9b7fd54 100644 --- a/src/syscall/js/func.go +++ b/src/syscall/js/func.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 js,wasm +//go:build js && wasm package js @@ -10,12 +10,10 @@ 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 ) -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 @@ -40,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 a48bbd4dd794b707bbb50a49fee6691b8eed7340..a5210faf7fd26cbd8497269334fbe78d6a4bcf34 100644 --- a/src/syscall/js/js.go +++ b/src/syscall/js/js.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 js,wasm +//go: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. @@ -27,12 +27,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 { @@ -50,11 +44,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 @@ -159,12 +148,12 @@ 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: // 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: @@ -203,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) @@ -307,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}) } @@ -346,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}) } @@ -358,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 { @@ -385,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) @@ -407,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) @@ -426,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 5fc9107d40250ce9da212e5db934a7c1c49da446..f860a5bb50581bddc428f2417933652004ba94b1 100644 --- a/src/syscall/js/js_test.go +++ b/src/syscall/js/js_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. -// +build js,wasm +//go:build js && wasm // To run these tests: // @@ -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/mkall.sh b/src/syscall/mkall.sh index dffb52864bad59de3f1c033c3c8ce98e6f3c7add..5fc91d381584297e61226399a327c9d0e1a72245 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" diff --git a/src/syscall/mkasm.go b/src/syscall/mkasm.go index e0ec46681d14a5ed20f10e713461089d05a4ebae..dce61f322c08e3184aaa69cf87e9c7b2b4847a16 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 94e8d92eff86c0e03df88125c1848f2d6f9f266f..4f81b81b57e528891f211ebd5aee7ea3b2f23157 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.pl b/src/syscall/mksyscall.pl index 758948bc53fe1364c29b97717964f27d77092ea6..25ab911b7c6a46a958daf60ef76dafd70cb7d628 100755 --- a/src/syscall/mksyscall.pl +++ b/src/syscall/mksyscall.pl @@ -387,7 +387,6 @@ print <> 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 } @@ -268,9 +270,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 } @@ -323,10 +323,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 { @@ -355,27 +354,10 @@ 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 -} - -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) @@ -441,9 +423,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: @@ -451,9 +431,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 595e705856ec3f407f3c77fe974e155736b298a9..5e636d5258046296d17ecdedd347a904631de3d3 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 @@ -168,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 } @@ -184,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 } @@ -215,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 } @@ -233,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: @@ -267,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: @@ -278,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 @@ -371,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 { @@ -398,29 +384,12 @@ 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 } //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) @@ -524,12 +493,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_bsd_test.go b/src/syscall/syscall_bsd_test.go index 2d8a8cbfe6125bfe2fe3d3323e72368ad42c76a9..98fab1d3963c8dd9e4ad1871d4829deb94983ccc 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_darwin.go b/src/syscall/syscall_darwin.go index a4fe4f1962bb7e096ff2c17461f775150dbf2455..902d6e77e11cb2bbf0e9512704a43ed8e77532f6 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) { @@ -96,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 } @@ -120,42 +106,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 b01a4ada67525e356195c6a1314a70bdeff50098..f3c0f545214c8e2bffd9d2a5b7f0181cb61604cc 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 @@ -96,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) @@ -109,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 } @@ -156,11 +164,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_dup2_linux.go b/src/syscall/syscall_dup2_linux.go deleted file mode 100644 index 351a96edc18c2fe59e057fbd53b93a6b5d547133..0000000000000000000000000000000000000000 --- 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_freebsd.go b/src/syscall/syscall_freebsd.go index 7c7b89aab9030aa91683b372267d96bb49166217..ecb9ec825aa0dd3e60874004f8f7e51b2db3dcfe 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 } @@ -176,11 +178,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_freebsd_test.go b/src/syscall/syscall_freebsd_test.go index 89c7959d0c43ac3e81b0e9d70722fe8c48dc43fe..f04b12b6d3ca4df1c5749cb8d970ecb5e035ccd4 100644 --- a/src/syscall/syscall_freebsd_test.go +++ b/src/syscall/syscall_freebsd_test.go @@ -3,12 +3,12 @@ // license that can be found in the LICENSE file. //go:build freebsd -// +build freebsd package syscall_test import ( "fmt" + "os" "syscall" "testing" "unsafe" @@ -53,3 +53,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_illumos.go b/src/syscall/syscall_illumos.go index ef95fe58f7c58cd70ead9ba6429b3af5f02b083d..de6b1600484a8d2e28589f353f32adee89869c86 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 ed70d622842da2c45106474f14ca0a95388eb442..cd9549906360b1b71bea8fc34d2b7875b52ab502 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.go b/src/syscall/syscall_linux.go index dfce3d0a4bac336618108e00b7ef0927afbb7029..abcf1d5dfefc5756761c337c344f40d6306981db 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -161,6 +161,25 @@ 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) + if err == nil { + 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) { @@ -204,18 +223,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) { @@ -387,9 +395,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 } @@ -402,9 +408,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 } @@ -455,9 +459,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 } @@ -496,9 +498,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: @@ -531,9 +531,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: @@ -542,9 +540,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 @@ -553,11 +549,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 } @@ -648,10 +640,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 { @@ -682,28 +673,10 @@ 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 } -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_linux_386.go b/src/syscall/syscall_linux_386.go index 0db037470d438761c4c290d27384aafe43c7eda2..98442055d80ea7c5c6837c5891bb6e7726c88722 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 5df3f796d1677785114bad853ae8479e8fee83b6..04acd063fa69e407184f67a8394e088732f43f4f 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 e887cf788f3ae20cab1ee83a502ff054f1383d97..f2f342e7ed25ed485ec12a187308f82825c3d516 100644 --- a/src/syscall/syscall_linux_arm.go +++ b/src/syscall/syscall_linux_arm.go @@ -22,36 +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 - // 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 -} - // 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 f575c84c930c2d0a884893289a285a939a0b4b07..990e732f359f0404654bd076cdcc9aee9482359f 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) @@ -146,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 5feb03e915adf0021f5060b2fa6e5b88d9b973b7..7c9dd80614a451c96b37106f6f5bd73b38f4b80c 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 @@ -103,30 +101,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 39104d71d84520f8fe6dd3bb17d8944635354318..741eeb14bbb67b7c5d717b94d9d5fbf21f1a3338 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 @@ -112,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) { diff --git a/src/syscall/syscall_linux_ppc64x.go b/src/syscall/syscall_linux_ppc64x.go index 495ae29757cac649b2a3b9cb754a0be19d1ff1e2..cc1b72e0e79cca158dfcd7559191c3b0e9a5661a 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 @@ -82,30 +80,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 2a0fe64d258617a8dc147d17d55cc8d205e0905b..bcb89c6e9aca20b63d42246ff7cb3bc5f2faa3b0 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 0f6f6277bbfda2b02aab58268b77ce9b796c2097..123664f5b2b98acf760310c11eef871eb10b3fdb 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/syscall_linux_test.go b/src/syscall/syscall_linux_test.go index 442dc9f10eb87f17b8b1f7d560011c8329fb44cf..8d828be0153348feeb9014d1a9894e3de1d17d16 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, diff --git a/src/syscall/syscall_netbsd.go b/src/syscall/syscall_netbsd.go index fc13b706b5da3c621f87177263e62984d433ea53..0d562cc78e42b3bd4efe31a57e1e7583979cb99e 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 @@ -112,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 } @@ -146,11 +150,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 5a5ba5a51b07b7d7f908b74a2831c2ab57c338c7..fa939ec5c8849501ba5467bebb7baf209b30a13e 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 } @@ -121,11 +123,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_openbsd1.go b/src/syscall/syscall_openbsd1.go index 15870ce1ee1523289608e02f9a98f82b2a1c81be..bddeda637a9815741058e9249b7a8b9ecdd38000 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 e67ee4e571c264eae8e1aea91d042666cab6c623..15b68fd0fcf51c780738f12ee73b00526f1c36ac 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_openbsd_mips64.go b/src/syscall/syscall_openbsd_mips64.go index b259dc69755b7d9cd3a4f74c00ed624590386dac..e8ae2e9911bafa336ce75b93eeff422602366088 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} } diff --git a/src/syscall/syscall_plan9.go b/src/syscall/syscall_plan9.go index d16cad45d851da0de4cb30a954f98f3c3c349dbe..6a8ab97dc6cc9238d5d8af1073005156c94343d0 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_ptrace_test.go b/src/syscall/syscall_ptrace_test.go index 45729d9e8e9698b187aced0e53eb75f79d0bd54c..5b128de77954574f1f29eb324d78a57ad3593139 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_solaris.go b/src/syscall/syscall_solaris.go index daa4b88a71d6fcb6d9d03c3048006d52fd9c135f..f44a9e25ac97bde5923eb688f9a67a2c8d11618b 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) @@ -55,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 } @@ -67,9 +71,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 } @@ -82,9 +84,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 } @@ -302,9 +302,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: @@ -313,9 +311,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 @@ -338,10 +334,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 { @@ -364,29 +359,12 @@ 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 -} - -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 5b405b99b4f23744bb35f308ab1b8b015d3994ee..5ee938115d4941a2467abe2b45d4da14693f1770 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 @@ -198,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 } @@ -219,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 } @@ -292,6 +297,119 @@ 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 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) + // 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 +} + +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 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 { + 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 { diff --git a/src/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go index af0bc856ee8f9dc3c092492ae093591d4b9f003f..e4af0ba4a595f67bd975ded647205310fc228bdf 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 @@ -85,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) @@ -252,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) diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index 660179ae9e8cf32ddccb2e09b3ac45dbf136f860..78e46a656d8ddaf7f8791f82cf1b92128ccb2772 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) } @@ -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 @@ -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 } @@ -738,9 +744,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 +764,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 +837,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 +846,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 @@ -924,6 +922,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() } @@ -1271,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/tables_js.go b/src/syscall/tables_js.go index 64d958415d8f8be750a355e1cc40b258270a7070..78a1e71a016e308e51b3ee7760de690570f512af 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 cf88aeb921a1621891a01258995357db53022df4..b60fe60b03c403155ae6a4ef8b8c4780ae635d6b 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 5eaa2daabd3f0537d95b5f759c78e05d4a866d2c..231875d8c3c92c9824712a9504cf855fd2133c19 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 e4f3d50f56b68bb23bcea2db498d89b475f968aa..7cf4be45b126634d34fbb6b8024a89229f0b5b96 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 6588d690eabd68a088ea95191eb4f4bd0eec3dc7..9e05af90ee5bca0a7e12b57c5a5284f2b6b49953 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 c2a32c0782edaec711eea9b173e047482766c56b..c9404aaf1bebda0113347f0d46f1d0c35ca31817 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 9f8d5bc3ddc06e5a75899d29c316ab6eb255c6b1..33420c4a92434da27290d84b5f0147928777be99 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 d7414117036779dcd7e96997eca38346d7ef2cdb..83bc7dc49979a9f35d1d179401323cdbdf6e7813 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 254e3e7cfeddb4ba6f67941d8c78d5539227df5d..22c172f1f7d9882725677f0806c7857268497095 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 bf76be978bce1f6e309ae7ca0b12a71433e64e9b..23a76edd902dd289a13384a69726a2a38d35f6ad 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 0bd25ea3c953d82796c364c5bf18527e95c6caec..e53e8c9386f5a7919d6c97221967f7f0cea22f30 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 8b41cdca230bf5b525e275a9dd0e41a60761b81f..bfe6e9f592f5ae60f442ccf4f6f1029d55ab30d4 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 179f7914817e85ecbf5974a3e9fdd29f33957b60..2f56bc06010261f5b327bdc54a2ad6987e3d3ca7 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 0b9897284c4d447af040193172dab90a29d5db57..ecbe89c5473a7cb2dcf482ccf2a360b4b4c81bf6 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 5f210fd1c40b2a1878db0078695bb6738402fbea..fa7cb845c316896000d52bca5c124e76edfc8c9b 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 35e2a52d253b6daafc0d20c80a6603af74c5caed..bca2f50c9695da591b3f54861f483425591176d9 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 aec26ad7785c8ff630c7f0c421b0ba74d6f62ec5..b1441e76a3c77d39453a4abc4fd77f8375ff75b1 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 d6d13e4155865c5127c9849eb46e7e978e9db77f..3aed004986d0bec029344c5ace1048294adb37e1 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 15c714fad810731547b6ada3eed9f90ee18a2b07..e1f91ff86cb7ec288919c2bafd74213a566ba2d6 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 b20ce7d82319e218eeb683269bf560bc63b0ffaf..d0cb6c8ac751bab068a6d963c19b3c65d9c91675 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 fb64932ad620945d8c3ab0c82c38793c5ac36503..5e4c867bc90a102b7e809c564f4c8fa6dd3cfdfe 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 3a92bcdbb46b1e939787f25ebcd915da5cbc18e9..3ff6e498e78df093c45134730ae0e3d9b9aa3c81 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 e013d8e7fd682fde0b041f9c37d2e11dad46ff02..35825cc9fb4b1287b1deb795c886aa7e2807dae2 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 1a4d33e3fd5cc95949e0ca057acecee74bd350a7..444b8816d56490692eabe63c34e36279a262103d 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 1dda43be70fc259a2ba873d0afe45df1ef93ce5c..dd439acc5823497b60535569c059d4ebff888a29 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 6d56f1c99817c25d1666e5aad9a27f758308a269..b71cb0b4e7ead7e09c66f17aee5b465f6cf3a818 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 934e9ef073abf72f977ee0a0ef50ae7763047208..b2fcb65782e98cb580b61cd37798adf5a435dfd9 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 0f5ad61a9f29a859f6f0b880448b909cb2dd2747..dc52c3ca573ec863aee220bfb8ec3ca81181d5bd 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 9d8678750d4cca58417b93091c49512f02f4ab0f..3137e18a2471f54b0778b68b42132e3884f4799a 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 7adb72f7edd622bfe9805359f7cb4edd3d4da43e..cc1b0088c9ab95655cfbe65f95202f3129c2450b 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 a8457c6edfe8b6cde64cf49d3302b2d049c7e99e..d17ecb96e50c5d3898b9d818ea34dde0d6963683 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 eb19537a2ac9ed6104cd1e7368721edaa76315c2..4904e7614f3d185d98bf7dfb172dab319b67db82 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 89a4e6d89a54b56f04bf2d15aa719b48c7269fd4..76ac9173a93f2ae1ee77744184899155d08264ab 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 b7dee696029654eea3992e4e3cd4a42233cbdb09..fb25dacee43f8d88655528d3b9721273cd01772b 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 134ae41165bd76cd33afecea1d65c2b1f2bdc6ff..94f1b4371c5724bee5b75b0d37e669a0f435c615 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 07a519d7d65fa92463e100d88b037abf71cd67c6..0ccdaf2d0eea6d2613201cd72d1951bcbaca527a 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 @@ -345,6 +344,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 492f94785548754bc70c6db0c60ba87217f5a959..563083d441a17c7600c4265e4104adc9498bc60b 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 5ae096730eae21ee5858b4ab9b7f4d594935a03c..09bf34bb3c55e4fd8aecaac90af61fb16c18a96c 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 @@ -345,6 +344,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 b606c6e49e35bba658ee8f19eb432debeb6fd820..0567a42fa337985c3b5d0115cf27299c9ebe04d4 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 diff --git a/src/syscall/zsyscall_dragonfly_amd64.go b/src/syscall/zsyscall_dragonfly_amd64.go index aa327c001095362fa7fd81f9716e28c51d78aeb8..5d5576d76ff64608d701aa5cee06a2f4323af85d 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 7137d66f0b232f710cf5d4e9a861c9215df042ad..ed0eb9fa15e68802b9e0e662f06f98b983f8f554 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 d721dafde28b7acd47838618ce5886b728833ab8..e291a5675688c56b21471d71046613a1b039e4bf 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 d9dbea921a141194ababeb30feab15497e85b3cf..7dd856fd970946c62507a7611dd65dcbbcece17f 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 a24f0115e2ce09595bec7818eb704443f3a24de7..229a9a22387bd7c324d349c5fa5d827fb831180e 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 ac822d6f7a435dde180689e7f217f90e1c972cd8..c385dd3ca140098e6fe63d85159de34a230d77e7 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 @@ -76,6 +75,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 +1057,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 ed37fa8decaa08bb6d3f6416ba623176654424d8..2059271324f7fee4da4a765b711c49c9b460d862 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 @@ -76,6 +75,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 +1653,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 213aaf3bac40a18ab11647ee6e3ebbb16c3dbf81..50498c6eb6792acb8f7e87ccb455e33e66cc62f3 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 @@ -76,6 +75,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 +1057,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 e2f9c0fd9b06e2cd0d60fbdb8dc8ce6170698001..6714123f9c7f7a367c79fb6af9f1af8e796e7900 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 @@ -76,6 +75,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 +1564,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 617c2f54663309179f6182694c4102734bdbf887..c6f4878ff7ba139b11d2b72bdf15fcf17f4602ed 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 @@ -76,6 +75,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 +1655,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 793d4b98846a4e7691c946eb3af2ab7b6d93d5e1..5187c28ebb6050c8fb5e20c91afb9981999541a4 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 @@ -76,6 +75,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 +1651,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 54e1760bda6d081a01cf174d439962273e1a14ce..f3dacfeedaff9316b569431464d39ad3722e7aa4 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 @@ -76,6 +75,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 +1651,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 ba7e2118c04e5769079a61229255a798b2ac247f..fbc543709fc163fef73e18d76320abf78e03a4df 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 @@ -76,6 +75,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 +1655,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 c3437722e02f50c49e40ebdb05a9b4d486eedc11..b71dca2b371e611a29ea287d4392112ac9b44cac 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 @@ -76,6 +75,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 +1712,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 acc34a76d2b6315a3f864773c5131191445531b2..193fbbc5418ecf2a49c8a62cf5afdb61999025fc 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 @@ -76,6 +75,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 +1712,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 d662d780db9d8fd8c3eda1de74b5816c0e548922..33b1e9b4312a6cdb7348b4b6a783ca6dfd0fb22d 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 @@ -76,6 +75,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 +1564,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 20f8c61366ca1eef8721a36a00c523a5351b9fc8..2ab78c71bfe39d1085dc90e7610d495abfca405d 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 @@ -76,6 +75,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 +1499,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 -} diff --git a/src/syscall/zsyscall_netbsd_386.go b/src/syscall/zsyscall_netbsd_386.go index 07ff5fba5f6a511feb5b368cbc06571fdc10d5ef..408318181af20c32446111d2933d643dc0f26d7f 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 ffb4e059a4b5aa64781b50448bd5c465c1a268cb..2039cf6d0ea80f318d113a7966a22f55e2800f51 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 37df77e5e8cbbf1dd7eb68c6b1b7423284fe83bc..3c287ea223d1e80e35acbce97633546469be5651 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 c5eb57a2269d6ff73eea66f5d7b9a636ae6201bc..1d40db9e6b632d541117fac2d0d91a437f4fb330 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 1ff5c95fa19855498cde553ddbfba410e33e4e51..5f95d7a9c6dbcec0bb9faaa38e7230cf972624c5 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 85cb195739f2966b04f4084ba716210220f2957c..189bf887e6223fd29f665da34b292968f7513994 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 04a2fadccddde263cc040a910b2799b1aa310535..c7513a3ac9af4c754ea2c0f02b5177c499d76d23 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 fa35905d1bcf9cb259f11aafdd7ca9d6e4c74bc6..293b70360021896c2d9a17a50af2367674d6ed42 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 70fd1474fd3f9b88e9f3cdd3f5b16edd7134b832..51904b5e29dc1ad1b5e85af65b177e86aca92dbf 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 8b7727b3435e88d4fc0824b31bc0d343e2303632..32fa0f0eb6e2b7d98071184bd5753f37df3d1799 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 bed9108ea6e2d5e242a73e07a30443db5d2a538d..b3337ce8110c977f58e0dffca0d96f6e5641a39d 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 7bbcf9b4b795065e600d47168d3ece2d579bd8cd..3705566fa3a4895a41694f77a5f9e40a690848aa 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 9b37dc09506f2860c011fbea13d65a62ecdf18cf..2d8cdfd280b807a0dd337ba2feab818eaad93934 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/zsyscall_windows.go b/src/syscall/zsyscall_windows.go index 7bfff16be6ac325fa9a406f98b76aa0542b39948..2d6f34e059d75bec84413d7249548a714f3edaeb 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) diff --git a/src/syscall/zsysnum_darwin_amd64.go b/src/syscall/zsysnum_darwin_amd64.go index f66f7d2715feba2ce0dc68f9e45157fb26bf6df3..08e003f2926448046e5a0f0ff76f814fc8262a28 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 6fa146368aff59ca847f7c520b1b0e468c4bdd35..71309bb4d6f7f83fb645b899a23f46f15e9e9a33 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 e8996db0f8dd580f016d94d5c50e29d168a3e7ef..03d4b06a09b40145b747dab7dd26f98c481f7ce2 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 1ed7e3ee8d3e3d7c70107ae5afa6b0395d0b350f..355b2ec3039cda704df92ebc33a717bf874ec651 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 d72dbc944a1b74e1d2c706c1a6f9135154b5053b..84c821c955f9e1956fbfcccf90d37a31fc242480 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 4f4dc4db7959e32e887f35e44341c30aa1a64d96..785e7875f40d2986eb474523be6a21518e0dc393 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 ab1a05258e7e95fa0e050703b28848091e1ebe12..7144a8abed126c460c8b7fb36fb987e69d1c0eeb 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 792f43550e99f59a254745d60fc05da41c14a6e8..4966d2a94714e89d4634275c25d3bdfd281d7cf3 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 9ea18d6111398c86976162a94af975bbe941d4cd..576c7c36a6b7eb70cf0e3b311f428fdc097b35bb 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 ccae9c15e32249b5cbb62f05a19b9037ac48d896..b0da97c64bc32d6848fa0a27a438e8fd4b595486 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 17c54a2c833bf4fcff45d7fd9c884691b0edc368..0136d9440b897a9a2b762cb8cd07e6362a632e9a 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 a0d37ff1f2701354c9baa4c1dbe4828fec695c76..cc964c23e2eef022236ffe12a5db01663529d8ec 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 f8f82d20432359617871f620222b5a229bc5213e..57bfb7795f23418fc95d0ebbcfe056129f4c5c56 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 fd0c32995142f826538f02638e0ed3cd0e6552d3..5696c4befebc897d49127e2f511e34e87116be75 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 03f2cd3bd328e7a5fb5fe2a98c193e5a22aad6ea..9fb85cddbaf858168fe7006444a34b6b6a7e7926 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 7b356e7102c06b3af3c72a105ec0f161e49b484d..e0e8994641ab71b19569f06597e2218411d739ea 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 3f57ec4d894e09d01956c200369ce6c4f9062aa9..9653364dae9411283badfca0d44cd56804c63359 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 b289886d6c61fc8710677ee881dacc0ba772d9bc..3b12639bd739930a8ac4b2e95092d94a3be56135 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 8cf2b68dcd3abe18c6b7b4f6b37c05af7ae9cd11..bce309dc5d94dbd79550032fadf0173db8c52473 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 cc33773a05833901c36ac0294832a450f3ac2996..05aed70762df58a68116c3f122c4ef28196ed32f 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 23c9c715b5215c1ac807496c24f1dc016a1290c2..ea244e535ec42ad2f1d433f05afe67e7525ae000 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 8feacc47ab5142754766f8df8aff93e38ce7b18e..551edc702578d18cc10307b193d1ee6fbc85560f 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 8079d22429b4500e23e7e30c5e51f1f03b8d73bb..46f78a97eb2950c937850757144a37f327e0bf75 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 a51e0038bb9bda3278b36ef995991f355c6a6c59..ec519b72ec15841fe1235b6a67c5966ddfbe644e 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 173972688387bf12da427087c0a77c0897ec36fa..e1946dece8d3f2d3dddb857d4d9eba7eb10977c6 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 0457d8e995918784465b0228151f55fed4f95909..a718345d799b949b4683e1f95a7807e5072ea603 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 29c8380d898784c348689090b86d90ade1c9a1f9..9c5a0667132a9911a568ef3c5d5fcc1560a359d6 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 6472db00809a51972811ffb3658f508217971372..3ccd9fc0dd7962247e9d81db35823f101fbd53a1 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 251a0c0b4ad249be800e35b96b432d15dd4ba57c..a45511e84760855810ed4f7ddc4d987f1bf31e36 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 34c953fc8bf45ae9ee7f4ff90e3cfa8cd58f5308..1bab13bf431ece2f79c01710b5d3206b41daa361 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 4de656b491e74a6283fbfed3ca29dd680a743b28..a4d61bd19bbe88000d55cdcfe605498cb828980a 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 bed9cb08515eb014b933edfe5ad8b178f6eb57e6..1e469c36d2eddb6b19992e6edbd1ee8f437b1316 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 355533fb27cb4730c170e9c75b6785ebabdb1262..c830cee966bf86d9e14a126da6c85709b8d5a100 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 94e12c742c8033e4a9e11d9e66b8351987277f9f..770ddc9fe9a23bdfb0fadfa0cabbd60a9dd21084 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 321460f45aa386047a84aac6f8777f57331ab360..74eaa4a15034b0b7593684944b5155dda475903f 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 370d7172634361212d3e7ec55c357df3e5789dfc..fc28fc9bb8f77f36cbad371d982de26aa9a6b15c 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 557c6345339c080fb6ac4e8b79cc7ae1441e8ec3..1f885048dd65f7461a4cde811439679024f5b26d 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 19f36903412e76d3b635aa1555e4ba36a7629f64..cac74693d756a87789ad34f83504d0ea544cfaa6 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 222c6c7e46520b2abf78e7f255afe21b66573a70..f9ba685e25269dbe21168cb827ae46f7c6c0c6f0 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 644ee9b3dfbe7192051b9a50957140323fe81768..889b9551ae9024572f3ec7e0fc410450994d1288 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 64e16b494350738844ca4334d944922034360285..d486cd002f967bf715f7ea7e94f694b52186b9d5 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/allocs_test.go b/src/testing/allocs_test.go index 5b346aaf83873ad5feb5196403abfdf76aa372d4..bbd3ae79c85311a6de9f28d857fc1fdae9cf5442 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/benchmark.go b/src/testing/benchmark.go index 15b4426c5a544cbc081bde34d7647bd3eb6f9365..d8ec217f66c628e0950a6223dd0a67e12625f8a0 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -32,35 +32,36 @@ 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 { - d time.Duration - n int +type durationOrCountFlag struct { + d time.Duration + n int + allowZero bool } -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() + return 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 { + if err != nil || n < 0 || (!f.allowZero && 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 { + if err != nil || d < 0 || (!f.allowZero && d == 0) { return fmt.Errorf("invalid duration") } - *f = benchTimeFlag{d: d} + *f = durationOrCountFlag{d: d} return nil } @@ -98,7 +99,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 @@ -298,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; { diff --git a/src/testing/example.go b/src/testing/example.go index 0217c5d2425a61ba69421a97c11434adc599b043..f33e8d2f926e0ac8cd4874e012a24ac6b58a5f5f 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 9fef2f4696ec7944acc891eb3c69e86a3f376139..4595b7313db9dd9d1e3f7445b3427f107f1b3b17 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) @@ -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 } @@ -154,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/mapfs_test.go b/src/testing/fstest/mapfs_test.go index 2abedd67351fc4d4b258225c7ec79d5d02764fad..c8d29283b28989c942ac9b00d51c1311717876fa 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) + } +} diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go index 5c4f30af168422c75c05b2c272b9fbc430320592..9a65fbbd0bb27dd13c2f4efc2b0998fa5fab0650 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 new file mode 100644 index 0000000000000000000000000000000000000000..4a5def1ab4136cefcb9be1584e1187a9595f25e1 --- /dev/null +++ b/src/testing/fuzz.go @@ -0,0 +1,701 @@ +// 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 ( + "bytes" + "errors" + "flag" + "fmt" + "io" + "os" + "path/filepath" + "reflect" + "runtime" + "sync/atomic" + "time" +) + +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 (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 ( + matchFuzz *string + fuzzDuration durationOrCountFlag + minimizeDuration = durationOrCountFlag{d: 60 * time.Second, allowZero: true} + fuzzCacheDir *string + isFuzzWorker *bool + + // 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 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. +type InternalFuzzTarget struct { + Name string + Fn func(f *F) +} + +// F is a type passed to fuzz tests. +// +// Fuzz tests run generated inputs against a provided fuzz target, which can +// find and report potential bugs in the code being tested. +// +// 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 + testContext *testContext + + // 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 +// import internal/fuzz from testing. +type corpusEntry = struct { + Parent string + Path string + Data []byte + Values []any + Generation int + IsSeed bool +} + +// 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 fuzz target, use t.Helper instead") + } + + // 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 + } +} + +// 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.Fail was called inside the fuzz target, use t.Fail instead") + } + f.common.Helper() + f.common.Fail() +} + +// 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.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 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 ...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)) + } + values = append(values, args[i]) + } + 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. +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 +// 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) { ... }) +// +// 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. +// +// 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 +// 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 beforehand. +func (f *F) Fuzz(ff any) { + if f.fuzzCalled { + 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{}) + 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: 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. + 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) + } + + // 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.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.deps.ReadCorpus(filepath.Join(corpusDir, f.name), types) + if err != nil { + f.Fatal(err) + } + 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 + } + } + + 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. + // fn is called in its own goroutine. + 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 true + } + testName := f.name + 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 + // 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, + } + 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. + t.chatty.Updatef(t.name, "=== RUN %s\n", t.name) + } + f.common.inFuzzFn, f.inFuzzFn = true, true + go tRunner(t, func(t *T) { + args := []reflect.Value{reflect.ValueOf(t)} + 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.deps.SnapshotCoverage() + f.fuzzContext.deps.ResetCoverage() + fn.Call(args) + }) + <-t.signal + f.common.inFuzzFn, f.inFuzzFn = false, false + return !t.Failed() + } + + 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.deps.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() + fmt.Fprintf(f.w, "%v\n", err) + if crashErr, ok := err.(fuzzCrashError); ok { + crashPath := crashErr.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) + } + } + // TODO(jayconrod,katiehockman): Aggregate statistics across workers + // and add to FuzzResult (ie. time taken, num iterations) + + case fuzzWorker: + // Fuzzing is enabled, and this is a worker process. Follow instructions + // from the coordinator. + 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 failing input should not be recorded. + f.Errorf("communicating with fuzzing coordinator: %v", err) + } + + default: + // Fuzzing is not enabled, or will be done later. Only run the seed + // corpus now. + 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(f.w, e) + } + } + } +} + +func (f *F) report() { + if *isFuzzWorker || f.parent == nil { + return + } + dstr := fmtDuration(f.duration) + format := "--- %s: %s (%s)\n" + if f.Failed() { + f.flushToParent(f.name, format, "FAIL", f.name, dstr) + } else if f.chatty != nil { + if f.Skipped() { + f.flushToParent(f.name, format, "SKIP", f.name, dstr) + } else { + f.flushToParent(f.name, format, "PASS", f.name, dstr) + } + } +} + +// 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 failing input +} + +func (r fuzzResult) String() string { + if r.Error == nil { + return "" + } + return r.Error.Error() +} + +// 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. +type fuzzCrashError interface { + error + Unwrap() error + + // 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=$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 tests. +type fuzzContext struct { + deps testDeps + mode fuzzMode +} + +type fuzzMode uint8 + +const ( + seedCorpusOnly fuzzMode = iota + fuzzCoordinator + fuzzWorker +) + +// 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(fuzzTests) == 0 || *isFuzzWorker { + return ran, ok + } + 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() { + root.chatty = newChattyPrinter(root.w) + } + for _, ft := range fuzzTests { + if shouldFailFast() { + break + } + testName, matched, _ := tctx.match.fullName(nil, ft.Name) + if !matched { + continue + } + if mFuzz != nil { + if _, fuzzMatched, _ := mFuzz.fullName(nil, ft.Name); fuzzMatched { + // If this 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), + barrier: 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 { + // TODO(#48132): adjust this to work with test2json. + f.chatty.Updatef(f.name, "=== RUN %s\n", f.name) + } + + go fRunner(f, ft.Fn) + <-f.signal + } + return root.ran, !root.Failed() +} + +// 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, fuzzTests []InternalFuzzTarget) (ok bool) { + if len(fuzzTests) == 0 || *matchFuzz == "" { + return true + } + m := newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz") + tctx := newTestContext(1, m) + tctx.isFuzzing = true + fctx := &fuzzContext{ + deps: deps, + } + root := common{w: os.Stdout} + if *isFuzzWorker { + root.w = io.Discard + fctx.mode = fuzzWorker + } else { + fctx.mode = fuzzCoordinator + } + if Verbose() && !*isFuzzWorker { + root.chatty = newChattyPrinter(root.w) + } + var fuzzTest *InternalFuzzTarget + var testName string + var matched []string + for i := range fuzzTests { + name, ok, _ := tctx.match.fullName(nil, fuzzTests[i].Name) + if !ok { + continue + } + matched = append(matched, name) + fuzzTest = &fuzzTests[i] + testName = name + } + if len(matched) == 0 { + 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 fuzz test: %v\n", matched) + return false + } + + 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 f.chatty != nil { + // TODO(#48132): adjust this to work with test2json. + f.chatty.Updatef(f.name, "=== FUZZ %s\n", f.name) + } + go fRunner(f, fuzzTest.Fn) + <-f.signal + return !f.failed +} + +// 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. +// 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 test is done. + defer func() { + // 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) + } + err := recover() + 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 F.FailNow. See issue 41355. + didPanic := false + defer func() { + 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 we recovered a panic or inappropriate runtime.Goexit, fail the test, + // flush the output log up to the root, then panic. + doPanic := func(err any) { + 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) + d := root.duration + 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. + f.duration += time.Since(f.start) + + if len(f.sub) > 0 { + // Unblock inputs that called T.Parallel while running the seed corpus. + // 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) + // 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() + }() + defer func() { + if len(f.sub) == 0 { + f.runCleanup(normalPanic) + } + }() + + f.start = time.Now() + fn(f) + + // Code beyond this point will not be executed when FailNow or SkipNow + // is invoked. + f.mu.Lock() + f.finished = true + f.mu.Unlock() +} diff --git a/src/testing/helper_test.go b/src/testing/helper_test.go index b27fd62ee8f7182c5c1709f60a1e62908ce051cf..6175410f18a7c276f456c70f7848d7343b1ec52f 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 df0476ed7323de68fe7a7d8e6dba0aa93658c33f..272b33c0e5095ba2712324749821867e133c2c40 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/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 3608d332946e2ebee0558a35c35c7930a65e923a..2e85a41b07751cd443410e3940dceecc0735862d 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -12,12 +12,18 @@ package testdeps import ( "bufio" + "context" + "internal/fuzz" "internal/testlog" "io" + "os" + "os/signal" + "reflect" "regexp" "runtime/pprof" "strings" "sync" + "time" ) // TestDeps is an implementation of the testing.testDeps interface, @@ -126,3 +132,68 @@ func (TestDeps) StopTestLog() error { func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } + +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, + Limit: limit, + MinimizeTimeout: minimizeTimeout, + MinimizeLimit: minimizeLimit, + Parallel: parallel, + Seed: seed, + Types: types, + CorpusDir: corpusDir, + CacheDir: cacheDir, + }) + if err == ctx.Err() { + return nil + } + return err +} + +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. + // 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 := signal.NotifyContext(context.Background(), os.Interrupt) + defer cancel() + err := fuzz.RunFuzzWorker(ctx, fn) + if err == ctx.Err() { + return nil + } + return err +} + +func (TestDeps) ReadCorpus(dir string, types []reflect.Type) ([]fuzz.CorpusEntry, error) { + return fuzz.ReadCorpus(dir, types) +} + +func (TestDeps) CheckCorpus(vals []any, types []reflect.Type) error { + return fuzz.CheckCorpus(vals, types) +} + +func (TestDeps) ResetCoverage() { + fuzz.ResetCoverage() +} + +func (TestDeps) SnapshotCoverage() { + fuzz.SnapshotCoverage() +} diff --git a/src/testing/match.go b/src/testing/match.go index b18c6e7f389ac64bfa10056ac958f69c50003eb9..d530f70c2676c61c2b43ec56aff204f67e20fcea 100644 --- a/src/testing/match.go +++ b/src/testing/match.go @@ -14,36 +14,52 @@ 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 + 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 { + // 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{}, + subNames: map[string]int32{}, } } @@ -60,22 +76,74 @@ 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 +} + +// 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) { 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,31 +171,88 @@ 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 // 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 8c09dc660fb1a42b164ae8977ba87b8b61b3f294..206ac0b651f4082c3b45380468894341873a0125 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}, @@ -142,45 +149,90 @@ 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 + 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) + } + } +} - 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`}, +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() - for i, tc := range testCases { - if got, _, _ := m.fullName(parent, tc.name); got != tc.want { - t.Errorf("%d:%s: got %q; want %q", i, tc.name, got, tc.want) + 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 { + s := make([]string, len(m)) + for i, m := range m { + s[i] = fmt.Sprintf("%#v", m) } + return fmt.Sprintf("(%s)", strings.Join(s, " | ")) } diff --git a/src/testing/quick/quick.go b/src/testing/quick/quick.go index c01647ecf0c911cdffbebe601975455dd94f6953..e73d307c13a7c65cc040b5da84d533efb1e37a52 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 { @@ -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/run_example.go b/src/testing/run_example.go index d9e342d4951edd62ec5f1537f076b7d38846fb82..e7eab1e50efd7956decdcd9074d6663d2521f3b8 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 d914633ba91889b975e9f764aaed56f9e9c0d90c..adef9511fb56f8700e9517f35c0f910e76a80367 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/testing/sub_test.go b/src/testing/sub_test.go index 6c7d83aac2c036af89e65de2a1f35f44243f52a7..6a5add6f4e89f5f259d8b94ad962ffd955f612d2 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, } @@ -669,7 +670,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 a19238d31e23fa5f308f97230a4f774be9785c91..7bd13a850c0b3281f84d27c9b84a605decb52395 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) { @@ -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 @@ -132,6 +140,71 @@ // example function, at least one other function, type, variable, or constant // declaration, and no test or benchmark functions. // +// Fuzzing +// +// '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. +// +// Functions of the form +// func FuzzXxx(*testing.F) +// are considered fuzz tests. +// +// 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) +// } +// }) +// } +// +// 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 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 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 target is called with the seed inputs +// registered with F.Add and seed inputs from testdata/fuzz/. In this +// 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 +// who are unfamiliar with fuzzing. +// // Skipping // // Tests or benchmarks may be skipped at run time with a call to @@ -144,6 +217,21 @@ // ... // } // +// The Skip method of *T can be used in a fuzz target if the input is invalid, +// but should not be considered a failing input. 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 +251,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 @@ -246,6 +342,7 @@ import ( "io" "math/rand" "os" + "reflect" "runtime" "runtime/debug" "runtime/trace" @@ -307,6 +404,7 @@ func Init() { shuffle = flag.String("test.shuffle", "off", "randomize the execution order of tests and benchmarks") initBenchmarkFlags() + initFuzzFlags() } var ( @@ -355,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() @@ -369,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() @@ -403,6 +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 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. @@ -416,7 +515,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. @@ -458,6 +557,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 fuzz target, 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 @@ -483,6 +588,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 @@ -572,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() @@ -632,24 +740,24 @@ 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{}) - 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 @@ -729,6 +837,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 @@ -797,47 +906,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 ...any) { + 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 ...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() } @@ -851,6 +972,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 @@ -890,6 +1012,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[:]) @@ -923,6 +1046,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() @@ -988,6 +1112,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 { @@ -1016,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() @@ -1080,6 +1205,12 @@ func (t *T) Parallel() { panic("testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests") } 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 @@ -1152,7 +1283,14 @@ 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 @@ -1173,6 +1311,19 @@ func tRunner(t *T, fn func(t *T)) { } } } + + if err != nil && t.context.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 @@ -1189,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) @@ -1242,7 +1393,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() @@ -1327,6 +1478,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. @@ -1390,6 +1547,16 @@ 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, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error { + return errMain +} +func (f matchStringOnly) RunFuzzWorker(func(corpusEntry) error) error { return errMain } +func (f matchStringOnly) ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) { + return nil, errMain +} +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. @@ -1398,15 +1565,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 @@ -1431,18 +1599,25 @@ type testDeps interface { StartTestLog(io.Writer) StopTestLog() error WriteProfileTo(string, io.Writer, int) 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) + CheckCorpus([]any, []reflect.Type) error + ResetCoverage() + SnapshotCoverage() } // 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, } } @@ -1469,9 +1644,15 @@ func (m *M) Run() (code int) { m.exitCode = 2 return } + if *matchFuzz != "" && *fuzzCacheDir == "" { + fmt.Fprintln(os.Stderr, "testing: -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.examples) + listTests(m.deps.MatchString, m.tests, m.benchmarks, m.fuzzTargets, m.examples) m.exitCode = 0 return } @@ -1499,22 +1680,42 @@ 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) - exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples) - m.stopAlarm() - if !testRan && !exampleRan && *matchBenchmarks == "" { - fmt.Fprintln(os.Stderr, "testing: warning: no tests to run") + + // 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 { + deadline := m.startAlarm() + haveExamples = len(m.examples) > 0 + testRan, testOk := runTests(m.deps.MatchString, m.tests, 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 == "" { + 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 !testOk || !exampleOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 { + + fuzzingOk := runFuzzing(m.deps, m.fuzzTargets) + if !fuzzingOk { fmt.Println("FAIL") - m.exitCode = 1 + if *isFuzzWorker { + m.exitCode = fuzzWorkerExitCode + } else { + m.exitCode = 1 + } return } - fmt.Println("PASS") m.exitCode = 0 + if !*isFuzzWorker { + fmt.Println("PASS") + } return } @@ -1535,7 +1736,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) @@ -1551,6 +1752,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) @@ -1580,6 +1786,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{ diff --git a/src/text/scanner/scanner.go b/src/text/scanner/scanner.go index c5fc4ff93b9061de0c32131d65dbadc324507b97..f1fbf9861d06bff843450a1a277efbf94d03b6b5 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/doc.go b/src/text/template/doc.go index 7b3029433690c94b932bbda092392c3599a7b53e..10093881fbef66440d3f9cf46018220049886a19 100644 --- a/src/text/template/doc.go +++ b/src/text/template/doc.go @@ -112,6 +112,14 @@ data, defined in detail in the corresponding sections that follow. T0 is executed; otherwise, dot is set to the successive elements of the array, slice, or map and T1 is executed. + {{break}} + The innermost {{range pipeline}} loop is ended early, stopping the + current iteration and bypassing all remaining iterations. + + {{continue}} + The current iteration of the innermost {{range pipeline}} loop is + stopped, and the loop starts the next iteration. + {{template "name"}} The template with the specified name is executed with nil data. @@ -307,9 +315,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 +353,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 5ad3b4ec582c411fe7d4d3819c03a82f5c0041f9..37984cf91a0740127f448b81fb75c96bc7241a1b 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -5,6 +5,7 @@ package template import ( + "errors" "fmt" "internal/fmtsort" "io" @@ -125,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) @@ -178,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) @@ -196,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 { @@ -243,6 +244,12 @@ func (t *Template) DefinedTemplates() string { return b.String() } +// Sentinel errors for use with panic to signal early exits from range loops. +var ( + walkBreak = errors.New("break") + walkContinue = errors.New("continue") +) + // Walk functions step through the major pieces of the template structure, // generating output as they go. func (s *state) walk(dot reflect.Value, node parse.Node) { @@ -255,7 +262,11 @@ func (s *state) walk(dot reflect.Value, node parse.Node) { if len(node.Pipe.Decl) == 0 { s.printValue(node, val) } + case *parse.BreakNode: + panic(walkBreak) case *parse.CommentNode: + case *parse.ContinueNode: + panic(walkContinue) case *parse.IfNode: s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList) case *parse.ListNode: @@ -300,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)) } @@ -316,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 @@ -334,6 +345,11 @@ func isTrue(val reflect.Value) (truth, ok bool) { func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { s.at(r) + defer func() { + if r := recover(); r != nil && r != walkBreak { + panic(r) + } + }() defer s.pop(s.mark()) val, _ := indirect(s.evalPipeline(dot, r.Pipe)) // mark top of stack before any variables in the body are pushed. @@ -347,8 +363,14 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { if len(r.Pipe.Decl) > 1 { s.setTopVar(2, index) } + defer s.pop(mark) + defer func() { + // Consume panic(walkContinue) + if r := recover(); r != nil && r != walkContinue { + panic(r) + } + }() s.walk(elem, r.List) - s.pop(mark) } switch val.Kind() { case reflect.Array, reflect.Slice: @@ -572,11 +594,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). @@ -601,11 +623,11 @@ 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() { - 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. @@ -613,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) @@ -643,7 +668,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 { @@ -669,7 +694,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 +716,38 @@ 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()) } + + 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) + var v reflect.Value + for _, arg := range args { + v = s.evalArg(dot, argType, arg).Interface().(reflect.Value) + if truth(v) == (name == "or") { + // This value was already unwrapped + // by the .Interface().(reflect.Value). + return v + } + } + if final != missingVal { + // 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 v + } + // Build the arg list. argv := make([]reflect.Value, numIn) // Args must be evaluated. Fixed args first. @@ -728,16 +785,13 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a 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. 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 @@ -774,12 +828,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()) @@ -931,7 +985,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 } @@ -969,8 +1023,8 @@ 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 { +func printableValue(v reflect.Value) (any, bool) { + if v.Kind() == reflect.Pointer { v, _ = indirect(v) // fmt.Fprint handles nil. } if !v.IsValid() { @@ -978,7 +1032,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/src/text/template/exec_test.go b/src/text/template/exec_test.go index ef521645a7f5d5b71c30ddee90362448971ed561..8c8143396dbefe37c067fa3b9f0d796b0bedef02 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}, @@ -481,8 +481,19 @@ 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}, + {"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}, + {"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}, // Indexing. {"slice[0]", "{{index .SI 0}}", "3", tVal, true}, @@ -564,6 +575,8 @@ var execTests = []execTest{ {"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true}, {"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true}, {"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"range []int break else", "{{range .SI}}-{{.}}-{{break}}NOTREACHED{{else}}EMPTY{{end}}", "-3-", tVal, true}, + {"range []int continue else", "{{range .SI}}-{{.}}-{{continue}}NOTREACHED{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true}, {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true}, {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true}, {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true}, @@ -735,7 +748,7 @@ func add(args ...int) int { return sum } -func echo(arg interface{}) interface{} { +func echo(arg any) any { return arg } @@ -754,7 +767,7 @@ func stringer(s fmt.Stringer) string { return s.String() } -func mapOfThree() interface{} { +func mapOfThree() any { return map[string]int{"three": 3} } @@ -764,6 +777,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, @@ -1454,7 +1468,7 @@ func TestBlock(t *testing.T) { func TestEvalFieldErrors(t *testing.T) { tests := []struct { name, src string - value interface{} + value any want string }{ { @@ -1597,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 }, @@ -1626,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") }, @@ -1634,7 +1648,7 @@ func TestExecutePanicDuringCall(t *testing.T) { tests := []struct { name string input string - data interface{} + data any wantErr string }{ { @@ -1773,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) + } +} diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go index fff833ed29813e21f8826914acf20b1e038ddf7b..dca5ed28db84ff8f03a927d91c8980deb6ff63dd 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 @@ -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. @@ -645,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)) } @@ -736,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)) } @@ -751,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/multi_test.go b/src/text/template/multi_test.go index b543ab5c47c6d3f06c57b20ce5993f57f63df32f..6b81ffe7acbb5806154ad0430c26638c4cd23a2d 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/option.go b/src/text/template/option.go index addce2d890d6d842445dae44c8d140a90416c41a..1035afad72a93f4eaa2d0282c83a43e68bba5e0c 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/src/text/template/parse/lex.go b/src/text/template/parse/lex.go index 6784071b1118d16f752d5b39e8467af013881f7e..40d0411121b7c9d1c9dced7f1282621796e0dd16 100644 --- a/src/text/template/parse/lex.go +++ b/src/text/template/parse/lex.go @@ -62,6 +62,8 @@ const ( // Keywords appear after all the rest. itemKeyword // used only to delimit the keywords itemBlock // block keyword + itemBreak // break keyword + itemContinue // continue keyword itemDot // the cursor, spelled '.' itemDefine // define keyword itemElse // else keyword @@ -76,6 +78,8 @@ const ( var key = map[string]itemType{ ".": itemDot, "block": itemBlock, + "break": itemBreak, + "continue": itemContinue, "define": itemDefine, "else": itemElse, "end": itemEnd, @@ -119,6 +123,8 @@ type lexer struct { parenDepth int // nesting depth of ( ) exprs line int // 1+number of newlines seen startLine int // start line of this item + breakOK bool // break keyword allowed + continueOK bool // continue keyword allowed } // next returns the next rune in the input. @@ -184,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 } @@ -461,7 +467,12 @@ Loop: } switch { case key[word] > 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 6510eed674dd9fecdae833ff8ae710e1522c17cb..df6aabffb20e13c9010faf779a0b190bf8d43ac4 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 177482f9b26059b5183e29b0146985b796dc134d..47268225c8ca1cd4aef1f4cc5e4bd4c9d0543904 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 1a63961c13ecce1c892584698d26e54836a1eed4..b0cbe9dfc8b0c7097097fb5e414cec75977f58ac 100644 --- a/src/text/template/parse/parse.go +++ b/src/text/template/parse/parse.go @@ -24,14 +24,14 @@ 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 vars []string // variables defined at the moment. treeSet map[string]*Tree actionLine int // line of left delim starting action - mode Mode + rangeDepth int } // A mode value is a set of flags (or 0). Modes control parser behavior. @@ -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,12 +218,14 @@ 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{"$"} t.funcs = funcs t.treeSet = treeSet + lex.breakOK = !t.hasFunction("break") + lex.continueOK = !t.hasFunction("continue") } // stopParse terminates parsing. @@ -238,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 @@ -386,6 +388,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 +411,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 +512,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 +561,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 9b1be272e573d98e38c3da477f50660fdeddd3d0..0c4778c7b3b7f865cf6880231118e5868c1f2207 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, ""}, @@ -310,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/text/template/template.go b/src/text/template/template.go index fd74d45e9b1c6df9a0bf45206eba1d040dd0d3b9..776be9cd075d37dc9863c6dccdf551298d9a0a77 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) diff --git a/src/time/embed.go b/src/time/embed.go index 34490c859ddb51af4c18ddddea22da1cace87a76..2a9821baa91959f335b93bd602cd998137cafb1e 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/example_test.go b/src/time/example_test.go index 0afb18aba6b4e5beb9233d54156966cb66cccfca..ec2259b1bae5e2af3454dd94731377cabcc2483b 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 diff --git a/src/time/format.go b/src/time/format.go index f4b4f48142f69387b72babac32ac888ff036145d..5fb9cdc969395a0ef040de8d877cdbece5c60520 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 @@ -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]...) } @@ -479,7 +507,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 +526,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 { @@ -732,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 @@ -1164,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 @@ -1373,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) @@ -1391,16 +1417,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 @@ -1411,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 } @@ -1434,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 @@ -1451,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 } @@ -1462,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. @@ -1481,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 [-+]? @@ -1501,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 ) @@ -1549,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)) } @@ -1557,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/format_test.go b/src/time/format_test.go index 1af41e2dfb315a65e6d154779d3665a4d7fdc268..db95536390040ba692271eef48f0bf5078c57672 100644 --- a/src/time/format_test.go +++ b/src/time/format_test.go @@ -832,3 +832,64 @@ 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) + } + } +} + +// 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) + } + } +} diff --git a/src/time/genzabbrs.go b/src/time/genzabbrs.go index 9fd2f2b7626ea68170e1bd0bf16f32c438d79e22..a8651bfdb87b550b5a91b9ad0d964cb28bced5d8 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/internal_test.go b/src/time/internal_test.go index 87a4208b058e1bd77e395374e1063e484d02d9a8..f0dddb737350045a89317ad5c33a1ca1075c3db7 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 @@ -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 4f4579941469cd978ef39c0b01e0f281e3ed39f3..1ffaabec6749ba81d98d600170a390634b30e49a 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, @@ -139,12 +139,8 @@ func (t *Timer) Reset(d Duration) bool { return resetTimer(&t.r, w) } -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. +// sendTime does a non-blocking send of the current time on c. +func sendTime(c any, seq uintptr) { select { case c.(chan Time) <- Now(): default: @@ -176,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/sleep_test.go b/src/time/sleep_test.go index e0172bf5e0b7361891b6fcbef8c5db35460af763..c48e704eb7b10cce96a6378a7e30a60f36d31816 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 diff --git a/src/time/sys_plan9.go b/src/time/sys_plan9.go index 4dc55e44aa5fb6a92ad1b7b28db4ea27b83d4549..ba37cf54244bee4471d4b04b49d77353df9e871e 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 60fc090dc967ff2785609295cb2e185924c5b9ba..a949a6af225a407ad7ceacbc4925a6f1f7a29034 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/tick.go b/src/time/tick.go index 81d2a43f2838800bf0b1d8cc456882600fc35de3..babf865aeb086bafbe85eecefd290db1ecf1acc6 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 { @@ -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 b5d0a189bc84045782f5d190af1b5b5b15a0afca..f539091869fcaf2f06bde50954608d2a229ee79c 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++ { @@ -123,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) diff --git a/src/time/time.go b/src/time/time.go index 4ecc3d82dcc95895742e6219c95503c994722c0f..8046ff508b6b4fc7a77258e23e241da8d1c40389 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, @@ -1163,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") @@ -1186,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), @@ -1202,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 } @@ -1213,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") } @@ -1230,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) @@ -1416,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 cea5f2d3f5acebcd18214e0167bf6a2a8de9f5d7..6a4049617cb640703835d7b36c82eaae4682f099 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" @@ -767,7 +768,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"}, @@ -886,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. @@ -925,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"`}, @@ -946,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. @@ -1437,6 +1453,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 { @@ -1569,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)) + } + } +} diff --git a/src/time/tzdata/generate_zipdata.go b/src/time/tzdata/generate_zipdata.go index 64b5b1b22c234fcba7056e93ce9c72145a5e5c52..653577cafaf1403934ec72e538727df7515f1beb 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 @@ -31,8 +30,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 @@ -72,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) } diff --git a/src/time/tzdata/zipdata.go b/src/time/tzdata/zipdata.go index 03b59720e27eb9b3add26ed883138bf3e200cb8b..09ca148770f2fb9c0fc640c658b3b5148cbb5758 100644 --- a/src/time/tzdata/zipdata.go +++ b/src/time/tzdata/zipdata.go @@ -11,380 +11,459 @@ // 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 -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" diff --git a/src/time/zoneinfo.go b/src/time/zoneinfo.go index 57aed03fec36cc5300913fc5c12b48febb6b4e3f..7b39f869e644fb62d90345d5741c861fa40dcb75 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 diff --git a/src/time/zoneinfo_ios.go b/src/time/zoneinfo_ios.go index 044691e13058520fdb290497731aa5db98a95b09..7eccabf24924309dfc053dbbb302bd22e34e8997 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 8245614d2e15c158d16a1c805c80409539c5f43a..d0aefb908898f930b5bfe68948fbd03571e502c2 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 4ea029dbde97984e4600633f0ce5cb1a6b54d0c1..23f8b3cdb4af2b81852a24168a09f29a10dcb2ff 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 b75b374c3d535123a0ef21e41af50d368d4ce403..de95295cd3f6bdb24ce224a2cb310d0f0e42bddc 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 diff --git a/src/unicode/example_test.go b/src/unicode/example_test.go index 50c5b18a48e63d8269996a21e810fbface9e6acf..d3a47aca91b7489ff9e27e9ea470dd3d30a356dd 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.IsSpace('a')) + // Output: + // true + // true + // true + // false +} diff --git a/src/unicode/utf8/example_test.go b/src/unicode/utf8/example_test.go index 5cd931d24279ff27eb4a1343dc9a306998f32020..fe434c94767c08d560e224fcdf0fec80f95f39e0 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.go b/src/unicode/utf8/utf8.go index 557e8a7770c7dd9fc70e4e60baf18fd093f19e35..6938c7e6a7742655d8d09bcae767bfd8fb1bf659 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 eaf1b5ffee39e00a464c7ed00cf1b2267dc5ad62..e9be4d2d636eec84bcb8dc9efe55047a83bf2fd3 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(init, %#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++ { 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 8fb49a13e3bf23167b8f1e4ff48adbb8fd413fe8..63cae9e6f0b1ba54dfd55721f855350e8e3a48b3 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 3dad4b2fa27b6a63f22d5eeccb74866df6d8074f..5c0fed26f85027845e4acaaa7dda6699fa670c25 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 818161189bc4b10c7edb4a92d7eb63769d9b0bcc..f3ef5a019d9593e4d70ce876f48f3a74562d245e 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.go b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go index 0d7bac3f7db586fc1284b2874e3f86a2a82374e4..93da7322bc48c29475d9dbc6bcab81c756e380ee 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_amd64.s b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s index 55226b0e6c2c59503bf3c0c36cf1f0c59611cbf5..867c181a14c07411be6f31accc1cd85d5fdc615e 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/chacha20poly1305/chacha20poly1305_generic.go b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go index fe191d395d55510d0fc269c3189fb225284070c9..96b2fd898bbca50a889c8a1c459ce2f69d44f5b7 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 d9d46b96396e73666be6fd8f6883f796d1afa77d..1cebfe946f44407b0515add20bade859384586de 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/curve25519/curve25519.go b/src/vendor/golang.org/x/crypto/curve25519/curve25519.go index 4b9a655d1b56231fdf6f70bbc93dd146277ad3ef..cda3fdd3540dd0363d6e2d1e85a3ad161fb0078f 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 84858480dff5fbd4c4f36503f5813146e68accf9..0000000000000000000000000000000000000000 --- 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 6c533809266b113e69fe99cf85323adf9dc4b5c7..0000000000000000000000000000000000000000 --- 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 c43b13fc83e70c2dc738b44441a434cde4543d11..0000000000000000000000000000000000000000 --- 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 259728af7dad7bae4f74062ae2b1aa13c5c6f8ae..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..e25bca7dc806b3c413494df90f4e35ef75b66e35 --- /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 0000000000000000000000000000000000000000..ca841ad99e3ab72f881e775dd33f9fe07a1791e7 --- /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 0000000000000000000000000000000000000000..44dc8e8caf916316195ab810b746beaf7e165983 --- /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 0000000000000000000000000000000000000000..293f013c94a66c8657217e75f7f9ada0bb3c4427 --- /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 0000000000000000000000000000000000000000..ddb6c9b8f7f2453bfedcf56d7533048b38255d1a --- /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 0000000000000000000000000000000000000000..af459ef51549e743f65998ef295447dc0feac8ff --- /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 0000000000000000000000000000000000000000..5c91e458923e32df3bb0c9599b3f9061127f0dd4 --- /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 0000000000000000000000000000000000000000..234a5b2e5d18abb386567fe10e05517930cc4815 --- /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 0000000000000000000000000000000000000000..7b5b78cbd6d7bf9eee2b764edd19d875b2710720 --- /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 0000000000000000000000000000000000000000..e3685f95cab22f3f8a781bd1ccdc7c09e16cc93a --- /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 0000000000000000000000000000000000000000..1ba22a8b4c9a28c8d64d56db596e8d4595a9e4c7 --- /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/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 9d7a6af09feb47240727065bb9d3683f4e18353e..4aaea810a268238b284b050196681bc67e604b33 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 99% 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 index 2cb03731408c96bfca262d0801b57aee9d2ca85a..1d74f0f88189b152f06e8f581474a70a8b4a8b0c 100644 --- a/src/vendor/golang.org/x/crypto/poly1305/sum_amd64.s +++ b/src/vendor/golang.org/x/crypto/internal/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_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 99% 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 index 3cede539dc40d7c2136a67e03295f2c05dd950aa..58422aad230570fa1b3292a95e1332d50a965042 100644 --- a/src/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s +++ b/src/vendor/golang.org/x/crypto/internal/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.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 bdd882c606def8a9fdd42aeb774327cb23dac70c..aa9e0494c909d8ec768719524c5d46277859f670 100644 --- a/src/vendor/golang.org/x/crypto/poly1305/sum_s390x.s +++ b/src/vendor/golang.org/x/crypto/internal/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" @@ -17,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/golang.org/x/net/dns/dnsmessage/message.go b/src/vendor/golang.org/x/net/dns/dnsmessage/message.go index 1736fc5d12e2f95b7bd0643d1fbf90cd3168e200..8c24430c5ce05260c8af7601b38bb72e957c70ed 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/golang.org/x/net/http/httpproxy/proxy.go b/src/vendor/golang.org/x/net/http/httpproxy/proxy.go index 1415b077912fac3e15daf344ce0f682e4476b7e4..d2c8c87eab918904907781c8cbcfe6aee639c066 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 a1ab2f056794802951624c472abc54ee2a00f645..fe0b84ccd467c40be86070fef89ea75360afceb0 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/lif/address.go b/src/vendor/golang.org/x/net/lif/address.go index afb957fd8e15a38d411bc4b07efdce614d79d5ac..34b6432d6e2002a9fa65948832e42422c5096d16 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 738a94f422409ddabb8b0a0bfdf0c74a204d4b69..f31ca3ad0726c9c315a42c6ba83480d8047cce3c 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 6e81f81f1c2a855e57dad902efbb65bb484e31a9..95c7d25846684174048fbac258ae3ec08019c0b7 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 913a53e1185fc2b34c83009473fa958e9364de80..f1af1306ca3882ce0298b45ee8ec5cf92a83f4b3 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 c896041b7b457828b6cd080e05a8c8e654344ffe..d0b532d9dc95e0d2ccc82f7c825cbed05d7e9642 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 aadab2e14bae4bbc690c440e3457a885caeb5433..8d03b4aa92895e54a330fba79468e8694eae31e0 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/nettest/nettest.go b/src/vendor/golang.org/x/net/nettest/nettest.go index 83ba858e2494f36794384d48a8fd4379a1dc9730..ae5413b23df6ba754c25ca8a459d371a8a6988cf 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/net/route/address.go b/src/vendor/golang.org/x/net/route/address.go index 4f6ad968a247e4de7ea06e991164e3197ba02120..1898ed0fad5decd0d030bc927412a00c014c6dc4 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 d53bb7f9b13108c9c1367da1874897afe5fb46e4..456a8363fec9dd708175a1f09ea9cfcc35520b31 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 fe91be1249c5c3cd4bab18b5e25181e11fe0284a..3599601740c267d459db3f453a04d74e8e045880 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/golang.org/x/net/route/syscall.go b/src/vendor/golang.org/x/net/route/syscall.go index 97166dd3c4c52ee5c37424ad0a7a3d883d5e095e..68d37c9621cba76eb64a299a18e0e6ff585cdd41 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 7a13e4fd90430d6ec08dc0ce114abf8bd4378255..0000000000000000000000000000000000000000 --- 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/golang.org/x/sys/cpu/cpu.go b/src/vendor/golang.org/x/sys/cpu/cpu.go index abbec2d44bfbe30fa5dda7fd33da3cbf9bdc9523..b56886f261631b85368088313b20e8ad4a6e68ff 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_gc_x86.go b/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go index 3298a87e98129347604f98f4f7ce08d7a40c23e1..fa7cdb9bcd5fa46a70730c36e9502d5ab9b7393a 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/golang.org/x/sys/cpu/cpu_x86.go b/src/vendor/golang.org/x/sys/cpu/cpu_x86.go index 54ca4667fb8ea05bc0965e04e631cbe52541ab09..f5aacfc825d5b7044ce6c40f731fab4fb059e3af 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) @@ -88,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 b748ba52f7cf55efe4775a78e8e98bfd8a6fff74..39acab2ff5c2030410a6d45c72dd0372d9723acf 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/golang.org/x/text/unicode/bidi/core.go b/src/vendor/golang.org/x/text/unicode/bidi/core.go index e4c0811016c2acd3f54b0ec93d59f84f8cbba190..fde188a33b014d05f48273eaa45a213773cc958b 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 ff01db5cdc77fe99287db108845ae5403a729678..4130027c7f3640d08b35847bdfb287b58a1e4bcc 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -1,14 +1,15 @@ -# golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e +# golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa ## 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/poly1305 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-20211209124913-491a49abca63 ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts @@ -18,10 +19,10 @@ 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-20211205182925-97ca703d548d ## 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.8-0.20211105212822-18b340fc7af2 ## explicit; go 1.17 golang.org/x/text/secure/bidirule golang.org/x/text/transform diff --git a/test/abi/method_wrapper.go b/test/abi/method_wrapper.go new file mode 100644 index 0000000000000000000000000000000000000000..7aa262fb5254fbb96dca5897686d866b7b52cccf --- /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") + } +} diff --git a/test/alias2.go b/test/alias2.go index d7b5dccb68c2c9bb4b048a4f33643e955ff65e9b..61c7551f79903223e61547a43c9f0f4366b54079 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 9dab120b25b19780e098ba8700d7cbcb1323a450..397be570d99fd5d628b2b11aefa17a411a780d35 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/asmhdr.dir/main.go b/test/asmhdr.dir/main.go new file mode 100644 index 0000000000000000000000000000000000000000..808b5de7bb31577340413d46e3870e57962c1103 --- /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 0000000000000000000000000000000000000000..7e2d8e7abd71c21a3a2baa2cb346f91e85295857 --- /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 0000000000000000000000000000000000000000..772f98e2cc6214f5d603ebc7f88f04410da7220b --- /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 diff --git a/test/chan/perm.go b/test/chan/perm.go index 4c94ab7ffaeefb2e96cd260768e2a4ceb2486983..04046723a4f6fefda18911b4bb9351086177ae0f 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" } diff --git a/test/closure3.dir/main.go b/test/closure3.dir/main.go index 662a2e967bb103a89399c369da9583ad115d0f39..7ef0a47595ea1f266656d27c800fda46c71865f0 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/codegen/arithmetic.go b/test/codegen/arithmetic.go index a27a17f6e112df3752870135b62b5e4440f39f97..00841d52ae27db5c9be6f59fefd9512103c26e8e 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -84,6 +84,38 @@ func NegAddFromConstNeg(a int) int { return c } +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 +} + // -------------------- // // Multiplication // // -------------------- // @@ -135,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 } @@ -202,7 +244,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 @@ -217,7 +259,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" @@ -266,7 +308,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 @@ -428,7 +470,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" @@ -439,7 +481,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" @@ -460,7 +502,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" @@ -483,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 } @@ -498,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 } @@ -526,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 } @@ -540,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 } diff --git a/test/codegen/bitfield.go b/test/codegen/bitfield.go index 0fe6799ec1d68e427e204401da2ebe2a958be05b..8327da6cf8b414f3fbd6daf3d35ff0457704eef0 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,12 +96,27 @@ 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 } +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" +} + +func sbfiz8(x int32) int64 { + return int64(x+1) << 40 // arm64:"SBFIZ\t[$]40, R[0-9]+, [$]24",-"LSL" +} + // 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" } @@ -108,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" } @@ -120,123 +138,189 @@ 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" } -// ubfiz -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 +// merge sbfx and sign-extension into sbfx. +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]+" } -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 +// ubfiz +// merge shifts into ubfiz: (x<>rc && lc>rc +func ubfiz1(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 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 ubfx7(x uint32) uint32 { +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 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 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]+" + return true + } + return false +} + // Check that we don't emit comparisons for constant shifts. //go:nosplit func shift_no_cmp(x int) int { diff --git a/test/codegen/bits.go b/test/codegen/bits.go index 8117a623072934c4a64be3f62060965bd9769f17..e7826b8e658dc89d6ae97516b6f8a6339796f8b1 100644 --- a/test/codegen/bits.go +++ b/test/codegen/bits.go @@ -6,6 +6,8 @@ package codegen +import "math/bits" + /************************************ * 64-bit instructions ************************************/ @@ -330,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 } @@ -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) +} diff --git a/test/codegen/bmi.go b/test/codegen/bmi.go new file mode 100644 index 0000000000000000000000000000000000000000..0c25e0b7968dac186b428dff22c20a955b3b47aa --- /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) +} diff --git a/test/codegen/bool.go b/test/codegen/bool.go index 929b1b49b9bd012c5471e4d21a185fa765b7045d..a32423308e02c6ae36ee3c15d9ba2da1ff6a709e 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 } diff --git a/test/codegen/clobberdead.go b/test/codegen/clobberdead.go index f8d964cba689a80b1924e62a5a9f7c7e9080fd7d..c490790bb63ded8997211ff95a6ffc5a5fedb442 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) } diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go index 17dcd94ae1eff13f0db08f07150a2692fc18a3c1..fd32ea335ce3aa9dc9ebe48c55b7c895ae049f29 100644 --- a/test/codegen/comparisons.go +++ b/test/codegen/comparisons.go @@ -538,3 +538,81 @@ 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" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" + return a == b +} + +func equalVarString1(a string) bool { + b := string("Z") + // amd64:-".*memequal" + // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" + return a[:1] == b +} + +func equalConstString2() bool { + a := string("AA") + b := string("ZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" + return a == b +} + +func equalVarString2(a string) bool { + b := string("ZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" + return a[:2] == b +} + +func equalConstString4() bool { + a := string("AAAA") + b := string("ZZZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" + return a == b +} + +func equalVarString4(a string) bool { + b := string("ZZZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" + return a[:4] == b +} + +func equalConstString8() bool { + a := string("AAAAAAAA") + b := string("ZZZZZZZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" + return a == b +} + +func equalVarString8(a string) bool { + b := string("ZZZZZZZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" + return a[:8] == b +} diff --git a/test/codegen/copy.go b/test/codegen/copy.go index ea8a01f803f7b92998e73d051ba75f11d311a13c..9b3bf75b7a35cd924634e53881b1634d9fd2029e 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[:]) } diff --git a/test/codegen/issue48054.go b/test/codegen/issue48054.go new file mode 100644 index 0000000000000000000000000000000000000000..1f3a041044274fa320f5f66880b04a11ad9e21a8 --- /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 codegen + +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 +} diff --git a/test/codegen/math.go b/test/codegen/math.go index 04cb4e577da6acd6fe0cbd540a6ac93eca0aee7a..ad154e0c40917f2b6a2501e913991c257496dfdf 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" @@ -73,6 +81,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 +105,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 +113,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,19 +126,37 @@ 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) } func fma(x, y, z float64) float64 { + // amd64/v3:-".*x86HasFMA" // amd64:"VFMADD231SD" // arm/6:"FMULAD" // arm64:"FMADDD" // 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.*" diff --git a/test/codegen/mathbits.go b/test/codegen/mathbits.go index 03012eff5d8444a2e71e5f0a49ccc8e850ae004c..859490c363c306a49bb8a760cc392f2f6cbbb4d7 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) } @@ -118,8 +120,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 +133,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 +144,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 +155,7 @@ func OnesCount32(n uint32) int { } func OnesCount16(n uint16) int { + // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT" // amd64:"POPCNTL" // arm64:"VCNT","VUADDLV" // s390x:"POPCNT" @@ -272,7 +278,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 +292,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 +311,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 +352,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 +363,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 +374,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 +385,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 +397,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 @@ -710,6 +724,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/codegen/memcombine.go b/test/codegen/memcombine.go index d74dae07f5b5481379a03524dc1250528999c060..97e1d4bdfb7ad6eff579801f1b23362c9a75e6de 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,15 +433,29 @@ 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` 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.` + // 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` @@ -496,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) } diff --git a/test/codegen/noextend.go b/test/codegen/noextend.go index 424fd2008d25fb84db5170afb00c3504560fa772..d8e2917bf276c75a7e2f6afebe292d86a81cf985 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 diff --git a/test/codegen/rotate.go b/test/codegen/rotate.go index 519cc8326338be8f512d345296a75f0fc980b4d3..204efaeafcd9e35e9342b2a2bc1d0de7b4d50730 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 } @@ -211,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 + } + +} diff --git a/test/codegen/shift.go b/test/codegen/shift.go index 06f6f1247399b8710bc9da0247f275bc277b8abb..b3ed69d9e343015e12541b08656cc515a53326ff 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:"SLLI",-"AND",-"SLTIU" + return v << uint64(33) +} + +func rshConst64Ux64(v uint64) uint64 { + // riscv64:"SRLI",-"AND",-"SLTIU" + return v >> uint64(33) +} + +func rshConst64x64(v int64) int64 { + // riscv64:"SRAI",-"OR",-"SLTIU" + return v >> uint64(33) +} + +func lshConst32x64(v int32) int32 { + // riscv64:"SLLI",-"AND",-"SLTIU" + return v << uint64(29) +} + +func rshConst32Ux64(v uint32) uint32 { + // riscv64:"SRLI",-"AND",-"SLTIU" + return v >> uint64(29) +} + +func rshConst32x64(v int32) int32 { + // riscv64:"SRAI",-"OR",-"SLTIU" + return v >> uint64(29) +} + +func lshConst64x32(v int64) int64 { + // riscv64:"SLLI",-"AND",-"SLTIU" + return v << uint32(33) +} + +func rshConst64Ux32(v uint64) uint64 { + // riscv64:"SRLI",-"AND",-"SLTIU" + return v >> uint32(33) +} + +func rshConst64x32(v int64) int64 { + // riscv64:"SRAI",-"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") } diff --git a/test/complit1.go b/test/complit1.go index 7c2a4e2996d5160a8500a1a3a139f8de156a21c3..8cbcd63ee0d176d93e88b951e758215f776f60d1 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 ad49b347f49dd66439b17fb86e9d2ad3569fc2e3..639b0bfdbdea8e220e33fd87c4c47ae5133c8d9b 100644 --- a/test/ddd1.go +++ b/test/ddd1.go @@ -17,9 +17,9 @@ 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([]int{1}) // ERROR "\[\]int{...}.*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" ) func sum3(int, int, int) int { return 0 } @@ -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/devirt.go b/test/devirt.go index e0149d8229247fccb35a1c40db8070f7b46c733e..d5c815222e448cb01b9620256db9e55f9cc09d0d 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/directive.go b/test/directive.go index 37781c30d54e9d297159992be38ea6e8876a7c66..147e81db2c2377238d0d1b5e842de9f1a22553e0 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 0000000000000000000000000000000000000000..e73e11235debfa23013a30f57b2a8c3293ae9920 --- /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/escape2.go b/test/escape2.go index b9b723d8666862195d9bc090eda8608ba0bf607e..e3e5904cde525bc9b4c2412a1c52b5764e23f837 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] } @@ -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$" } } @@ -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)) } @@ -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 7c8208aa73ca11afb097cd1a0fb9e68922dc8d89..57cc1a01639eb410656caaba1e6bc092c4b59d0e 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] } @@ -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$" } } @@ -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)) } @@ -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/escape5.go b/test/escape5.go index 82be2c38e790e64f8ffc62f86a84d8572e563142..089130dad5c73e2163b7fbd3fa0c509ada81c319 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 } @@ -173,15 +173,14 @@ type U int func (*U) M() {} func (_ *U) N() {} -func _() { +func fbad24305a() { var u U u.M() u.N() } -func fbad24305() { - // BAD u should not be heap allocated - var u U // ERROR "moved to heap: u" +func fbad24305b() { + var u U (*U).M(&u) (*U).N(&u) } diff --git a/test/escape_array.go b/test/escape_array.go index 0d07fd861ffb331dc019b55887a08e4484aa3f30..83062c9436e71d2a1ed9462633b2e8d829a63197 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 9e1db5426ed5d69b3ed20bb907cdc59ae8975b53..aa7c7f516cf96ef38dc7ab1b8617e7cbf5b246e7 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 9152319fe045ba025ea32298fe8dff9c6c604dad..bd6c025476ee8a8ddaff4933b715aa9bf999f2c8 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_goto.go b/test/escape_goto.go index f024a9afe378b256bf51cb0c018b81c23cca19c9..90da5a2151297082b9163b998bae1830c0e36db5 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/escape_param.go b/test/escape_param.go index dc93f689cf9fbd8e17a52097fbe95f244c525ddb..b630bae88fcd9b357c442609d07d3495aee0aec8 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 62e8fede278b7f6022892c1cc39b89650c805f9b..30d1d0c0c1d89dc572873f037b20a90dd32003c0 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 d60414736c38d28c2527db8d21a1dba7be40983b..055b60be4173cfe5a2ef6ba55b147133e9e2a8eb 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 222ef8bc22a064cc8c2e507034028cd82e26a174..a42ae1e8c9b5270e610865554af7477ac95ab6be 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 b34beacccb5992f208b9b2789dd8c8b32c7a6086..cec6674a142374c7c9f6d9c867048f475d866ff2 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/bug062.go b/test/fixedbugs/bug062.go index 24c2dff9339a689b749f5ac79046a53d7880db68..1008f1af9ceca8b1d28c58537eef5519636e9d92 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 2c9d120ed069bf7b4a74984a999123ab641ebc3b..de606da1679d979ca4001f395b2aea552361ca91 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 88210a59b3e520c780f47cd0a1738b31f57684f0..caf3168536e2a8ce3e978a280e51cded7563dcff 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/bug195.go b/test/fixedbugs/bug195.go index 94f61fff7f1cb0a2b030b6ba7273b12e7f7b47b4..6d8578d6cb06049eaf2bdc115f0fae0832110394 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/bug248.dir/bug2.go b/test/fixedbugs/bug248.dir/bug2.go index c0fdecfdb7b1e2a05abfccb67bea8e85ada95b2e..92a7974679eae10349fe8f4f7817cbf39fbf28dd 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/bug267.go b/test/fixedbugs/bug267.go index cf8bf841f8b1da65e102fab82c413a54b868bb1b..b61216a9d5a93fe746d09f93d43b142c8d91e87f 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/bug289.go b/test/fixedbugs/bug289.go index fea6829992f57ac699f7fe08f934dfec767b7a38..7e8346ee0f631bd8bc1383b2f5ffcdf7a1556f3f 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/bug326.go b/test/fixedbugs/bug326.go index dfd8be80050edae795a665adb4d3ea9e0d9c902b..74e06f39d78707388830da49486dfe54f1fca84f 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/bug345.dir/main.go b/test/fixedbugs/bug345.dir/main.go index b77a2fad5fba076e5c0e7ad8f3d87fcaccc057f3..a53d3e8586ed553a73d847d6b8493a95bcb9a513 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/bug389.go b/test/fixedbugs/bug389.go index 167e64e72c731a8f5185724469e71d3c992ac0e5..209be8e6f7ace3b07ec8823396991203b4e7ff5b 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/bug460.dir/b.go b/test/fixedbugs/bug460.dir/b.go index ef646946cf187ab02ef5a993f93e4d8e268a8da5..5d388fc413f783de1aa93fe6c0aacab463b87e63 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/bug514.go b/test/fixedbugs/bug514.go new file mode 100644 index 0000000000000000000000000000000000000000..3fb7f32a3009cf662cae8c4c3b08bea83b978e67 --- /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) + } +} diff --git a/test/fixedbugs/gcc101994.go b/test/fixedbugs/gcc101994.go new file mode 100644 index 0000000000000000000000000000000000000000..6e1e2b8075181217dcc7ed5859e370bbf04695cf --- /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{} +} diff --git a/test/fixedbugs/issue10441.go b/test/fixedbugs/issue10441.go index 9bc4948b15b2881f703389d68e1288f396814608..7cd26d841b66d1573e3e7b2bb097d22f80a8d0be 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 diff --git a/test/fixedbugs/issue10975.go b/test/fixedbugs/issue10975.go index 89ef23c1a86e555cb175daedb55c550b3c874015..a58ccce2db16d43bfeed7540f0b4e0381fca9687 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 @@ -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 { diff --git a/test/fixedbugs/issue11614.go b/test/fixedbugs/issue11614.go index de15f9827ffb28d1c18166c762349d0834de0422..6ea463b7fe92ffbbe0ebfc5d7fe8500caacec2a7 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/fixedbugs/issue12006.go b/test/fixedbugs/issue12006.go index 0a2ef8dad04dbc76b3e09ec265ef8540f8dd2605..e878bc48e241e11befd77c30a2790c07a9d2058a 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 950ef36e206c76e9c83e6d6503462f19ed1f73ae..dc8111198c49d24e87ebe8b1bcd8e473bcea3b3a 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/issue14652.go b/test/fixedbugs/issue14652.go index d53b412668314822423427c98711bb0731041b83..6dd2fbfbf6d6cfc91ad8f20d764af494d41c5dec 100644 --- a/test/fixedbugs/issue14652.go +++ b/test/fixedbugs/issue14652.go @@ -1,4 +1,4 @@ -// errorcheck +// compile -G=3 // 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.*" +// any is now permitted instead of interface{} +var x any diff --git a/test/fixedbugs/issue14999.go b/test/fixedbugs/issue14999.go index b648441fc29779b1f202a20b9056da176f32e59f..a25a50e519a5ea75d90fd263ac11328b3aef09eb 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 } diff --git a/test/fixedbugs/issue16008.go b/test/fixedbugs/issue16008.go index 45457cdb7f5682e34974bcbb553d902f12cb0bf7..b88e2351b7f58d8d0953ba63f0c4a2ff48149895 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 } diff --git a/test/fixedbugs/issue16428.go b/test/fixedbugs/issue16428.go index 5696d186c77d081391294b2fa8ffce2d1a313505..91e1079959a0a3d79521b7fa23c784fd53cf5c98 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 bb34e4ee97a3bfd5db2cad3439ce3ef375c4a257..111fa81e136368c190ee3955267baa8a12829ce1 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/issue19323.go b/test/fixedbugs/issue19323.go index 77cac3ee16a230119167bc51d2806225b87f3d48..5db0a48a345faf5a25247ed1ac46b2fd4f8a50b6 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/issue20250.go b/test/fixedbugs/issue20250.go index 1a513bea56df1f916dfe77d99b0f8f72733a6d28..aed7b25d1bff4b30cb591c70afe96eda623afd0e 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/fixedbugs/issue22076.go b/test/fixedbugs/issue22076.go index 5d628b96bd3a08b574c1a156e72565c5f1115745..b383a674e2f66b02d2bd53ca6306f23f92db45b1 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/issue24651a.go b/test/fixedbugs/issue24651a.go index 6c7bf3090877fcae177cebe06c2462265be27ab5..1bfe8ac1ce8243b77f1b4374d4c92b2776fc980f 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 aa88a6787b96bfd7db8f8231dc7f4dccdce4ce50..2af54fc4b53e52bf92480997bb94ee0e17e5cb48 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/fixedbugs/issue26163.go b/test/fixedbugs/issue26163.go index d141a2797d60f15e5047d756d063fb3102305e75..3f3d77859def812a43f934347592b7013c87836e 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/issue26616.go b/test/fixedbugs/issue26616.go index d5210e87b0f5af9d9183dbd7335f6ece002e6689..edf88d489ecc666b93e5bc8c1fc40d5140b1de71 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/issue27557.go b/test/fixedbugs/issue27557.go index e35ab5a1690fb03dc01faff01b56a1302ad1f5e6..f609b27faa5e12ddc4e03218c36e5916d4c43271 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/issue27595.go b/test/fixedbugs/issue27595.go index 2fc0eb2a58ea17a7987ee0bf478c8097ab735731..86fb6384cdb5b48c99028db2e5fd1b60703b0ca8 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/issue28688.go b/test/fixedbugs/issue28688.go index 8ef0802812c6824a6b0e74f070115a843921738a..0d2000e149872f2d0d5496e64123bbcd0f491d8f 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 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 3e501bb8dcbdc7c853f614fba5b360d50d87c044..230221d5036248af1c1c80415a675cc55f8ee16e 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 80db0e13a84753fda986ebfc40c0bd3bdcda44d4..1489c5a34255fbb01b93700bd1150d90de93920a 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 ba122cc3c8b805b931660d3c39c36db48ddb2e9c..acac71e2ccabd4d85c16b9e38265f93f03af0652 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/fixedbugs/issue30898.go b/test/fixedbugs/issue30898.go index b6376d3f9e7a7fe0ae223db0c869bd9a0dc6c9fa..c7f6f2d3712b3cf507cbc8d1338a4604d99e5c47 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/fixedbugs/issue31573.go b/test/fixedbugs/issue31573.go index 005910e00d16b8b6b8727e42163457cbadefcf9b..eaab5634316916a239b1c71d9ea35dafe42533e6 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$" } } diff --git a/test/fixedbugs/issue32901.dir/main.go b/test/fixedbugs/issue32901.dir/main.go index 28bb8cde28343791ae0215febdc80eef699c31f3..673c6ab3e0f894b886f459f1cd10ba38e52688bd 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/fixedbugs/issue41247.go b/test/fixedbugs/issue41247.go index c5e495ba93396cef9dfe6c99444d7825a08a3329..05889a9ce884739a5e024c86337f6931894592ef 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/issue41500.go b/test/fixedbugs/issue41500.go index 3ec23a0dfe08ba973230b633a1e59058127d6e35..b0ae7cfd59f575326239970c1e48978078134f3a 100644 --- a/test/fixedbugs/issue41500.go +++ b/test/fixedbugs/issue41500.go @@ -13,8 +13,8 @@ type s struct { func f() { var x *s - _ = x == nil || len(x.slice) // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types|cannot convert" - _ = len(x.slice) || x == nil // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types|cannot convert" - _ = x == nil && len(x.slice) // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types|cannot convert" - _ = len(x.slice) && x == nil // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types|cannot convert" + _ = x == nil || len(x.slice) // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types|mismatched types untyped bool and int" + _ = len(x.slice) || x == nil // ERROR "invalid operation: .+ \(operator \|\| not defined on int\)|incompatible types|mismatched types int and untyped bool" + _ = x == nil && len(x.slice) // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types|mismatched types untyped bool and int" + _ = len(x.slice) && x == nil // ERROR "invalid operation: .+ \(operator && not defined on int\)|incompatible types|mismatched types int and untyped bool" } diff --git a/test/fixedbugs/issue4215.go b/test/fixedbugs/issue4215.go index 7201591f3f3c851445c7d3d007739acf60359bfa..b6ece4bf21db0e02255f3603a3eeb5d49c1b1815 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/issue42284.dir/a.go b/test/fixedbugs/issue42284.dir/a.go index ffe9310be35b645165ab7b329f168703b9d9867e..f7fd80bd2070bb5a8e7f4e0074970d2bf16399f3 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 } diff --git a/test/fixedbugs/issue43762.go b/test/fixedbugs/issue43762.go index 9f7682ad6ac50b013a0e513b25bf55e9395a9c9b..bf950c8f524d58266ccdaaefdb1cf4bf21bea7e0 100644 --- a/test/fixedbugs/issue43762.go +++ b/test/fixedbugs/issue43762.go @@ -6,6 +6,6 @@ package p -var _ = true == '\\' // ERROR "invalid operation: true == '\\\\'|cannot convert true" -var _ = true == '\'' // ERROR "invalid operation: true == '\\''|cannot convert true" -var _ = true == '\n' // ERROR "invalid operation: true == '\\n'|cannot convert true" +var _ = true == '\\' // ERROR "invalid operation: (cannot compare true)|(true) == '\\\\' \(mismatched types untyped bool and untyped rune\)" +var _ = true == '\'' // ERROR "invalid operation: (cannot compare true)|(true) == '\\'' \(mismatched types untyped bool and untyped rune\)" +var _ = true == '\n' // ERROR "invalid operation: (cannot compare true)|(true) == '\\n' \(mismatched types untyped bool and untyped rune\)" diff --git a/test/fixedbugs/issue44432.go b/test/fixedbugs/issue44432.go index c5fb67e0d782b6a5acceca35291c8add42705ad5..eec53f30008e3d889aeac58fcd57730b7b1e30eb 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/issue45258.go b/test/fixedbugs/issue45258.go index f4d6fccf17d85d6a6aa8dccae6272dbc782fdfe9..b026c0c8f539c4a62ee7b74f9f7431bf5ff08047 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/issue46556.go b/test/fixedbugs/issue46556.go new file mode 100644 index 0000000000000000000000000000000000000000..b159f61b0c5034309d27288ab9a425834bb6ea1d --- /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 +} diff --git a/test/fixedbugs/issue46749.go b/test/fixedbugs/issue46749.go index 63ed19795e5fc7ccde39515d9a34ac1fed0a63de..faf1f884a6b40cde9d83a606b77a25314091315f 100644 --- a/test/fixedbugs/issue46749.go +++ b/test/fixedbugs/issue46749.go @@ -14,13 +14,13 @@ var iface interface{} var ( _ = "" + b // ERROR "invalid operation.*mismatched types.*untyped string and bool" _ = "" + i // ERROR "invalid operation.*mismatched types.*untyped string and int" - _ = "" + nil // ERROR "invalid operation.*mismatched types.*untyped string and nil" + _ = "" + nil // ERROR "invalid operation.*mismatched types.*untyped string and nil|(untyped nil)" ) var ( _ = s + false // ERROR "invalid operation.*mismatched types.*string and untyped bool" _ = s + 1 // ERROR "invalid operation.*mismatched types.*string and untyped int" - _ = s + nil // ERROR "invalid operation.*mismatched types.*string and nil" + _ = s + nil // ERROR "invalid operation.*mismatched types.*string and nil|(untyped nil)" ) var ( @@ -31,7 +31,7 @@ var ( var ( _ = b + 1 // ERROR "invalid operation.*mismatched types.*bool and untyped int" _ = i + false // ERROR "invalid operation.*mismatched types.*int and untyped bool" - _ = iface + 1 // ERROR "invalid operation.*mismatched types.*interface {} and int" - _ = iface + 1.0 // ERROR "invalid operation.*mismatched types.*interface {} and float64" - _ = iface + false // ERROR "invalid operation.*mismatched types.*interface {} and bool" + _ = iface + 1 // ERROR "invalid operation.*mismatched types.*interface *{} and int" + _ = iface + 1.0 // ERROR "invalid operation.*mismatched types.*interface *{} and float64" + _ = iface + false // ERROR "invalid operation.*mismatched types.*interface *{} and bool" ) diff --git a/test/fixedbugs/issue46903.go b/test/fixedbugs/issue46903.go new file mode 100644 index 0000000000000000000000000000000000000000..3237a583d547361117b1b82aa6df2ca0a66a5508 --- /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/fixedbugs/issue46938.go b/test/fixedbugs/issue46938.go new file mode 100644 index 0000000000000000000000000000000000000000..87532d47694edc4a275d923d00c847227de929b4 --- /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] +} diff --git a/test/fixedbugs/issue46957.go b/test/fixedbugs/issue46957.go index f3ed3c3def0c9b2bbb5ced20d84fe4e47f1fb8e0..6c1c0fe0c28981f3dbb19d7859181c55d3cdc9bc 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/issue47068.dir/a.go b/test/fixedbugs/issue47068.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..f7b780d459d274140e13bffda0ec26a8a3a057b1 --- /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 0000000000000000000000000000000000000000..d341a4a395005cb9b5411ece09004ee9c2571118 --- /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 0000000000000000000000000000000000000000..16ef5b780b9f8d4648e04aaf09958d908f3f2946 --- /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/src/internal/cpu/cpu_386.go b/test/fixedbugs/issue47068.go similarity index 54% rename from src/internal/cpu/cpu_386.go rename to test/fixedbugs/issue47068.go index 561c81f8083518a397202083d53cf4f797ce8b9c..af6f1341729458e04aba9a8a7110ec999540bc2a 100644 --- a/src/internal/cpu/cpu_386.go +++ b/test/fixedbugs/issue47068.go @@ -1,7 +1,7 @@ -// Copyright 2018 The Go Authors. All rights reserved. +// 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 cpu - -const GOARCH = "386" +package ignored diff --git a/test/fixedbugs/issue47131.dir/a.go b/test/fixedbugs/issue47131.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..6e798d1d0c8e2dd7370416750e2fc5764346a9e9 --- /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 0000000000000000000000000000000000000000..c658127ca9d53c2495f12690437e095401f9a4c2 --- /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/src/internal/cpu/cpu_amd64.go b/test/fixedbugs/issue47131.go similarity index 54% rename from src/internal/cpu/cpu_amd64.go rename to test/fixedbugs/issue47131.go index 9b0015362d53fba083efefb8a8f0c3b7e42a4a9c..b83fbd7af16a576c16e0fc73b84f1ca0f618b756 100644 --- a/src/internal/cpu/cpu_amd64.go +++ b/test/fixedbugs/issue47131.go @@ -1,7 +1,7 @@ -// Copyright 2018 The Go Authors. All rights reserved. +// 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 cpu - -const GOARCH = "amd64" +package ignored diff --git a/test/fixedbugs/issue47201.dir/b.go b/test/fixedbugs/issue47201.dir/b.go index 5fd0635af2e11dd86e97bc0a480c0acfccc72490..ae3ff3f2b8143d280da4958a17a5a21852ffb978 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/issue47227.go b/test/fixedbugs/issue47227.go new file mode 100644 index 0000000000000000000000000000000000000000..a14efc9a689410ccfe66ac2c94ee120524640215 --- /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") + } +} diff --git a/test/fixedbugs/issue47712.go b/test/fixedbugs/issue47712.go new file mode 100644 index 0000000000000000000000000000000000000000..81a2681592e92cc1dfee1ef94018624b9040e5e0 --- /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() + }() + } +} diff --git a/test/fixedbugs/issue47771.go b/test/fixedbugs/issue47771.go new file mode 100644 index 0000000000000000000000000000000000000000..a434bffe4b1ad101bef7b6695872614371f35863 --- /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) + } +} diff --git a/test/fixedbugs/issue47928.go b/test/fixedbugs/issue47928.go new file mode 100644 index 0000000000000000000000000000000000000000..3bc291dd3f1b4ea8746b7e52155467b18eb5a562 --- /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() {} diff --git a/test/fixedbugs/issue48026.go b/test/fixedbugs/issue48026.go new file mode 100644 index 0000000000000000000000000000000000000000..a693d33b45f00f422971f371c9b79f53c2a1675f --- /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< 0 { goto L1 } else { diff --git a/test/fixedbugs/issue8606b.go b/test/fixedbugs/issue8606b.go index 448ea566f0bea0ad66b7fc387fa1eb4589380008..41b9a3d00eab60a776f89a867372a1337f052ba8 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)) diff --git a/test/fixedbugs/issue8761.go b/test/fixedbugs/issue8761.go index 7f458f7f03378d7343dc1216f14a43d3a00dca3a..e5130e1ff5ca92edad3f7d950093be9ced6d00b0 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/fixedbugs/issue9083.go b/test/fixedbugs/issue9083.go index f5c5296a2bf7c60dd05f8cdc6ebeb302e2c72195..ea53e7a69ae0b2c7c77a0e6cbb2942236bf3f61e 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/fixedbugs/issue9521.go b/test/fixedbugs/issue9521.go index 1ad40bdfda1ff5dca519efca6489fd375b9fcc42..a029ec145e9637dfa494fb82d8b3626d1ed3412c 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/float_lit3.go b/test/float_lit3.go index 850d02c9c7f97366ae3d5db35ec9e78b5417290e..37a1289fb9dd21a22e1b10961e8e94d815e9cbb4 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/inline.go b/test/inline.go index 472a941dca3a66a47b0b2a6679bb921bc1cbc8b3..2780e10b196c3c904df2bbb26d9cbd1aa1363eb4 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 @@ -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" @@ -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() } @@ -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: @@ -161,14 +160,28 @@ 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" 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" } func small1() { // ERROR "can inline small1" @@ -217,8 +230,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() { @@ -232,12 +244,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" diff --git a/test/inline_big.go b/test/inline_big.go index 68e1101d3b0de921e9128f4d2b519e58748ce2ba..83672753f78a171bd224fa71705eb3e7dc4c2118 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 } diff --git a/test/inline_endian.go b/test/inline_endian.go new file mode 100644 index 0000000000000000000000000000000000000000..e00e06a75ee9598283f50ff15f2b11cf85de032a --- /dev/null +++ b/test/inline_endian.go @@ -0,0 +1,23 @@ +// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1 + +//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 +// 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" +} diff --git a/test/inline_variadic.go b/test/inline_variadic.go index 687048a1922d55ca42ac1c334bd1380978e4d499..49483d77f79934b9f4011da0705daba3faeb2a7b 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 } diff --git a/test/interface/explicit.go b/test/interface/explicit.go index 1b7af6712b661df40e890e2292fa5a0519248212..e18d6843ec66ec3efb92893714d46330bf86d322 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 @@ -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/interface/pointer.go b/test/interface/pointer.go index c21e4da390ab0fd92df3288c2d2d64fe994eb649..a71b3f4bf89ddd2f048ec4913ea1cb91e0faebcb 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" } diff --git a/test/ken/slicearray.go b/test/ken/slicearray.go index 6cf676c588b2558b185a5bf6c70d3d1e8ec595c7..a431983d156b1852b2c83193c29d033bd95250eb 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] diff --git a/test/linkname.dir/linkname1.go b/test/linkname.dir/linkname1.go index c61a0d7d95ce09259d389d7d1220bd96476dc73b..7d51b94802841f23e34e989dff025f538d15e124 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 diff --git a/test/linkname2.go b/test/linkname2.go index 43e66a584958bbb03fd2177b01b20f87c62c6871..5eb250f9c4bcb787eda256e4aa2d9a35518bb9aa 100644 --- a/test/linkname2.go +++ b/test/linkname2.go @@ -16,15 +16,6 @@ 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 "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 -//go:linkname t notvarfunc -//go:linkname x duplicate diff --git a/test/linkname3.go b/test/linkname3.go new file mode 100644 index 0000000000000000000000000000000000000000..df110cd064d151e4e7a2eee26fa842adda28436c --- /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/live.go b/test/live.go index bc7b3849cf3b571994f120f9ae27cc6b1fc084fa..6130f7f06944d79535d3468bb01d0069e5b84fb0 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.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 @@ -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 } @@ -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() } @@ -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()) @@ -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 2b0278ecb83c903531e7076d865e1d6d6fec63b2..aac9a7766c02fe61189fa6ae8ad8240dc4e88330 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.regabidefer,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 @@ -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()) @@ -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. diff --git a/test/maymorestack.go b/test/maymorestack.go new file mode 100644 index 0000000000000000000000000000000000000000..ec84ad44bc42c85604fbac35db51a0d626f971b5 --- /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) +} diff --git a/test/recover4.go b/test/recover4.go index 67ed970ecb2f00f215ad2e76aff8c517c353ce8b..7cab15a5a814dc8910708525a37933e8b33f82bf 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) } } diff --git a/test/reflectmethod7.go b/test/reflectmethod7.go index 42429978b45a691297fd1eba287b6b52dc774599..688238c5119fa68d97cc3d1906033ebf5c82f18d 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") } diff --git a/test/reflectmethod8.go b/test/reflectmethod8.go new file mode 100644 index 0000000000000000000000000000000000000000..482163bae6f4419811b374ec7eaea0442eef8980 --- /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) +} diff --git a/test/retjmp.dir/a.s b/test/retjmp.dir/a.s index c67a06638f90be9d182770f2738326d7c02c835c..101b3428fc2d6c794b2119fffe709e58a74c910b 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 cb4bd018bf8c021090187d2e9b58fe3de954f4f1..0bed5a61b7ac623be289e969c8f17f7b7b9b44c5 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") diff --git a/test/run.go b/test/run.go index d7f5d02391b67dbf2641af524889520c705761b3..37be958959f97a355aeba804dd8cc0fd99131e1d 100644 --- a/test/run.go +++ b/test/run.go @@ -9,6 +9,7 @@ package main import ( "bytes" + "encoding/json" "errors" "flag" "fmt" @@ -31,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.") @@ -42,11 +47,55 @@ 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, "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.") shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.") ) +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(","+env.GOEXPERIMENT+",", ",unified,") + + // 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 +}() + // 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 @@ -56,12 +105,13 @@ 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? - 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 @@ -82,11 +132,13 @@ const maxTests = 5000 func main() { flag.Parse() - 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))) + 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) } findExecCmd() @@ -113,11 +165,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 +177,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)...) } } } @@ -142,8 +194,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 @@ -151,7 +210,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,30 +330,78 @@ 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 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 } -// startTest -func startTest(dir, gofile string) *test { - t := &test{ - dir: dir, - gofile: gofile, - donec: make(chan bool, 1), +// initExpectFail initializes t.expectFail based on the build+test +// configuration. +func (t *test) initExpectFail(hasGFlag bool) { + if *force { + return } - if toRun == nil { - toRun = make(chan *test, maxTests) - go runTests() + + 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 } - select { - case toRun <- t: - default: - panic("toRun buffer size (maxTests) is too small") + + 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) } - return t + + 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)) + 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 tests } // runTests runs tests in parallel, but respecting the order they @@ -427,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 @@ -480,12 +588,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 != CompilerDefaultGLevel { + 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 == CompilerDefaultGLevel } var errTimeout = errors.New("command exceeded time limit") @@ -510,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) } @@ -541,7 +652,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:] @@ -569,6 +684,8 @@ func (t *test) run() { return } + goexp := env.GOEXPERIMENT + // collect flags for len(args) > 0 && strings.HasPrefix(args[0], "-") { switch args[0] { @@ -595,7 +712,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]) @@ -616,6 +737,60 @@ func (t *test) run() { } } + type Tool int + + const ( + _ Tool = iota + AsmCheck + Build + Run + Compile + ) + + // 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 { + hasGFlag := false + for _, flag := range flags { + if strings.Contains(flag, "-G") { + hasGFlag = true + } + } + + // 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()) + } + return false + } + + t.initExpectFail(hasGFlag) + + switch tool { + case Build, Run: + // ok; handled in goGcflags + + case Compile: + if !hasGFlag { + flags = append(flags, fmt.Sprintf("-G=%v", t.glevel)) + } + + default: + 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 true + } + t.makeTempDir() if !*keep { defer os.RemoveAll(t.tempDir) @@ -692,6 +867,10 @@ func (t *test) run() { t.err = fmt.Errorf("unimplemented action %q", action) case "asmcheck": + if !validForGLevel(AsmCheck) { + return + } + // Compile Go file and match the generated assembly // against a set of regexps in comments. ops := t.wantedAsmOpcodes(long) @@ -746,6 +925,10 @@ func (t *test) run() { return case "errorcheck": + if !validForGLevel(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 +957,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 !validForGLevel(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 !validForGLevel(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 +986,10 @@ func (t *test) run() { } case "errorcheckdir", "errorcheckandrundir": + if !validForGLevel(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 +1035,10 @@ func (t *test) run() { fallthrough case "rundir": + if !validForGLevel(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 +1097,10 @@ func (t *test) run() { } case "runindir": + if !validForGLevel(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 +1126,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 +1140,21 @@ func (t *test) run() { t.checkExpectedOutput(out) case "build": + if !validForGLevel(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 !validForGLevel(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 +1234,14 @@ func (t *test) run() { } case "buildrun": + if !validForGLevel(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 +1263,17 @@ func (t *test) run() { t.checkExpectedOutput(out) case "run": + if !validForGLevel(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 && 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 @@ -1136,7 +1295,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 +1310,10 @@ func (t *test) run() { t.checkExpectedOutput(out) case "runoutput": + if !validForGLevel(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 +1321,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 +1336,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 +1349,14 @@ func (t *test) run() { t.checkExpectedOutput(out) case "errorcheckoutput": + if !validForGLevel(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") } @@ -1348,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 @@ -1394,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{`\`, `*`, `+`, `?`, `[`, `]`, `(`, `)`} { @@ -1585,7 +1747,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"}, @@ -1594,6 +1756,7 @@ var ( "ppc64le": {"GOPPC64", "power8", "power9"}, "s390x": {}, "wasm": {}, + "riscv64": {}, } ) @@ -1941,66 +2104,157 @@ 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. + // 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{ - "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 - "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) - - "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/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/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/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/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/issue19012.go": true, // multiple errors on same line - "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/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/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/issue4452.go": true, // types2 reports (correct) extra errors - "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/issue46749.go": true, // types2 reports can not convert error instead of type mismatched +var types2Failures = setOf( + "import1.go", // types2 reports extra errors + "import6.go", // issue #43109 + "initializerr.go", // types2 reports extra errors + "notinheap.go", // types2 doesn't report errors about conversions that are invalid due to //go:notinheap + "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) + "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/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/issue17038.go", // types2 doesn't report a follow-on error (pref: types2) + "fixedbugs/issue18331.go", // missing error about misuse of //go:noescape (irgen needs code from noder) + "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) + "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/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/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) +) + +var g3Failures = setOf( + "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 + "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" + "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 + "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 { + 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 +// 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/shift1.go b/test/shift1.go index d6a6c38839f56076a9445e160192570d8bb997fb..0dae49a74dc590a0a40c9007688be4d20908b2c6 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<><-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]() +} diff --git a/test/typeparam/issue48198.go b/test/typeparam/issue48198.go new file mode 100644 index 0000000000000000000000000000000000000000..1d7e44e0c46ad80465beeb2775c6f071fe3e3f24 --- /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]{} +) diff --git a/test/typeparam/issue48225.go b/test/typeparam/issue48225.go new file mode 100644 index 0000000000000000000000000000000000000000..887ffd8a8481140a0feb33be788e0925583b1ce1 --- /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) + } +} diff --git a/test/typeparam/issue48253.go b/test/typeparam/issue48253.go new file mode 100644 index 0000000000000000000000000000000000000000..7bd0234e57873712a943dbdfbfd5a3398866f165 --- /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() +} diff --git a/test/typeparam/issue48276a.go b/test/typeparam/issue48276a.go new file mode 100644 index 0000000000000000000000000000000000000000..060ac3eb7f95e19a34abaa524e1da3aafc7ff669 --- /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 0000000000000000000000000000000000000000..7e8a8a9a2e445c0de24017dcc417ebfab6fa1d69 --- /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 0000000000000000000000000000000000000000..67c3e3d9f5c25b97e2fae54529c0b1f90beb8ba0 --- /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 +} diff --git a/test/typeparam/issue48280.dir/a.go b/test/typeparam/issue48280.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..f66fd30e34ee432300fb932c332fc401818a65e6 --- /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 any] 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 0000000000000000000000000000000000000000..b9981c6f61a748c65b3e200ce66c1cc45a3862dc --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue48306.dir/a.go b/test/typeparam/issue48306.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..fdfd86cb6d4a5dc6390e936ccee80aa92531c6ad --- /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 any] interface { + F() T +} diff --git a/test/typeparam/issue48306.dir/main.go b/test/typeparam/issue48306.dir/main.go new file mode 100644 index 0000000000000000000000000000000000000000..5d602fe07ca7b9b03751b7d4bed83da1b4544213 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue48317.go b/test/typeparam/issue48317.go new file mode 100644 index 0000000000000000000000000000000000000000..c8f088dc7afb827cac1617b4352a9eed0ec646c4 --- /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]() +} diff --git a/test/typeparam/issue48318.go b/test/typeparam/issue48318.go new file mode 100644 index 0000000000000000000000000000000000000000..ae53a28dc5050a7bcf2a122c6197c32097756db9 --- /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)) + } +} diff --git a/test/typeparam/issue48337a.dir/a.go b/test/typeparam/issue48337a.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..6f1b128589bde634cce287f25694c9f3fe9fe003 --- /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 0000000000000000000000000000000000000000..16f71153f3d0f6a237aa466dc4e19b39fa124994 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 0000000000000000000000000000000000000000..fa8d3eedcbabae2cd05ed962050ce17cc5350425 --- /dev/null +++ b/test/typeparam/issue48337a.out @@ -0,0 +1 @@ +this file does import sync diff --git a/test/typeparam/issue48337b.dir/a.go b/test/typeparam/issue48337b.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..a3c2e88a2f2ba317f4ed91e77d87efbe226890b9 --- /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 0000000000000000000000000000000000000000..0b2814cbc0c6bd48105be6a43f14ca5ad40aec39 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue48344.go b/test/typeparam/issue48344.go new file mode 100644 index 0000000000000000000000000000000000000000..7ea539cfccbbff4717d033b3c3ec7edbc863216d --- /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]() +} diff --git a/test/typeparam/issue48424.go b/test/typeparam/issue48424.go new file mode 100644 index 0000000000000000000000000000000000000000..3253e6457b6c6057b08efab22d848cccb326d343 --- /dev/null +++ b/test/typeparam/issue48424.go @@ -0,0 +1,54 @@ +// 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. + +// 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{} +) diff --git a/test/typeparam/issue48453.go b/test/typeparam/issue48453.go new file mode 100644 index 0000000000000000000000000000000000000000..0f751d38edf99895c5b296d7a8f27f16fdd2cacc --- /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) +} diff --git a/test/typeparam/issue48454.dir/a.go b/test/typeparam/issue48454.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..9613916a4c8bb8df1cee6fff49151c682c08d925 --- /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 0000000000000000000000000000000000000000..2b59b714b8eefb55b9c4450e0bb76dc69c600932 --- /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 0000000000000000000000000000000000000000..becb5f30247bfaed89b39057cebd0c317c04ae77 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue48462.dir/a.go b/test/typeparam/issue48462.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..26c704dbe4617dd30d9166ed5639088f616590bb --- /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 0000000000000000000000000000000000000000..8054ddd3277723eb2a83756fa089c3c956a9d0dc --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue48537.go b/test/typeparam/issue48537.go new file mode 100644 index 0000000000000000000000000000000000000000..a2dc5cf082a1c5940f0e2e91b30ba473c190af1f --- /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", + } +} diff --git a/test/typeparam/issue48538.go b/test/typeparam/issue48538.go new file mode 100644 index 0000000000000000000000000000000000000000..fed9b5e9a6a3b559fb03dcda142049866fde79be --- /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", + } +} diff --git a/test/typeparam/issue48598.go b/test/typeparam/issue48598.go new file mode 100644 index 0000000000000000000000000000000000000000..ea360f213588287c7a6c60282115031e75f60f73 --- /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]() +} diff --git a/test/typeparam/issue48602.go b/test/typeparam/issue48602.go new file mode 100644 index 0000000000000000000000000000000000000000..53ce20e6eae41ff76b6914926c814d9b31f8495f --- /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]() +} diff --git a/test/typeparam/issue48604.go b/test/typeparam/issue48604.go new file mode 100644 index 0000000000000000000000000000000000000000..1babd3f864b899331c175960a1cc43ba6a21088c --- /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 diff --git a/test/typeparam/issue48609.go b/test/typeparam/issue48609.go new file mode 100644 index 0000000000000000000000000000000000000000..6cf6908291256a2a18162c8bc6f6f8aab465cebb --- /dev/null +++ b/test/typeparam/issue48609.go @@ -0,0 +1,16 @@ +// 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 ~chan E, E any](e E) T { + ch := make(T) + go func() { + defer close(ch) + ch <- e + }() + return ch +} diff --git a/test/typeparam/issue48617.go b/test/typeparam/issue48617.go new file mode 100644 index 0000000000000000000000000000000000000000..4b00570ba6de06aee63bbac379b1a568d7144051 --- /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]() +} diff --git a/test/typeparam/issue48645a.go b/test/typeparam/issue48645a.go new file mode 100644 index 0000000000000000000000000000000000000000..8d5aac94c6254a8b0173f2a712f5ff8f149eb049 --- /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 0000000000000000000000000000000000000000..5093d0f0ffce708e205e916a3737f7496502177b --- /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 0000000000000000000000000000000000000000..0f3a7f230a0755c9a9e2d0fa0692124184483c38 --- /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) + }) +} diff --git a/test/typeparam/issue48711.go b/test/typeparam/issue48711.go new file mode 100644 index 0000000000000000000000000000000000000000..d09a72e576d3fd30a762a9e7409fefbaf95db8ac --- /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) +} diff --git a/test/typeparam/issue48716.dir/a.go b/test/typeparam/issue48716.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..63e599d9a18696840d7c9ca9db716470e0e59f07 --- /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 0000000000000000000000000000000000000000..adde0f5afe8410becd427a21f5583b4ab37e8232 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue48838.go b/test/typeparam/issue48838.go new file mode 100644 index 0000000000000000000000000000000000000000..ef2150d6a249c622a0ccbce3ebf99bbf44cad724 --- /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) {} diff --git a/test/typeparam/issue48962.go b/test/typeparam/issue48962.go new file mode 100644 index 0000000000000000000000000000000000000000..de9a23cdd2185ea8590f4d20c2cd8ef250f850e4 --- /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] +} diff --git a/test/typeparam/issue49027.dir/a.go b/test/typeparam/issue49027.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..da88297965ec213caba577b318242dcec217fc6f --- /dev/null +++ b/test/typeparam/issue49027.dir/a.go @@ -0,0 +1,55 @@ +// Copyright 2021 The Go Authors. 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 +} + +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 new file mode 100644 index 0000000000000000000000000000000000000000..aa20a2fdfbcec6f2b91ec4e6b90d19e79aa9eb7a --- /dev/null +++ b/test/typeparam/issue49027.dir/main.go @@ -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 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)) + } + 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)) + } +} diff --git a/test/typeparam/issue49027.go b/test/typeparam/issue49027.go new file mode 100644 index 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue49049.go b/test/typeparam/issue49049.go new file mode 100644 index 0000000000000000000000000000000000000000..f4fdd05d85ff6f594e079c02aeabf4927a6176c0 --- /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]() +} diff --git a/test/typeparam/issue49241.dir/a.go b/test/typeparam/issue49241.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..34c99657d49b9594393b02ba792de821102e8418 --- /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 0000000000000000000000000000000000000000..45c1afbaf1570f9e64a6986358d4529d1801ed7f --- /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 0000000000000000000000000000000000000000..ea3bab2954480f2a652c4c76acd3489c85b55158 --- /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 0000000000000000000000000000000000000000..7c8a8b1acd0a996ddbd360b54c3e0ec52d9d70b7 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue49246.dir/a.go b/test/typeparam/issue49246.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..97459ee7481de590169e3453c77399aa1f4807b1 --- /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 0000000000000000000000000000000000000000..5141b72fd4ddceb5d2ec320481bec4e7f95546fb --- /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 0000000000000000000000000000000000000000..87b4ff46c1ea4e6750058822d454a40cccb2cf1c --- /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 diff --git a/test/typeparam/issue49295.go b/test/typeparam/issue49295.go new file mode 100644 index 0000000000000000000000000000000000000000..435b44d10c1fb23bfe7dbd65750d593a2ac28b3f --- /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 +} diff --git a/test/typeparam/issue49309.go b/test/typeparam/issue49309.go new file mode 100644 index 0000000000000000000000000000000000000000..36da86a9c3885a3cf9be5c6e865867b07810ab0c --- /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) +} diff --git a/test/typeparam/issue49421.go b/test/typeparam/issue49421.go new file mode 100644 index 0000000000000000000000000000000000000000..526e038bec258c71943bdf6c0ec2045b6e7a8871 --- /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) +} diff --git a/test/typeparam/issue49432.go b/test/typeparam/issue49432.go new file mode 100644 index 0000000000000000000000000000000000000000..21d6ec4b7022a7fdcee9971b1f5b520d1f01e077 --- /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() +} diff --git a/test/typeparam/issue49497.dir/a.go b/test/typeparam/issue49497.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..86062d446ffff60a62f53625b1b287919a2638bb --- /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 0000000000000000000000000000000000000000..3725e5591e3ba88a6060713b6051c96861bd21fc --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue49516.go b/test/typeparam/issue49516.go new file mode 100644 index 0000000000000000000000000000000000000000..d6fab0246374a9e9a0d311def9670cad0c341814 --- /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) +} diff --git a/test/typeparam/issue49524.dir/a.go b/test/typeparam/issue49524.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..f40075e953ee6ae0b15f7f2492169ec43c1996b8 --- /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 0000000000000000000000000000000000000000..ef00c8a81c982b211a952250a6b614c17365eb41 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue49538.go b/test/typeparam/issue49538.go new file mode 100644 index 0000000000000000000000000000000000000000..ac20a5423f4822e502b4c263842cf9bb859352b5 --- /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]{}) +} diff --git a/test/typeparam/issue49547.go b/test/typeparam/issue49547.go new file mode 100644 index 0000000000000000000000000000000000000000..99c124d7abe6cd4520b3b6af50f371e89c4d3f25 --- /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/issue49611.go b/test/typeparam/issue49611.go new file mode 100644 index 0000000000000000000000000000000000000000..96c651e2b5db6de6e7cfc7990b27e24be28f5469 --- /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 () +} diff --git a/test/typeparam/issue49659.dir/a.go b/test/typeparam/issue49659.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..718bc0c5fce5d7dbd7c305e082a9280b0a780338 --- /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 0000000000000000000000000000000000000000..1f3715376942429720524f6af49cc3bdcdc0291c --- /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 0000000000000000000000000000000000000000..87b4ff46c1ea4e6750058822d454a40cccb2cf1c --- /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 0000000000000000000000000000000000000000..a9a14af77deb1e3870aef8897ab4d21112a15836 --- /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() +} diff --git a/test/typeparam/issue49667.dir/a.go b/test/typeparam/issue49667.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..3b1889f699272da8af5b7cd06a29fe589f7e5cef --- /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 0000000000000000000000000000000000000000..e7f781e4af25c8b20b7d72a5f61540f632bd5818 --- /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 0000000000000000000000000000000000000000..fccefe023f68aeffa2fd907007d8aef716fc6465 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue49875.go b/test/typeparam/issue49875.go new file mode 100644 index 0000000000000000000000000000000000000000..aece7deab1d65435c1817e96f3a0a9cd170d26a7 --- /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...) +} diff --git a/test/typeparam/issue49893.dir/a.go b/test/typeparam/issue49893.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..bc810cd3dd5300752cd3b36322aecc983b68c245 --- /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 0000000000000000000000000000000000000000..b36f6bddf0304dc000bb4d63299ed02d70b09c8d --- /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 0000000000000000000000000000000000000000..8b5b3bdad784638ee9222e94a1b5bfeaf8ccfcc2 --- /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 0000000000000000000000000000000000000000..87b4ff46c1ea4e6750058822d454a40cccb2cf1c --- /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 diff --git a/test/typeparam/issue50002.go b/test/typeparam/issue50002.go new file mode 100644 index 0000000000000000000000000000000000000000..670fc2eae3a1b03aabf96382efc4f97c68dd1ddd --- /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) +} diff --git a/test/typeparam/issue50109.go b/test/typeparam/issue50109.go new file mode 100644 index 0000000000000000000000000000000000000000..a6913df84357100b2562cd4851b73ccc3d04d22a --- /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 0000000000000000000000000000000000000000..7d6ecc0c6d2bf0c54deda95d5c7652cce6ff4b40 --- /dev/null +++ b/test/typeparam/issue50109.out @@ -0,0 +1 @@ +MySuperStruct \ No newline at end of file diff --git a/test/typeparam/issue50121.dir/a.go b/test/typeparam/issue50121.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..9918fa38a6a6ef2666eb5184dda506e7904c59e1 --- /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 0000000000000000000000000000000000000000..71eb44ff62a769f12e682097b85aabab1c7de881 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/issue50147.go b/test/typeparam/issue50147.go new file mode 100644 index 0000000000000000000000000000000000000000..2bdce6c504037f54f9a140e4f0dd855b56f8c9dc --- /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 +} diff --git a/test/typeparam/list.go b/test/typeparam/list.go index 579078f02f7b1397cd5de521def0c82f086d6dae..adfe72f1de1ea2cd899766e316f6be3ab7456a1c 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. @@ -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 385193d87657c7ab1172e2bd5170ed3461f377ba..e7f346c78e13c7addd209c42fb50904931f5925b 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,8 +594,15 @@ func TestTransform() { checkList(l2, []interface{}{"1", "2"}) } - func main() { TestList() + TestExtending() + TestRemove() + TestIssue4103() + TestIssue6349() + TestMove() + TestZeroList() + TestInsertBeforeUnknownMark() + TestInsertAfterUnknownMark() + TestTransform() } - diff --git a/test/typeparam/listimp.dir/a.go b/test/typeparam/listimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..bf1641af9c384d8a0baeb4ff41fe87501aa4bf95 --- /dev/null +++ b/test/typeparam/listimp.dir/a.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 a + +type Ordered interface { + ~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 { + ~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. +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 +} diff --git a/test/typeparam/listimp.dir/main.go b/test/typeparam/listimp.dir/main.go new file mode 100644 index 0000000000000000000000000000000000000000..985ff59a18994bbb9c5c383a763d9982888be160 --- /dev/null +++ b/test/typeparam/listimp.dir/main.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. + +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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/listimp2.dir/a.go b/test/typeparam/listimp2.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..3a7dfc3999a0db856c877a5cc2c4f21c899e801c --- /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 0000000000000000000000000000000000000000..226e1a9a571bde4b654e44bd9e52ce86bdc019c5 --- /dev/null +++ b/test/typeparam/listimp2.dir/main.go @@ -0,0 +1,315 @@ +// Copyright 2021 The Go Authors. 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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/lockable.go b/test/typeparam/lockable.go index d53817521f30c8529fe9c3e4876eb7a5bddad553..9b20d87bb77e53cbf345876ca23471e970271f6b 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 { - T +type Lockable[T any] struct { + x 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 + return l.x } -// 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 + 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) } diff --git a/test/typeparam/mapimp.dir/a.go b/test/typeparam/mapimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..cbfa80ac6b1d338bf40a4d6c76da0f3f419c60b2 --- /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 0000000000000000000000000000000000000000..4d4a4d9eb0b384687ae81fe3dc89c372a537dba3 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/mapsimp.dir/a.go b/test/typeparam/mapsimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..696e2a568014a9b0edb23cb9438557d2e2914526 --- /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 0000000000000000000000000000000000000000..873660e4cd5038f6f316c1d1d5dd7c3883bc1a0c --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/mdempsky/1.dir/a.go b/test/typeparam/mdempsky/1.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..a668eb52dc9dc13d0457e3a8ed3a8049cefac904 --- /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 0000000000000000000000000000000000000000..af6fef3f6d8bad40de56f7c1803ef5990191abc7 --- /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 0000000000000000000000000000000000000000..87b4ff46c1ea4e6750058822d454a40cccb2cf1c --- /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 0000000000000000000000000000000000000000..95e111d3470a1a7259d398b3d68ec26f70b6ed65 --- /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 0000000000000000000000000000000000000000..0ef28fd02de3282e61ce2ebb2b0278db1ee4d9f3 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 0000000000000000000000000000000000000000..e86c038a10468bce44f091844369b07cf412473a --- /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 0000000000000000000000000000000000000000..ee8be939a8fadd5985e56a491ae2d3e19928ef11 --- /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 0000000000000000000000000000000000000000..2891322e298867275828c331830fa8bbd3fda114 --- /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 0000000000000000000000000000000000000000..a2dc4daacccee5e623f57cc1d45ecf266bfe2a7d --- /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 0000000000000000000000000000000000000000..b492774d3d849a285e74202d9f03a128733eadc5 --- /dev/null +++ b/test/typeparam/mdempsky/13.go @@ -0,0 +1,84 @@ +// 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 + +// Interface which will be used as a regular interface type and as a type bound. +type Mer interface{ + M() +} + +// Interface that is a superset of Mer. +type Mer2 interface { + M() + String() string +} + +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() { + 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) +} diff --git a/test/typeparam/mdempsky/14.go b/test/typeparam/mdempsky/14.go new file mode 100644 index 0000000000000000000000000000000000000000..ba685bc35c8d3fd08ae56a6f49f68fe328b3ded3 --- /dev/null +++ b/test/typeparam/mdempsky/14.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 + +// Zero returns the zero value of T +func Zero[T any]() (_ T) { + return +} + +type AnyInt[X any] int + +func (AnyInt[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 = AnyInt[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/15.go b/test/typeparam/mdempsky/15.go new file mode 100644 index 0000000000000000000000000000000000000000..4899fc75eecdbb44a31439c1d88fe5cdb803eb59 --- /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]() +} diff --git a/test/typeparam/mdempsky/2.go b/test/typeparam/mdempsky/2.go new file mode 100644 index 0000000000000000000000000000000000000000..f09730f94910f65f3420d23e8b9fa705f6867415 --- /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 0000000000000000000000000000000000000000..cf456e8d48f17422ebb16183066d6556f371f04e --- /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 0000000000000000000000000000000000000000..0cfd142f4c454e8222253d97e5a48cab273580d5 --- /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 0000000000000000000000000000000000000000..87b4ff46c1ea4e6750058822d454a40cccb2cf1c --- /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 0000000000000000000000000000000000000000..cb672949eaedcd8faaeb72beb135078c6de41a7e --- /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 0000000000000000000000000000000000000000..e1fb0e7c5eaabc3af41c320fe9adfda6a22e7eab --- /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 0000000000000000000000000000000000000000..87b4ff46c1ea4e6750058822d454a40cccb2cf1c --- /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 0000000000000000000000000000000000000000..0d1ad3994624ae1b01cd0bf73f256fd3c36111e5 --- /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 0000000000000000000000000000000000000000..a26ff62f6d44e9275325ee62ce68f97881c4050d --- /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 0000000000000000000000000000000000000000..59c5995611834a9cbec9ca3b2aa9f9588011ea36 --- /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 0000000000000000000000000000000000000000..9f70530811482ea8213ec47efd5f76593a432814 --- /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 0000000000000000000000000000000000000000..87b4ff46c1ea4e6750058822d454a40cccb2cf1c --- /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 0000000000000000000000000000000000000000..607fe5e0af2e098b1083bbe81c12c3f7dfa58506 --- /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/src/cmd/gofmt/gofmt_typeparams_test.go b/test/typeparam/mdempsky/8.dir/b.go similarity index 68% rename from src/cmd/gofmt/gofmt_typeparams_test.go rename to test/typeparam/mdempsky/8.dir/b.go index 10641a77cb2f8762dfd10c2dfbb25313adab225a..84037bf763ecb625fad1de7c081c146ea7beef9b 100644 --- a/src/cmd/gofmt/gofmt_typeparams_test.go +++ b/test/typeparam/mdempsky/8.dir/b.go @@ -2,11 +2,10 @@ // 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 b -package main +import "./a" func init() { - typeParamsEnabled = true + a.F[func()]() // ERROR "does not implement comparable" } diff --git a/test/typeparam/mdempsky/8.go b/test/typeparam/mdempsky/8.go new file mode 100644 index 0000000000000000000000000000000000000000..32cf4b830d256cbd600e05557df95d693a98b2bf --- /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 0000000000000000000000000000000000000000..b72516c4eabccf4175b99bfb9027acd58bcc2ff6 --- /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]() } diff --git a/test/typeparam/min.go b/test/typeparam/min.go index a3e4464a3039c85a9481d05225605f3d92b5c2af..d6c65d68b79db93e9f9aead771071d3e61b67f37 100644 --- a/test/typeparam/min.go +++ b/test/typeparam/min.go @@ -11,7 +11,7 @@ import ( ) type Ordered interface { - type int, int64, float64 + ~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/mincheck.dir/a.go b/test/typeparam/mincheck.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..fa0f249e61510c3a136fc0c66b3cff4d3f876df0 --- /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 { + 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 0000000000000000000000000000000000000000..63786de5e62d2df161a8066ee0d1ad5deacbf8c2 --- /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 implement" + panic(fmt.Sprintf("got %d, want %d", got, want2)) + } + + if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not implement" + 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 0000000000000000000000000000000000000000..32cf4b830d256cbd600e05557df95d693a98b2bf --- /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 diff --git a/test/typeparam/minimp.dir/a.go b/test/typeparam/minimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..fabde62c5d7218c987cbd64793586c941456451c --- /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 { + ~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 0000000000000000000000000000000000000000..509f5aaed2b4cb8b1f0e7a46bc2e93d3c7555ddb --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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/mutualimp.dir/a.go b/test/typeparam/mutualimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..5b924d3ce5dfec687d84c11e0bcf7b145493abcb --- /dev/null +++ b/test/typeparam/mutualimp.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 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 0000000000000000000000000000000000000000..83cc3af2835c55b7c1b5db2ba604d9a5b2da05e8 --- /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 0000000000000000000000000000000000000000..87b4ff46c1ea4e6750058822d454a40cccb2cf1c --- /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 diff --git a/test/typeparam/nested.go b/test/typeparam/nested.go new file mode 100644 index 0000000000000000000000000000000000000000..c0037a3e6e46edbe34cbeec1d61b08abd2a57776 --- /dev/null +++ b/test/typeparam/nested.go @@ -0,0 +1,134 @@ +// 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 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 0000000000000000000000000000000000000000..37cb762e32baacdb79c6bcb980f081664b8a7560 --- /dev/null +++ b/test/typeparam/nested.out @@ -0,0 +1,4 @@ +0,3: main.T·2[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]] diff --git a/test/typeparam/ordered.go b/test/typeparam/ordered.go index 448db68bb55bf5eb64a68bd28a89b3f5ab592d86..0f539d659c39785752cd29083cfad45161bd29ec 100644 --- a/test/typeparam/ordered.go +++ b/test/typeparam/ordered.go @@ -13,15 +13,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 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 db1b3742674080552fd771b41fe6882c08b317be..1f077333b8fcc49c46d10260d58d4d6f1022df37 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. @@ -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 new file mode 100644 index 0000000000000000000000000000000000000000..d6a2de5d7b3e4a7eead46e360ac9a9c04b1293a1 --- /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 0000000000000000000000000000000000000000..978f1e763c09f4d2ae5badbcc33a46dad0771af0 --- /dev/null +++ b/test/typeparam/orderedmapsimp.dir/main.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 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"))) + } + + 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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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/pair.go b/test/typeparam/pair.go index 7faf083c89d117aa8283ca994b9ecb74abacd4cb..c1427b9c52c2d48896401fec162ff12d7a0ec029 100644 --- a/test/typeparam/pair.go +++ b/test/typeparam/pair.go @@ -24,7 +24,11 @@ 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 } + + 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 new file mode 100644 index 0000000000000000000000000000000000000000..a984fba37b6e6655d8ba2031166d7b575737927c --- /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 0000000000000000000000000000000000000000..027fdd9ce766605db05c73fe435af0384923e274 --- /dev/null +++ b/test/typeparam/pairimp.dir/main.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 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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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/recoverimp.dir/a.go b/test/typeparam/recoverimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..a465fd1545fe9deda77d80575f100b4af9d60d30 --- /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 0000000000000000000000000000000000000000..c9d8e3cc0899a545b70867d14a55271493847034 --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 0000000000000000000000000000000000000000..3c8b38cbaeaa7a397e5c1bebcb3084aaf70407ac --- /dev/null +++ b/test/typeparam/recoverimp.out @@ -0,0 +1,2 @@ +panic: 5.3 +panic: hello diff --git a/test/typeparam/select.dir/a.go b/test/typeparam/select.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..983e4b1d5f7cd8c4deb00ce7a43893fb4b09a3e2 --- /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 0000000000000000000000000000000000000000..6ea3fe2eeac3a4b54e0175211a996aca02e34cec --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/sets.go b/test/typeparam/sets.go index 258514489e1708ef552242a081c34f313bfc2c51..4f07b590e36fae404b99cb4d120d7efae02b9c5f 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/setsimp.dir/a.go b/test/typeparam/setsimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..92449ce95620caf19ee17019ddecf36c8130ea89 --- /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 0000000000000000000000000000000000000000..8fd165714395b1d790a37f980cdfc4bbfcbf191c --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/settable.go b/test/typeparam/settable.go index 588166da8584fad5b19ce4ec32026202fcb420aa..412023b20a0abb792d604c5b786a950683014280 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 + ~*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 @@ -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)) @@ -54,12 +53,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/shape1.go b/test/typeparam/shape1.go new file mode 100644 index 0000000000000000000000000000000000000000..de1ea65ed227faa5da63301aad4c5a4573f43dcb --- /dev/null +++ b/test/typeparam/shape1.go @@ -0,0 +1,50 @@ +// 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 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() +} + +type squarer int + +func (x squarer) foo() int { + return int(x*x) +} + +type doubler int + +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 new file mode 100644 index 0000000000000000000000000000000000000000..da9a12ded55a5e58b371ee3a4e6c00be8eb0cdc7 --- /dev/null +++ b/test/typeparam/shape1.out @@ -0,0 +1,4 @@ +25 +10 +6 +4 diff --git a/test/typeparam/sliceimp.dir/a.go b/test/typeparam/sliceimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..dbcfae893185e3b9f2e07f1060c523c0c48b3155 --- /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 { + ~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 comparison +// 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 0000000000000000000000000000000000000000..0f79e10018b17f7e9062316c0db711ba1a91871d --- /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 { + ~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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/slices.go b/test/typeparam/slices.go index 149199eb64909db8844208f2fdcb4de78baa235e..4bdf10748e50c33c5b82b4a04fbc8db95fed12db 100644 --- a/test/typeparam/slices.go +++ b/test/typeparam/slices.go @@ -15,31 +15,31 @@ 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. 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 @@ -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) { @@ -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 63dd9ddb700fe3ee49eeeadc4dd4b4778c5f441d..af1d72d89928fd9638c3aaed1cee404e1f5f6869 100644 --- a/test/typeparam/smallest.go +++ b/test/typeparam/smallest.go @@ -11,13 +11,13 @@ 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 { +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/smoketest.go b/test/typeparam/smoketest.go index b7d6201b2c12494eeee64f2a9eb0b0bbc38c356c..f32b40062d6bc8ca75ae25ef5dbe64054ff5ea35 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 @@ -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] @@ -29,15 +29,15 @@ 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 type _ interface { m1() m2() - type int, float32, string + int | float32 | string m3() } diff --git a/test/typeparam/stringable.go b/test/typeparam/stringable.go index 9340a3b10a9d188dd3eca552189a840f884146cb..855a1edb3bf6884a9917d362d94d987ad00faec2 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,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/stringerimp.dir/a.go b/test/typeparam/stringerimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..3f70937ff55e862ed1fbf8dc206d830f56a97f59 --- /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 0000000000000000000000000000000000000000..e30bdf1abeb671c426b0d69193a6cf648c25f78d --- /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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 98f0fcd888839dbea21f59f2bc5218e96dbe1b05..ad1b41ddac40dc5d1ef0966c8413ff569b752734 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 { - panic(fmt.Sprintf("got %d, want %d", 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 { - 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)) } - 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)) + 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/subdict.go b/test/typeparam/subdict.go new file mode 100644 index 0000000000000000000000000000000000000000..c519b4f51c3d701d17df5eca36060cdbe2737b64 --- /dev/null +++ b/test/typeparam/subdict.go @@ -0,0 +1,43 @@ +// 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 C comparable + +type value[T C] 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)) + } +} diff --git a/test/typeparam/sum.go b/test/typeparam/sum.go index f0f5e6aa07537b4627acf7d049341c835e4aaa00..d444e007a3a492605e0010adb5b3f6e62916793e 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 @@ -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/tparam1.go b/test/typeparam/tparam1.go index 70439333269a704bc5f911bf7d68ac41be17ca92..ef024ce40f08b6516bee45da6f57b605cfc6be70 100644 --- a/test/typeparam/tparam1.go +++ b/test/typeparam/tparam1.go @@ -8,35 +8,36 @@ 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" -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 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]() -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{}]() {} // ok if #48424 is accepted +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 bd90d86fcf2a36f1edf58d781b20e93a4d6308e1..34ea4b8aa99219199d13da19524dcb0994014180 100644 --- a/test/typeparam/typelist.go +++ b/test/typeparam/typelist.go @@ -6,85 +6,91 @@ // 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 { - return &x +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 { - return x[i] +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) { - type myint int +func _[T interface{ ~int }](x T) { 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 { 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 + 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"] } - // 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 _() { +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)) f(0, 0) f1(0, 0) } +*/ -func f2[A any, B interface{type []A}](_ A, _ B) -func _() { +func f2[A any, B interface{ ~[]A }](_ A, _ B) {} +func f2x() { f := f2[byte] f(byte(0), []byte{}) f2(byte(0), []byte{}) @@ -92,31 +98,39 @@ 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 _() { +func f3x() { f := f3[int] var x int 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 _() { +func f4[A any, B interface{ ~[]C }, C interface{ ~*A }](_ A, _ B, c C) {} +func f4x() { f := f4[int] var x int f(x, []*int{}, &x) f4(x, []*int{}, &x) } -func f5[A interface{type struct{b B; c C}}, B any, C interface{type *B}](x B) A -func _() { +func f5[A interface { + ~struct { + b B + c C + } +}, 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 -func _() { - x := f6(struct{f []string}{}) +func f6[A any, B interface{ ~struct{ f []A } }](B) A { panic(0) } +func f6x() { + x := f6(struct{ f []string }{}) var _ string = x } diff --git a/test/typeparam/typeswitch1.go b/test/typeparam/typeswitch1.go new file mode 100644 index 0000000000000000000000000000000000000000..834302e37a1356194bee77b16759da231eeed059 --- /dev/null +++ b/test/typeparam/typeswitch1.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 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)) + f[int32](int32(7)) + f[int](int32(7)) +} diff --git a/test/typeparam/typeswitch1.out b/test/typeparam/typeswitch1.out new file mode 100644 index 0000000000000000000000000000000000000000..dc5dfdb76116522636ea57997095cef06105f62b --- /dev/null +++ b/test/typeparam/typeswitch1.out @@ -0,0 +1,7 @@ +T +int +int32/int16 +struct{T,T} +other +T +int32/int16 diff --git a/test/typeparam/typeswitch2.go b/test/typeparam/typeswitch2.go new file mode 100644 index 0000000000000000000000000000000000000000..ce4af34f04cefa5e20cc46c34c923eaa50c1f81d --- /dev/null +++ b/test/typeparam/typeswitch2.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 "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)) + f[int32](int32(7)) + f[int](int32(7)) +} diff --git a/test/typeparam/typeswitch2.out b/test/typeparam/typeswitch2.out new file mode 100644 index 0000000000000000000000000000000000000000..85b54e38aebf60eb46cbba2f6a80fbf7adf0796a --- /dev/null +++ b/test/typeparam/typeswitch2.out @@ -0,0 +1,7 @@ +T +6.000000e+000 +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 new file mode 100644 index 0000000000000000000000000000000000000000..0527a83eb09f3340c515684805dd96b380c104ba --- /dev/null +++ b/test/typeparam/typeswitch3.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 + +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)) + f[myint32](myint32(8)) + f[myint32](myfloat(7)) + f[myint](myint32(9)) +} diff --git a/test/typeparam/typeswitch3.out b/test/typeparam/typeswitch3.out new file mode 100644 index 0000000000000000000000000000000000000000..ed59987e6d96deb29b29e0463cc4fd8ce8a67879 --- /dev/null +++ b/test/typeparam/typeswitch3.out @@ -0,0 +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 new file mode 100644 index 0000000000000000000000000000000000000000..08de2a1d411a4245936a2c0577433571f66d28df --- /dev/null +++ b/test/typeparam/typeswitch4.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 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)) + f[myint32](myint32(9)) + f[myint](myint32(10)) + f[myint](myfloat(42)) +} diff --git a/test/typeparam/typeswitch4.out b/test/typeparam/typeswitch4.out new file mode 100644 index 0000000000000000000000000000000000000000..d6121d077c051976f0a6bea207e9f41b5fb8eda8 --- /dev/null +++ b/test/typeparam/typeswitch4.out @@ -0,0 +1,6 @@ +other 6 +T/myint32 7 +T/myint32 8 +T/myint32 9 +T/myint32 10 +other 42 diff --git a/test/typeparam/typeswitch5.go b/test/typeparam/typeswitch5.go new file mode 100644 index 0000000000000000000000000000000000000000..1fc6e0a14ee533680f7c704b23d60551ab7d3f16 --- /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 0000000000000000000000000000000000000000..6b4cb4416f4536f81658050e0a3e9548728cfc09 --- /dev/null +++ b/test/typeparam/typeswitch5.out @@ -0,0 +1,4 @@ +fooer 6 +other +other +fooer +9.000000e+000 diff --git a/test/typeparam/typeswitch6.go b/test/typeparam/typeswitch6.go new file mode 100644 index 0000000000000000000000000000000000000000..574f4aa819eecf6cf519f5ae36824e5f9d16c5d5 --- /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 0000000000000000000000000000000000000000..441add5ec5bed8e4e8919df3602fc16ba9a3f87a --- /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 0000000000000000000000000000000000000000..f2e1279fb41c5c622b84c6da7a0ca20f5ee11ad9 --- /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 0000000000000000000000000000000000000000..d7fcad4fee14f8788902cc35bdaa2aa3af80ff6e --- /dev/null +++ b/test/typeparam/typeswitch7.out @@ -0,0 +1,3 @@ +other +barT +myfloat diff --git a/test/typeparam/valimp.dir/a.go b/test/typeparam/valimp.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..2ed0063cfd6473855a71a27e3327130ae6c553a2 --- /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 0000000000000000000000000000000000000000..606ff2273af8333521a5947fe262497110181dc1 --- /dev/null +++ b/test/typeparam/valimp.dir/main.go @@ -0,0 +1,55 @@ +// Copyright 2021 The Go Authors. 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 0000000000000000000000000000000000000000..76930e5e4f694938e8456a8875300e2529e2ee08 --- /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 diff --git a/test/typeparam/value.go b/test/typeparam/value.go index 5dd7449d9c76f9ee563d277255bc16fbfbb1cfd5..6c6dabcf7ca8725c5171730a7afe8919289c0ed8 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 } diff --git a/test/typeswitch3.go b/test/typeswitch3.go index a57889bc1dee4f66dd7276e746812f8dd6817938..2e144d81c00cef738b5ff3acadd19d1aedfa6ba3 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" } } diff --git a/test/uintptrescapes2.go b/test/uintptrescapes2.go index 3ff1d940425863caae41c03e59a1a57d379e97e0..656286c0ff2bd72e7580bd7592a533d4a346d1df 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" diff --git a/test/unsafebuiltins.go b/test/unsafebuiltins.go index 4c940aa85599c12c4b4300744983ae769d43da49..d04bcbdc7d6a2f8f41d9c617791b8c8aa01661a7 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) }) } } diff --git a/test/writebarrier.go b/test/writebarrier.go index dbf0b6dde28662d0d6670037744c6611866e31a1..1b30fa509e5503275904c53fb7d559296ab85259 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 + } +} diff --git a/test/zerodivide.go b/test/zerodivide.go index 214d481164442aab25c7e5f9189933108a54c005..fd36d67d1ad6dc8b189473a7e45206edea866428 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")