[dev.cmdgo] all: merge master (c2f96e6) into dev.cmdgo

src/cmd/go/testdata/script/work.txt and
src/cmd/go/testdata/script/work_edit.txt were updated so the want files
specified go1.18 as that's what go mod initwork will produce under Go
1.18.

Conflicts:

- src/cmd/go.mod
- src/cmd/go.sum
- src/cmd/go/internal/modload/init.go
- src/cmd/go/internal/work/init.go
- src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go
- src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go
- src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go
- src/cmd/vendor/modules.txt
- src/cmd/vet/testdata/print/print.go

Merge List:

+ 2021-08-24 c2f96e686f cmd/compile: mark ODYNAMICDOTTYPE as an expression that can panic
+ 2021-08-24 5b64381155 cmd/compile: fix naming of types inside instantiations
+ 2021-08-24 4a9f0cec29 cmd/compile: change irgen to generate exprs/stmts after decls processed
+ 2021-08-24 daa55b21d1 cmd/link: guarantee "section .debug_gdb_scripts" is always "$GOROOT/src/runtime/runtime-gdb.py".
+ 2021-08-24 e6798795ff cmd/compile/internal/types2: use TypeList in the Inferred struct
+ 2021-08-24 b1cdf860dd cmd/compile/internal/types2: use a TypeList type to hold type arguments
+ 2021-08-24 1ff0554b53 cmd/compile/internal/types2: use []*TypeParam rather than []*TypeName for type param lists
+ 2021-08-24 bd97763577 cmd/compile/internal/types2: use an opaque environment for Instantiate
+ 2021-08-24 bba460499c cmd/compile/internal/types2: don't export TypeSet
+ 2021-08-24 d70c69d830 embed: document the maximum file size supported
+ 2021-08-24 f98b6111eb go/token: match the implementation of index selection with sort.Search
+ 2021-08-24 8eeb1bff1d cmd/compile: reuse same node for global dictionaries
+ 2021-08-23 be1a693477 cmd/compile: fixes for non-constant Sizeof/Alignof/Offsetof
+ 2021-08-23 8157960d7f all: replace runtime SSE2 detection with GO386 setting
+ 2021-08-23 22540abf76 runtime: use RDTSCP for instruction stream serialized read of TSC
+ 2021-08-23 fa34678c67 internal/buildcfg: change GOEXPERIMENT to always return non-empty string
+ 2021-08-23 0a7f00ae23 cmd/compile: do not mark arrays used for map initialization noalg
+ 2021-08-23 6b9e3f883e cmd/compile: don't emit write barriers for offsets of global addresses
+ 2021-08-23 3081f817da cmd/compile: always remove receiver type from instantiated method values
+ 2021-08-23 8486ced8b0 cmd/compile: copy captured dictionary var to local var
+ 2021-08-23 aeec6dbfe0 spec: add example for method value in case of embedded method
+ 2021-08-23 f457ecc7f0 cmd/compile: fixing 15.go for -G=3
+ 2021-08-23 f1d8ea1da3 reflect: fix memmove for big endian cases with new ABI
+ 2021-08-23 4fbb5c8666 go/types: use TypeList in the Inferred struct
+ 2021-08-23 7a6d64fed6 go/types: use a TypeList type to hold type arguments
+ 2021-08-23 2438660602 go/types: use []*TypeParam rather than []*TypeName type param lists
+ 2021-08-23 9fe5c7f122 go/types: add the TypeParam.Obj method
+ 2021-08-23 baf2866956 go/types: move to an opaque environment for Instantiate
+ 2021-08-23 c7e354d9d1 go/types: return an error from Instantiate
+ 2021-08-23 c1a14781ec runtime: remove unused cpu architecture feature variables from binaries
+ 2021-08-23 457418b475 cmd/go: fix long test builders
+ 2021-08-22 86ee89225a strings: smarter growth of temporal buffer and avoid copying on return
+ 2021-08-22 29d7e5472b go/types: report argument type for unsafe.OffsetOf
+ 2021-08-22 8fcc614360 cmd/compile/internal/types2: enable TestSelection API test
+ 2021-08-22 5d5e50c3db os/user: simplify test skip for plan9
+ 2021-08-22 5d0c2840da cmd/compile/internal/types2: report argument type for unsafe.OffsetOf
+ 2021-08-22 19585826fa math/big: clarified doc string for SetMantExp
+ 2021-08-22 6416bde023 runtime: use asmcgocall_no_g when calling sigprocmask on openbsd
+ 2021-08-22 bd6845965c reflect: add example for FieldByIndex
+ 2021-08-22 96d816c574 runtime: fix buckHashSize duplication
+ 2021-08-21 6e50991d2a strconv: reject surrogate halves in Unquote
+ 2021-08-21 8fff20ffeb cmd/compile: absorb NEG into branch when possible on riscv64
+ 2021-08-21 bcd146d398 cmd/compile: convert branch with zero to more optimal branch zero on riscv64
+ 2021-08-21 dcee007aad cmd/compile: sort regalloc switch by architecture
+ 2021-08-21 e17439e087 go/types: don't override x.mode before using it
+ 2021-08-21 c9912780ab cmd/compile: enable -G=3 by default
+ 2021-08-20 97d17dc023 test/typeparam: add a test case for issue46591
+ 2021-08-20 835ff47c16 cmd/internal/buildid: reject empty id
+ 2021-08-20 f67e31d643 test: enable regabi test on arm64
+ 2021-08-20 ab9aaf46ee cmd/compile/internal/syntax: add PosBase.Trimmed
+ 2021-08-20 5045477be8 net/http: fix typo in header.go
+ 2021-08-20 0f25251127 go/types: change Checker.verify to return an error
+ 2021-08-20 30a423eb39 go/types: no need to validate substituted instances
+ 2021-08-20 e49775e057 go/types: consolidate verification logic
+ 2021-08-20 4d00fcbc43 go/types: clean up panics in instantiation
+ 2021-08-20 bacbc33439 archive/zip: prevent preallocation check from overflowing
+ 2021-08-20 7007431374 crypto/rand, internal/syscall/unix: don't use getentropy on iOS
+ 2021-08-20 303446395d cmd/compile: use typeAndStr directly in signatslice
+ 2021-08-20 e9e0d1ef70 cmd/asm/internal/arch: adds the missing type check for arm64 SXTB extension
+ 2021-08-20 c92c2c9d62 cmd/internal/obj/arm64: disable the pre and post index formats for pseudo registers
+ 2021-08-19 65074a4086 cmd/dist: remove unused variables
+ 2021-08-19 0e598e7da4 syscall: add SyscallN
+ 2021-08-19 91e2e3b903 cmd/compile: prevent duplicated works in WriteRuntimeTypes
+ 2021-08-19 9871726c72 reflect: add test for invalid conversion
+ 2021-08-19 69d8fbec7a cmd/compile/internal/types2: return an error from Instantiate
+ 2021-08-19 3bdc1799d6 io: unexport internal methods
+ 2021-08-19 740f7d7370 archive/tar: unexport internal methods
+ 2021-08-19 c85695a117 cmd/compile: add support for //go:nointerface for -G=3
+ 2021-08-18 322879d5c9 cmd/compile/internal/dwarfgen: use src.Pos.Rel{Filename,Line,Col} consistently
+ 2021-08-18 687f2acf6a cmd/compile: only use dictionaries for conversions to type parameters
+ 2021-08-18 eda3de0f79 cmd/compile/internal/types2: change Checker.verify to return an error
+ 2021-08-18 805d38a352 cmd/compile/internal/types2: no need to validate substituted instances
+ 2021-08-18 c2bd9ee2db cmd/compile: only sort methods/interfaces during export for -d=unifiedquirks
+ 2021-08-18 8f0578ef39 cmd/compile/internal/types2: consolidate verification logic
+ 2021-08-18 165ebd85a7 cmd/compile/internal/types2: clean up panics in instantiation
+ 2021-08-18 4a0fd73ead cmd/go/internal/work/exec: throw an error when buildP is negative
+ 2021-08-18 0c83e01e0c cmd/go/testdata/script: fix test script added by CL 334873
+ 2021-08-18 8b471db71b path/filepath: change IsAbs to treat \\host\share as an absolute path
+ 2021-08-18 946e2543f8 runtime: use RDCYCLE for cputicks on riscv64
+ 2021-08-18 8e18428e38 cmd/internal/obj/arm64: don't use REGTMP when moving C_AACON2 to a register
+ 2021-08-18 aef24d8f7d cmd/internal/obj/arm64: fix the encoding error when operating with ZR
+ 2021-08-17 ddfcc02352 cmd/link: do not use GO_LDSO when cross compile
+ 2021-08-17 a2a9a7b513 cmd/go: make mod init disallow invalid major version suffixes
+ 2021-08-17 3848488f0f cmd/go/internal/test: add an all sentinel to -vet
+ 2021-08-17 ace1730a41 cmd/go: go test flag -failfast should be cacheable
+ 2021-08-17 0f85b0c0e1 go/types: fix method lookup for type-parameter based types
+ 2021-08-17 9d9e3291fa cmd/compile/internal/types2: fix method lookup for type-parameter based types
+ 2021-08-17 cf12b0d1f9 cmd/trace: use newTaskDesc to create taskDesc
+ 2021-08-17 3001b0abf0 cmd/link: remove elfwritedynentsym
+ 2021-08-17 4012fea822 all: fix typos
+ 2021-08-17 b7b790a71a cmd/compile: fix CONVIFACE case converting interface to empty interface
+ 2021-08-17 a304273d74 cmd/compile/internal/types2: allow composite literals of type parameter type
+ 2021-08-17 d3deb2c359 cmd/compile: fix typos
+ 2021-08-17 29ec74fb82 go/types: check if the interface is already complete in Complete
+ 2021-08-17 91a935ea0f Revert "go/types: make Interface.Complete a no-op"
+ 2021-08-17 a8d39f151d src: simplify race.bash checking condition
+ 2021-08-17 1951afc919 cmd/compile: lowered MulUintptr on riscv64
+ 2021-08-16 2a19333716 net: reduce allocations for UDP send/recv on Windows
+ 2021-08-16 9c5eb16f6c net: reduce allocation size in ReadFromUDP
+ 2021-08-16 d9349175ad net: remove allocation from UDPConn.WriteTo
+ 2021-08-16 8ff16c1990 runtime: accept restartable sequence pcdata values in isAsyncSafePoint
+ 2021-08-16 df9c5d8f5d cmd/cgo: fix unused parameter warnings in generated _cgo_main.c
+ 2021-08-16 213e157d3a testing/fstest: allow specifying file for "." in MapFS
+ 2021-08-16 c04a32e59a net: avoid memory copy calling absDomainName
+ 2021-08-16 6406227d71 runtime: skip sysmon workaround on NetBSD >= 9.2
+ 2021-08-16 a05a7d49a9 cmd/go: address code review comments in test cgo_path_space_quote
+ 2021-08-16 54ce8793a8 cmd: update x/tools and remove copy of txtar
+ 2021-08-16 742dcba7bb cmd: support space and quotes in CC and CXX
+ 2021-08-16 41d991e4e1 cmd/internal/str: add utilities for quoting and splitting args
+ 2021-08-16 4466141822 cmd/go: add document -json in testflag
+ 2021-08-16 8d2066177d cmd/go/internal/modfetch/codehost: refactor gitRepo.loadRefs to be harder to misuse
+ 2021-08-16 ec27168712 net/http: drop headers with invalid keys in Header.Write
+ 2021-08-16 d35035f84e go/types: use the orig object for Named.Obj
+ 2021-08-16 ddffe30a21 go/types: rename TypeParams to TParamList
+ 2021-08-16 631af58e20 go/types: remove targs from substMap
+ 2021-08-16 d1ba047edf go/types: simplify Named.under
+ 2021-08-16 56a919f17f go/types: define Identical for instances
+ 2021-08-16 ff36d11470 go/types: merge Instantiate and InstantiateLazy
+ 2021-08-16 2460cf8602 go/types: remove Named.SetTArgs
+ 2021-08-16 281ed619f8 go/types: parameterized functions must have a body
+ 2021-08-16 aab1d1fcb9 go/types: expand is only required for *Named types
+ 2021-08-16 9ff61acbd7 go/types,types2: superficial changes to align types and types2
+ 2021-08-16 fda8ee8b07 go/types: make Interface.Complete a no-op
+ 2021-08-16 e61d1445ab cmd/compile: fix panic with dead hidden closures
+ 2021-08-16 5c7a460a1c syscall: hoist Getsockname out of NetlinkRIB loops
+ 2021-08-16 850768bbc9 time: update current time comment
+ 2021-08-16 a0adf91d85 internal/syscall/unix: change Ioctl arg type to unsafe.Pointer on AIX
+ 2021-08-16 5a40100141 cmd/compile: fix dictionaries for nested closures
+ 2021-08-16 c92f5ee170 cmd/link: start at address 0 when external linking
+ 2021-08-16 5da2010840 doc: start draft of go1.18 release notes, move go1.17 to x/website
+ 2021-08-16 ea8298e2f5 cmd/compile/internal/ssa: delete unused code
+ 2021-08-16 fe489c86a7 go/types: limit termlist lengths
+ 2021-08-16 b9f135d98f go/types: change types2.Union API to accept a list of Terms
+ 2021-08-16 c2b4ec8f49 go/types: add defined type to term/termlist tests
+ 2021-08-16 11a43df461 go/types: minor cleanup of writeTParamList
+ 2021-08-16 b0fba64ef4 go/types: fix make with type parameter argument
+ 2021-08-16 efd206eb40 cmd/compile: intrinsify Mul64 on riscv64
+ 2021-08-16 7b7d7d7818 go/types: fix range over exprs of type parameter type
+ 2021-08-16 02f932e173 go/types: better names for things (cleanup)
+ 2021-08-16 a192ef8ac4 go/types: cleanup panic calls
+ 2021-08-16 11a1f37b07 go/types: remove TestIncompleteInterfaces (cleanup)
+ 2021-08-16 0b61dc4577 go/types: remove unused gcCompatibilityMode flag (cleanup)
+ 2021-08-16 c88e3ff648 cmd/compile/internal/types2: use the underlying TypeParam in assignableTo
+ 2021-08-16 d043c8ea89 go/types: implement type sets with term lists
+ 2021-08-16 94002f6fca go/types: implement term lists
+ 2021-08-16 3d679c6554 syscall: use correct type for TIOCSPGRP/TIOCGPGRP
+ 2021-08-16 fcdc3c098c runtime: make asmcgocall g0/gsignal checks consistent
+ 2021-08-16 160d797260 runtime: correct mips64 asmcgocall signal stack behaviour
+ 2021-08-16 6a760d6c36 runtime: include pthread.h in defs_openbsd.go
+ 2021-08-16 7aa57a9687 runtime: remove unused getrlimit on linux/riscv64
+ 2021-08-16 57c115e1f6 crypto/sha{256,512}: unname result parameters for consistency
+ 2021-08-15 717894cf80 cmd/compile/internal/types2: better error message for index syntax error (follow-up)
+ 2021-08-15 6ed9463133 cmd/compile/internal/syntax: better error message for index syntax error
+ 2021-08-15 48dfddbab3 lib/time: fix RFC 6557 url
+ 2021-08-15 1162aae0ad time/tzdata: update links in comment
+ 2021-08-14 ff3469b1c2 cmd/dist: remove tests using the typeparams build tag
+ 2021-08-14 0a0a160d4d sync/atomic: fix documentation for CompareAndSwap
+ 2021-08-14 49c688e45c cmd/compile/internal/types2: rename TypeParams to TParamList
+ 2021-08-14 b2253c8041 cmd/compile/internal/types2: remove targs from substMap
+ 2021-08-14 456759b246 cmd/compile/internal/types2: use the orig object for Named.Obj
+ 2021-08-14 2d250043b4 cmd/compile/internal/types2: simplify Named.under
+ 2021-08-14 50f4ebbdd3 cmd/compile/internal/types2: define Identical for instances
+ 2021-08-14 fc27eb50ff cmd/compile/internal/types2: merge Instantiate and InstantiateLazy
+ 2021-08-13 7eaabae84d net: update IP.String doc to reflect RFC 5952 conformance
+ 2021-08-13 58490972c0 cmd/link: fix dead reference link
+ 2021-08-13 a95f1b51be test: change issue10441.go from "build" to "compile"
+ 2021-08-13 89a4f99640 lib/time: fix tz-link ftp url
+ 2021-08-13 2eb4d68833 runtime: don't use systemstack for BeforeFork/AfterFork
+ 2021-08-13 bad1fc1265 test: add test case for CL 340609
+ 2021-08-13 641e8bc2c7 test: add test case that caused a gofrontend compiler crash
+ 2021-08-13 98f3d7fecb all: gofmt more (but vendor, testdata, and top-level test directories)
+ 2021-08-13 20a620fd9f runtime: drop SIGPROF while in ARM < 7 kernel helpers
+ 2021-08-13 4c8ffb3baa cmd/internal/str: move package from cmd/go/internal/str
+ 2021-08-13 4be75faa3e cmd/go: make fewer 'go mod' commands update go.mod
+ 2021-08-13 1fffeddfe9 cmd/go: add -testsum flag to update go.sum in script tests
+ 2021-08-12 0d01934094 Merge "all: REVERSE MERGE dev.typeparams (4d3cc84) into master"
+ 2021-08-12 044ec4fa98 time: fix docs for new comma layouts
+ 2021-08-12 3601aedff6 all: REVERSE MERGE dev.typeparams (4d3cc84) into master
+ 2021-08-12 4d3cc84774 Merge "[dev.typeparams] all: merge master (46fd547) into dev.typeparams" into dev.typeparams
+ 2021-08-12 a64ab8d3ec [dev.typeparams] all: merge master (46fd547) into dev.typeparams
+ 2021-08-12 7e9f911ec4 [dev.typeparams] cmd/compile:  remove some shape checks in type substituter, other cleanups
+ 2021-08-12 46fd547d89 internal/goversion: update Version to 1.18
+ 2021-08-12 5805efc78e doc/go1.17: remove draft notice
+ 2021-08-12 39634e7dae CONTRIBUTORS: update for the Go 1.17 release
+ 2021-08-12 095bb790e1 os/exec: re-enable LookPathTest/16
+ 2021-08-12 677dfe5ad6 [dev.typeparams] cmd/compile: don't print out node pointer in ir.Dump
+ 2021-08-11 dea23e9ca8 src/make.*: make --no-clean flag a no-op that prints a warning
+ 2021-08-11 8ab59d812a [dev.typeparams] cmd/compile: change export version to 1.17 for testing
+ 2021-08-11 d7d4f28a06 [dev.typeparams] runtime, internal/bytealg: remove regabi fallback code on AMD64
+ 2021-08-11 eeb7899137 [dev.typeparams] internal/buildcfg: always enable regabi on AMD64
+ 2021-08-11 d4c0ed26ac doc/go1.17: linker passes -I to extld as -Wl,--dynamic-linker
+ 2021-08-11 0888a8cd2d [dev.typeparams] cmd/compile/internal/types2: remove unused TypeParam.Bound method
+ 2021-08-10 7308d747e7 [dev.typeparams] cmd/compile/internal/types2: remove Named.SetTArgs
+ 2021-08-10 0f34a92df7 [dev.typeparams] go/types: don't expose the TypeSet API for 1.18
+ 2021-08-10 40ba119e3f [dev.typeparams] cmd/compile: keep export format unchanged if no type params are exported
+ 2021-08-10 fb8579746c [dev.typeparams] internal/goexperiment: update comment for RegabiArgs requirements
+ 2021-08-10 2e250cc957 [dev.typeparams] cmd: update vendored golang.org/x/tools to 337cebd2c1
+ 2021-08-10 2fbf6aafe7 [dev.typeparams] cmd/compile: handle interface type parameters in type switches
+ 2021-08-10 e4cfa2f6da [dev.typeparams] cmd/compile/internal/types2: parameterized functions must have a body
+ 2021-08-10 508624f359 [dev.typeparams] cmd/compile/internal/types2: expand is only required for *Named types
+ 2021-08-10 1f9c9d8530 doc: use "high address/low address" instead of "top/bottom"
+ 2021-08-09 f5f79c47f9 [dev.typeparams] cmd/compile: use types2.Constraint() rather than types2.Bound()
+ 2021-08-09 f1dce319ff cmd/go: with -mod=vendor, don't panic if there are duplicate requirements
+ 2021-08-09 9f4d6a8359 [dev.typeparams] cmd/compile: call transformArgs before early typecheckaste in noder
+ 2021-08-09 ca3c6985cd [dev.typeparams] cmd/compile: implement generic type switches
+ 2021-08-09 57668b84ff [dev.typeparams] cmd/compile: simplify interface conversions
+ 2021-08-09 7aeaad5c86 runtime/cgo: when using msan explicitly unpoison cgoCallers
+ 2021-08-08 507cc341ec doc: add example for conversion from slice expressions to array ptr
+ 2021-08-07 d10a904712 [dev.typeparams] cmd/compile: don't export/import type parameter indices anymore
+ 2021-08-07 891547e2d4 doc/go1.17: fix a typo introduced in CL 335135
+ 2021-08-06 8eaf4d16bc make.bash: do not overwrite GO_LDSO if already set
+ 2021-08-06 63b968f4f8 doc/go1.17: clarify Modules changes
+ 2021-08-06 9e0ac72d68 [dev.typeparams] cmd/compile/internal/types2: remove Interface.Complete (cleanup)
+ 2021-08-06 9bd1817e41 [dev.typeparams] cmd/compile/internal/types2: limit termlist lengths
+ 2021-08-06 313924f272 [dev.typeparams] cmd/compile: swap export order of union term components (cleanup)
+ 2021-08-06 0d7dc417ea [dev.typeparams] cmd/compile: change types2.Union API to accept a list of Terms
+ 2021-08-06 09d82689ed [dev.typeparams] cmd/compile/internal/types2: add defined type to term/termlist tests
+ 2021-08-06 3a9fd99849 [dev.typeparams] cmd/compile/internal/syntax: cleanup panic calls
+ 2021-08-06 c3b57af8bc [dev.typeparams] cmd/compile/internal/types2: minor cleanup of writeTParamList
+ 2021-08-06 0811108670 [dev.typeparams] cmd/compile/internal/types2: fix make with type parameter argument
+ 2021-08-06 93285c89d1 [dev.typeparams] cmd/compile/internal/types2: fix range over exprs of type parameter type
+ 2021-08-06 5aac85ad5e [dev.typeparams] cmd/compile/internal/types2: better names for things (cleanup)
+ 2021-08-06 110343e4a2 [dev.typeparams] cmd/compile: cleanup wrapper code for generics
+ 2021-08-06 5e33d11e10 [dev.typeparams] cmd/compile: do transformCall with non-shape type of call
+ 2021-08-06 ac78501b9c [dev.typeparams] cmd/compile: make sure closures inside generic funcs are not compiled
+ 2021-08-06 70546f6404 runtime: allow arm64 SEH to be called if illegal instruction
+ 2021-08-05 fd45e267c2 runtime: warn that KeepAlive is not an unsafe.Pointer workaround
+ 2021-08-05 f78d538858 [dev.typeparams] cmd/compile/internal/types2: cleanup panic calls
+ 2021-08-05 c5b6c36ddd [dev.typeparams] cmd/compile/internal/types2: remove TestIncompleteInterfaces (cleanup)
+ 2021-08-05 f14908d01b [dev.typeparams] cmd/compile/internal/types2: remove unused gcCompatibilityMode flag (cleanup)
+ 2021-08-05 bb5608dd5d [dev.typeparams] cmd/compile/internal/types2: implement type sets with term lists
+ 2021-08-05 6dadee759c [dev.typeparams] cmd/compile: unified importReader receiver name to r
+ 2021-08-05 5dcb5e2cea [dev.typeparams] cmd/compile: dictionary/shape cleanup
+ 2021-08-05 3cdf8b429e [dev.typeparams] cmd/compile: fixing case where type arg is an interface
+ 2021-08-04 1b708c0260 [dev.typeparams] go/types: remove a stale comment (cleanup)
+ 2021-08-04 0ec2a8b42d [dev.typeparams] go/types: switch the TArgs API to NumTArgs/TArg
+ 2021-08-04 e5fe769be1 [dev.typeparams] cmd/compile/internal/types2: implement term lists
+ 2021-08-04 b730a26729 [dev.typeparams] cmd/compile: put shape types in their own package
+ 2021-08-04 e590cb64f9 [dev.typeparams] runtime: handle d.link carefully when freeing a defer
+ 2021-08-04 6e738868a7 net/http: speed up and deflake TestCancelRequestWhenSharingConnection
+ 2021-08-04 d27a889119 [dev.typeparams] go/types: move instance.go contents into named.go (cleanup)
+ 2021-08-04 b01e775e9c [dev.typeparams] go/types: print constraint info for type param operands
+ 2021-08-04 3efc8f9a8d [dev.typeparams] go/types: (TypeParam) SetBound -> SetConstraint
+ 2021-08-04 ed3667d079 [dev.typeparams] go/types: use type terms to represent unions
+ 2021-08-04 880ab6209e [dev.typeparams] cmd/compile/internal/types2: fix a panic in missingMethod
+ 2021-08-04 5b51cf47dc [dev.typeparams] go/types: implement type terms
+ 2021-08-04 e0d0907212 [dev.typeparams] go/types: use comparable bit rather than ==() method
+ 2021-08-04 18e0503724 [dev.typeparams] go/types: embedded type cannot be a (pointer to) a type parameter
+ 2021-08-04 89897473e2 [dev.typeparams] go/types: implement TypeParam.Constraint
+ 2021-08-04 1ea3596b41 [dev.typeparams] go/types: adjust unsafe.Alignof/Offsetof/Sizeof
+ 2021-08-03 88bd92bb6d [dev.typeparams] runtime: simplify freedefer
+ 2021-08-03 1a0630aef4 [dev.typeparams] runtime,cmd/compile,cmd/link: replace jmpdefer with a loop
+ 2021-08-03 077925e2b0 [dev.typeparams] runtime: remove unnecessary split-prevention from defer code
+ 2021-08-03 7ab8754029 [dev.typeparams] cmd/compile: avoid redundant method wrappers in unified IR
+ 2021-08-03 fe73f28dc5 [dev.typeparams] cmd/compile: set sym.Def to ir.Name for method value wrappers
+ 2021-08-03 656f0888b7 [dev.typeparams] cmd/compile: make softfloat mode work with register ABI
+ 2021-08-03 1b193598b3 [dev.typeparams] cmd/compile: fail early on unexpected types2.Invalid
+ 2021-08-02 e56234a305 [dev.typeparams] cmd/compile: simple shape cleanups
+ 2021-08-02 c3c19731a9 [dev.typeparams] cmd/compile/internal/types2: move instance.go contents into named.go (cleanup)
+ 2021-08-02 156eeb40a6 [dev.typeparams] cmd/compile: make HasShape() more efficient by implementing with a type flag
+ 2021-08-02 8a7ee4c51e io/fs: don't use absolute path in DirEntry.Name doc
+ 2021-08-02 283991bd7f [dev.typeparams] cmd/compile/internal/types2: print constraint info for type param operands
+ 2021-08-02 aa3d54da07 [dev.typeparams] runtime: rewrite softfloat functions to avoid using floats
+ 2021-07-31 b8ca6e59ed all: gofmt
+ 2021-07-31 0b8a9ccb25 [dev.typeparams] cmd/compile: make all pointer types have the same shape
+ 2021-07-30 7bed50e667 [dev.typeparams] Revert "[dev.typeparams] runtime: remove unnecessary split-prevention from defer code"
+ 2021-07-30 e3e9f0bb2d [dev.typeparams] Revert "[dev.typeparams] runtime,cmd/compile,cmd/link: replace jmpdefer with a loop"
+ 2021-07-30 40e561d933 [dev.typeparams] cmd/compile: allow types with the same underlying type to have the same shape
+ 2021-07-30 fd0011dca5 [dev.typeparams] runtime,cmd/compile,cmd/link: replace jmpdefer with a loop
+ 2021-07-30 53fd5b1b77 [dev.typeparams] runtime: remove unnecessary split-prevention from defer code
+ 2021-07-30 ea94e5d3c5 [dev.typeparams] runtime: use func() for deferred functions
+ 2021-07-30 b7a85e0003 net/http/httputil: close incoming ReverseProxy request body
+ 2021-07-30 4480e3b11a [dev.typeparams] go/types: backport lazy loading changes from CL 336252
+ 2021-07-30 27283d208f [dev.typeparams] cmd/compile: remove now-unneeded check for '==' method for comparable type
+ 2021-07-29 3e7571f6ff [dev.typeparams] go/types,cmd/compile/internal/types2: fix TypeParams.At docs
+ 2021-07-29 1d35d8ffa5 [dev.typeparams] cmd/compile: switch unified IR from TypeParam.Bound to TypeParam.Constraint
+ 2021-07-29 35dbdda2fe [dev.typeparams] cmd/compile: remove remaining uses of Unshapify
+ 2021-07-29 600b7b431b [dev.typeparams] cmd/compile: handle meth expressions on typeparams
+ 2021-07-29 5ecbd811b5 [dev.typeparams] cmd/compile/internal/types2: (TypeParam) SetBound -> SetConstraint
+ 2021-07-29 46cc686381 [dev.typeparams] cmd/compile/internal/types2: use the TParams API consistently
+ 2021-07-29 27552e9172 [dev.typeparams] cmd/compile: set type parameter indices when they are bound
+ 2021-07-29 af903261e7 [dev.typeparams] go/types, types2: remove instance.verify field (cleanup)
+ 2021-07-29 c079b6baaa [dev.typeparams] cmd/compile/internal/types2: trigger verification while resolving instance
+ 2021-07-29 ff0c0dbca6 [dev.typeparams] cmd/compile/internal/types2: use type terms to represent unions
+ 2021-07-29 2fa8f00915 [dev.typeparams] cmd/compile/internal/types2: implement type terms
+ 2021-07-29 f4f503e0a3 [dev.typeparams] cmd/compile: implement generic .(T) operations
+ 2021-07-29 70fd4e47d7 runtime: avoid possible preemption when returning from Go to C
+ 2021-07-28 4a47e40a14 [dev.typeparams] cmd/compile: don't export blank functions in unified IR
+ 2021-07-28 506fd520d5 [dev.typeparams] cmd/compile: don't compile blank functions
+ 2021-07-28 adedf54288 [dev.typeparams] test: rename blank functions
+ 2021-07-28 5355753009 [dev.typeparams] test/typeparam: gofmt -w
+ 2021-07-28 473e493d18 [dev.typeparams] cmd/compile/internal/types2: merge instance and Named to eliminate sanitization
+ 2021-07-28 e00a6ec084 [dev.typeparams] cmd/compile: mark methods of instantiated interface types as used
+ 2021-07-27 c751e2e6ba [dev.typeparams] cmd/compile/internal/types2: use comparable bit rather than ==() method
+ 2021-07-27 5d8f90f904 [dev.typeparams] cmd/compile: don't need to unshapify append calls
+ 2021-07-27 cb14e673ec [dev.typeparams] runtime: don't keep stack uintptr across potential stack move
+ 2021-07-26 37d2219960 [dev.typeparams] cmd/compile/internal/types2: embedded type cannot be a (pointer to) a type parameter
+ 2021-07-26 d6753fd491 [dev.typeparams] cmd/compile/internal/types2: implement TypeParam.Constraint
+ 2021-07-26 9e3274bb3d [dev.typeparams] cmd/compile/internal/types2: import regexp/syntax instead of cmd/compile/internal/syntax
+ 2021-07-26 b93f646125 [dev.typeparams] cmd/compile/internal/types2: fix a bug in package qualification logic
+ 2021-07-26 996b0dbc65 [dev.typeparams] all: merge master (ecaa681) into dev.typeparams
+ 2021-07-26 bfcb7c4c8a [dev.typeparams] cmd/compile: fix unified IR support for //go:nointerface
+ 2021-07-24 b27c7e30dc [dev.typeparams] cmd/compile: fix HasShape, add dottype test
+ 2021-07-24 a2e2b0362b [dev.typeparams] transformDot() should set Selection and tc flag for added ODOTs
+ 2021-07-24 3dc0a0a2c5 [dev.typeparams] cmd/compile: get rid of concretify use for bounds.
+ 2021-07-24 77e0bf294c [dev.typeparams] cmd/compile: introduce OCONVIDATA op
+ 2021-07-24 9f928f9318 [dev.typeparams] go/types, types2: set tset when constructing interfaces in the universe
+ 2021-07-23 6992dcdad9 [dev.typeparams] cmd/compile: fix some issues with cons.go
+ 2021-07-23 e6d956e1c5 [dev.typeparams] cmd/compile: add CONVIFACE nodes for return values during noder2
+ 2021-07-23 02c0172500 [dev.typeparams] cmd/compile: add dictionary entries for itab conversion
+ 2021-07-23 12866bd8ea [dev.typeparams] Add CONVIFACE nodes in noder2, where possible
+ 2021-07-23 4cdc65d32a [dev.typeparams] cmd/compile/internal/types: format union types
+ 2021-07-22 244267e8c4 Merge "[dev.typeparams] all: merge master (798ec73) into dev.typeparams" into dev.typeparams
+ 2021-07-22 d8ceb133ca [dev.typeparams] runtime: mark TestGcSys as flaky
+ 2021-07-22 a27e325c59 [dev.typeparams] all: merge master (798ec73) into dev.typeparams
+ 2021-07-22 5cb84f0604 [dev.typeparams] cmd/compile: make sure types added to the dictionary are instantiated correctly
+ 2021-07-22 73162a54c2 [dev.typeparams] cmd/compile: remove outdate TODO in escape analysis
+ 2021-07-22 80127a7dfe [dev.typeparams] cmd/compile/internal/types2: adjust unsafe.Alignof/Offsetof/Sizeof
+ 2021-07-22 fca3e5c445 [dev.typeparams] cmd/compile: fix missing condition in usemethod
+ 2021-07-22 5ba06495c1 [dev.typeparams] go/types: use the TParams API consistently
+ 2021-07-22 6f57139c7a [dev.typeparams] go/types: set type parameter indices when they are bound
+ 2021-07-22 311baf65f4 [dev.typeparams] test: cleanup 'go env' and -goexperiment
+ 2021-07-22 b7149b781f [dev.typeparams] go/types: trigger verification while resolving instance
+ 2021-07-22 61f69d2559 [dev.typeparams] go/types: merge instance and Named to eliminate sanitization
+ 2021-07-22 8e9109e95a [dev.typeparams] Fix problem with 14.go
+ 2021-07-22 ee20dff27d [dev.typeparams] Get dictionaryCapture.go working.
+ 2021-07-21 4e6836e82c [dev.typeparams] Fix the types of the OFUNCINST nodes in noder2
+ 2021-07-21 dcc8350ad3 [dev.typeparams] cmd/compile: handle ++/-- in noder2 for operands with generic type
+ 2021-07-21 f19e49e7b1 [dev.typeparams] cmd/compile: added a builtins.go test, fixed one bug
+ 2021-07-21 e6a2cf233f [dev.typeparams] cmd/compile: get runtime stuff working
+ 2021-07-21 4a97fe8c22 [dev.typeparams] cmd/compile: avoid adding incorrectly instantiated types to the dictionary
+ 2021-07-21 2fe4b14795 [dev.typeparams] cmd/compile: ensure methods of generic types survive linker pruning
+ 2021-07-21 73af5f718f [dev.typeparams] cmd/compile: disable failing generic tests
+ 2021-07-21 a7a17f0ca8 [dev.typeparams] cmd/compile: introduce named gcshape types
+ 2021-07-21 897970688b [dev.typeparams] cmd/compile: cleanup unified IR file format a little
+ 2021-07-21 d5f6ba943c [dev.typeparams] test: add regression test for go/defer wrapper
+ 2021-07-20 6a931673f0 [dev.typeparams] cmd/compile: add base.Assertf{,At} functions
+ 2021-07-20 e4994e71fb [dev.typeparams] all: merge master (c8f4e61) into dev.typeparams
+ 2021-07-19 c6d3d0b0ad [dev.typeparams] go/types: fix the type parameter index in applyTypeFunc
+ 2021-07-19 6bf2667d4e [dev.typeparams] go/types: more consistent handling of predeclared "any"
+ 2021-07-19 7e714f448e [dev.typeparams] go/types: embedding stand-alone type parameters is not permitted
+ 2021-07-19 82f875d735 [dev.typeparams] go/types: fix generic type indirection
+ 2021-07-19 62f6f130fe [dev.typeparams] go/types: interface identity must consider full type set
+ 2021-07-19 baeabf3b36 [dev.typeparams] go/types: cleanups around receiver type checks
+ 2021-07-19 b3d91e3a24 [dev.typeparams] go/types: implement delete(m, k) where m is of type parameter type
+ 2021-07-19 cf7e66b7d4 [dev.typeparams] go/types: implement close(ch) where ch is of type parameter type
+ 2021-07-19 19b4142f24 [dev.typeparams] go/types: implement ch <- x where ch is of type parameter type
+ 2021-07-19 d6d7f8458e [dev.typeparams] go/types: implement <-ch where ch is of type parameter type
+ 2021-07-19 796ac6d5f2 [dev.typeparams] go/types: move methods on *Named into named.go
+ 2021-07-19 22f39ba208 [dev.typeparams] go/types: use InstantiateLazy to create instance types (cleanup)
+ 2021-07-19 4a72be87b3 [dev.typeparams] go/types: move instantiation code to instantiate.go (cleanup)
+ 2021-07-19 41ff0aac13 [dev.typeparams] go/types: replace types2.Instantiate with Checker.Instantiate
+ 2021-07-19 9e147c55b7 [dev.typeparams] go/types: update TypeParam APIs to match types2
+ 2021-07-19 22a38ba5ca [dev.typeparams] go/types: remove unnecessary guard from NewInterfaceType
+ 2021-07-19 b96f1b9419 [dev.typeparams] go/types: add some missing APIs for the importer
+ 2021-07-19 43ad1ffa99 [dev.typeparams] go/types: recursive substitution must terminate (bug fix)
+ 2021-07-19 c7c13ae432 [dev.typeparams] go/types: use scope numbers to identify local types
+ 2021-07-19 ccf95f17dd [dev.typeparams] go/types: support local defined types
+ 2021-07-19 76b39959f4 [dev.typeparams] go/types: don't permit method calls on ptr to type parameter receivers
+ 2021-07-19 9b85985d36 [dev.typeparams] Separate out gcshape types that are instantiated types
+ 2021-07-17 df778e6fd9 [dev.typeparams] go/types: replace optype() with under() in various cases (cleanup)
+ 2021-07-17 e9836fe318 [dev.typeparams] go/types: clean up index expr implementation for type parameters
+ 2021-07-17 c4cd76fbbb [dev.typeparams] go/types: disallow "free" type parameter as RHS of a type declaration
+ 2021-07-16 521828091c [dev.typeparams] go/types: move (remaining) type decls into their own files (cleanup)
+ 2021-07-16 624d152db7 [dev.typeparams] go/types: move Interface type decl into interface.go (cleanup)
+ 2021-07-16 e12d43866d [dev.typeparams] go/types: move Signature type decl into signature.go (cleanup)
+ 2021-07-16 b3e7f23a48 [dev.typeparams] go/types: move Struct type decl into struct.go (cleanup)
+ 2021-07-16 7c35f5c2fc [dev.typeparams] go/types: rename newTypeSet -> computeTypeSet
+ 2021-07-16 de209e693a [dev.typeparams] go/types: make Interface.obj a *TypeName
+ 2021-07-16 0f4198b5e2 [dev.typeparams] go/types: delay interface check for type bounds
+ 2021-07-16 5f50a6442e [dev.typeparams] go/internal/typeparams: remove the Enabled guard
+ 2021-07-16 726ffce659 [dev.typeparams] go/types: "comparable" must not be visible before Go 1.18
+ 2021-07-16 79955155e9 [dev.typeparams] go/types: move newTypeSet function into typeset.go
+ 2021-07-16 fe4f13404d [dev.typeparams] go/types: move embedding positions from Checker to Interface
+ 2021-07-16 b98b8b9b5b [dev.typeparams] go/types: remove unused *Checker arguments (cleanup)
+ 2021-07-16 fce6290e0a [dev.typeparams] go/types: remove typeparams wrappers and aliases
+ 2021-07-16 24f9eb2de3 [dev.typeparams] go/types: introduce type set abstraction for interfaces
+ 2021-07-16 b296e54618 [dev.typeparams] go/types: port lazy import resolution from types2
+ 2021-07-16 10c8b7c1d7 [dev.typeparams] cmd/compile: use dictionary to convert arguments of ==, != to interfaces
+ 2021-07-16 ed9e109dc9 [dev.typeparams] cmd/compile: fix small -G=3 issues for tests disabled in run.go
+ 2021-07-16 3d8453e00e [dev.typeparams] cmd/compile/internal/types2: more consistent handling of predeclared "any"
+ 2021-07-16 334f2fc045 [dev.typeparams] go/*: switch from ListExpr to MultiIndexExpr
+ 2021-07-15 6b85a218b8 [dev.typeparams] cmd/compile: make TestUnifiedCompare insensitive to default -G level
+ 2021-07-14 4ff0e04c2e [dev.typeparams] cmd/compile/internal/types2: embedding stand-alone type parameters is not permitted
+ 2021-07-14 3a047326e8 [dev.typeparams] cmd/compile/internal/types2: fix generic type indirection
+ 2021-07-14 dd8bdf4a1f [dev.typeparams] cmd/compile/internal/types2: interface identity must consider full type set
+ 2021-07-14 2a8087817c [dev.typeparams] cmd/compile/internal/types2: cleanups around receiver type checks
+ 2021-07-14 95f8e64fc0 [dev.typeparams] cmd/compile/internal/types2: implement delete(m, k) where m is of type parameter type
+ 2021-07-14 5f0ea40c67 [dev.typeparams] cmd/compile/internal/types2: implement close(ch) where ch is of type parameter type
+ 2021-07-14 6511922a14 [dev.typeparams] cmd/compile/internal/types2: implement ch <- x where ch is of type parameter type
+ 2021-07-14 ff33d3dc3a [dev.typeparams] cmd/compile/internal/types2: implement <-ch where ch is of type parameter type
+ 2021-07-14 e3e6cd3022 [dev.typeparams] cmd/compile: fix escape printout bugs for -G=3
+ 2021-07-14 2b10d7ff0b [dev.typeparams] go/types: export the Config.GoVersion field
+ 2021-07-14 5517053d17 [dev.typeparams] cmd/compile: record more typ/fun info for dictionaries in unified IR
+ 2021-07-14 82744bfbfc [dev.typeparams] cmd/compile: handle objStub earlier in reader
+ 2021-07-13 e5faa8d84b [dev.typeparams] cmd/compile/internal/types2: move methods on *Named into named.go (cleanup)
+ 2021-07-13 d0324eb8fb [dev.typeparams] cmd/compile/internal/types2: use InstantiateLazy to create instance types (cleanup)
+ 2021-07-13 70f1246a9f [dev.typeparams] cmd/compile/internal/types2: move instantiation code to instantiate.go (cleanup)
+ 2021-07-13 22e9265467 [dev.typeparams] cmd/compile/internal/types2: replace types2.Instantiate with Checker.Instantiate
+ 2021-07-12 1c783dc148 [dev.typeparams] Add optional sub-dict entry for typeparam bound calls
+ 2021-07-11 0dcab98fd8 [dev.typeparams] cmd/compile: slightly more incremental unified typecheck
+ 2021-07-10 3c3c1d8d28 [dev.typeparams] cmd/compile: more incremental typecheck for unified IR
+ 2021-07-10 a12ad27119 [dev.typeparams] cmd/compile: report functions declared in Go and assembly
+ 2021-07-10 5059aed9dd [dev.typeparams] internal/buildcfg: allow regabiwrappers on all GOARCH
+ 2021-07-09 f2ed30c31e [dev.typeparams] cmd/compile/internal/types2: recursive substitution must terminate (bug fix)
+ 2021-07-09 69d945fc6e [dev.typeparams] cmd/compile/internal/types2: use scope numbers to identify local types
+ 2021-07-09 04acb8a7b9 [dev.typeparams] cmd/compile:  report mismatch between types because of //go:notinheap
+ 2021-07-08 2b1d70a137 [dev.typeparams] all: merge master (296ddf2) into dev.typeparams
+ 2021-07-08 42fe132787 [dev.typeparams] cmd/compile: cleanup ABI utils tests
+ 2021-07-08 d4f6d161e4 [dev.typeparams] cmd/compile: fix bunch of -G=3 bugs for test cases in test/typeparams/mdempsky
+ 2021-07-07 18135150b0 [dev.typeparams] cmd/compile/internal/types2: don't permit method calls on ptr to type parameter receivers
+ 2021-07-07 d2bf94fb86 [dev.typeparams] cmd/compile/internal/types2: replace optype() with under() in various cases (cleanup)
+ 2021-07-07 03ec8de24b [dev.typeparams] cmd/compile/internal/types2: clean up index expr implementation for type parameters
+ 2021-07-07 47547d8508 [dev.typeparams] cmd/compile/internal/types2: disallow "free" type parameter as RHS of a type declaration
+ 2021-07-07 60cb2cab97 [dev.typeparams] cmd/compile: fix bug with types2.Instantiate with interface type param
+ 2021-07-07 85267f402c [dev.typeparams] cmd/compile: move def of comparable to end of predeclared slices
+ 2021-07-07 c65ca97a45 [dev.typeparams] cmd/compile: fix windows longtest builder
+ 2021-07-07 501725032c [dev.typeparams] cmd/compile: handle derived types that are converted to interfaces
+ 2021-07-07 b614c05a15 [dev.typeparams] cmd/compile: add built-in name/type "comparable".
+ 2021-07-07 b4844c9f54 [dev.typeparams] cmd/compile: handle the (*T).M method expression with dictionaries
+ 2021-07-07 4676c3675e [dev.typeparams] cmd/compile: rename PartialCallType -> MethodValueType
+ 2021-07-07 5c42b6a953 [dev.typeparams] test: add regress tests that fail(ed) with -G=3
+ 2021-07-07 49ade6b298 [dev.typeparams] test: add expected failure mechanism
+ 2021-07-04 cd00499c61 [dev.typeparams] cmd/compile: better Call constructor
+ 2021-07-04 899b158ee9 [dev.typeparams] cmd/compile: set Func.ClosureCalled in escape analysis
+ 2021-07-03 ea5369bac0 [dev.typeparams] cmd/compile: remove ir.CallUse
+ 2021-07-03 c45d0eaadb [dev.typeparams] cmd/compile: flatten OINLCALL in walk
+ 2021-07-03 ad2ba3ff51 [dev.typeparams] src,cmd: run 'go mod tidy'
+ 2021-07-03 5dac279fbd [dev.typeparams] cmd/compile: formalize "hidden parameters" idea
+ 2021-07-03 611056ec34 Merge "[dev.typeparams] all: merge master (912f075) into dev.typeparams" into dev.typeparams
+ 2021-07-02 ef39edefe1 [dev.typeparams] src,cmd: bump go.mod to 'go 1.18'
+ 2021-07-02 f35d86fd5f [dev.typeparams] all: merge master (912f075) into dev.typeparams
+ 2021-07-02 b994cc69e0 [dev.typeparams] cmd/compile:  separate out creating instantiations from creating dictionaries
+ 2021-07-02 6dec18cc75 [dev.typeparams] cmd/compile: start using sub-dictionary entries where needed
+ 2021-07-02 a18726a648 [dev.typeparams] cmd/compile: incremental typecheck during unified IR
+ 2021-07-02 2aea44204e [dev.typeparams] cmd/compile: enable generics syntax with -lang=go1.18
+ 2021-07-01 30e5f266ed [dev.typeparams] cmd/compile/internal/types2: move (remaining) type decls into their own files (cleanup)
+ 2021-07-01 9c1e7d9eff [dev.typeparams] cmd/compile/internal/types2: move Interface type decl into interface.go (cleanup)
+ 2021-07-01 838079beef [dev.typeparams] cmd/internal/dwarf: remove putInlinedFunc's callersym param
+ 2021-07-01 9ba294e15b [dev.typeparams] cmd/compile: fix getDictionarySym for methods references, write out sub-dictionaries
+ 2021-07-01 0e0b80cb56 [dev.typeparams] cmd/compile/internal/types2: move Signature type decl into signature.go (cleanup)
+ 2021-07-01 1aadb18f83 [dev.typeparams] cmd/compile/internal/types2: move Struct type decl into struct.go (cleanup)
+ 2021-07-01 fac21803ce [dev.typeparams] cmd/compile/internal/types2: rename newTypeSet -> computeTypeSet
+ 2021-07-01 1eb756689c [dev.typeparams] cmd/compile/internal/types2: make Interface.obj a *TypeName
+ 2021-07-01 9cb1b0f50b [dev.typeparams] cmd/compile/internal/types2: delay interface check for type bounds
+ 2021-07-01 1cd505c353 [dev.typeparams] cmd/compile/internal/types2: "comparable" must not be visible before Go 1.18
+ 2021-07-01 706c580ee1 [dev.typeparams] cmd/compile: simplify autotmpname
+ 2021-07-01 372b312735 [dev.typeparams] cmd/compile: refactor top-level typechecking in unified IR
+ 2021-06-30 ad7e5b219e [dev.typeparams] all: merge master (4711bf3) into dev.typeparams
+ 2021-06-30 8767b87ab5 [dev.typeparams] cmd/compile: functions to create GC shape types/names for a concrete type
+ 2021-06-30 b47cbc2ffe [dev.typeparams] cmd/compile/internal/types2: move newTypeSet function into typeset.go
+ 2021-06-30 f0206e3df2 [dev.typeparams] cmd/compile/internal/types2: move embedding positions from Checker to Interface
+ 2021-06-30 1ff43d1b17 [dev.typeparams] cmd/compile/internal/types2: remove unused *Checker arguments (cleanup)
+ 2021-06-30 4b5fdb0b7a [dev.typeparams] cmd/compile/internal/types2: introduce type set abstraction for interfaces
+ 2021-06-30 f503740ccf [dev.typeparams] cmd/compile: add derived-type dictionaries to unified IR
+ 2021-06-29 6a5f7e8498 [dev.typeparams] cmd/compile: use dictionary entries for more conversion cases
+ 2021-06-29 5fa6bbc669 [dev.typeparams] cmd/compile: clean up instantiation and dictionary naming
+ 2021-06-29 dfa8fd861c [dev.typeparams] cmd/compile: add a field (method) name for function in TestABIUtilsInterfaces
+ 2021-06-28 64e6c75924 [dev.typeparams] cmd/compile: port fix for issue46725 to transform.go
+ 2021-06-28 f99b3fe2ab [dev.typeparams] cmd/compile: move MethodValueWrapper to walk
+ 2021-06-28 a8861b907d [dev.typeparams] cmd/compile: port CL 330838 for -G=3
+ 2021-06-27 20a04f6041 [dev.typeparams] cmd/compile: delay method value wrapper generation until walk
+ 2021-06-27 1b995f91a5 [dev.typeparams] cmd/compile: rename OCALLPART to OMETHVALUE
+ 2021-06-27 d44ed5d144 [dev.typeparams] cmd/compile: add method value wrappers to unified IR
+ 2021-06-26 3ea0fcfe15 [dev.typeparams] cmd/compile: do not skip TestUnifiedCompare in short mode
+ 2021-06-26 27e3b797bb [dev.typeparams] cmd/compile: remove OCALLMETH Fatals in SSA generation
+ 2021-06-26 0cf71f7f92 [dev.typeparams] cmd/compile: rewrite method calls during typecheck
+ 2021-06-26 180c338c68 [dev.typeparams] cmd/compile: restore check for OCALLMETH in walkCall
+ 2021-06-26 942bcc2d4f [dev.typeparams] cmd/compile: fix wrong AST generation in devirtualization
+ 2021-06-26 d417b8cf87 [dev.typeparams] cmd/compile: clarify comment about checking reflect.Method in usemethod
+ 2021-06-25 ed647b16d0 [dev.typeparams] cmd/compile: use Type.LinkString for map keys
+ 2021-06-25 942edc7502 [dev.typeparams] cmd/compile: rename types.Type.{Short,Long}String to {Link,Name}String
+ 2021-06-25 373ca3a846 Merge "[dev.typeparams] all: merge master (37f9a8f) into dev.typeparams" into dev.typeparams
+ 2021-06-25 1b60284c0a [dev.typeparams] cmd/compile: simplify variable capturing in unified IR
+ 2021-06-25 9fe7c38d3d [dev.typeparams] cmd/compile: fix TestUnifiedCompare
+ 2021-06-25 f4198f85d5 [dev.typeparams] cmd/compile: generate wrappers within unified IR
+ 2021-06-25 3f1a517a45 [dev.typeparams] cmd/compile: refactor "need to emit" logic for types
+ 2021-06-25 badb98364b [dev.typeparams] cmd/compile: switch CaptureVars to use syntax.Walk
+ 2021-06-25 ac2de11cfb [dev.typeparams] all: merge master (37f9a8f) into dev.typeparams
+ 2021-06-25 2493c72742 [dev.typeparams] cmd/compile: rewrite method call into method expression during escape analysis
+ 2021-06-25 f190a9280d [dev.typeparams] cmd/compile: simplify usemethod
+ 2021-06-25 aee209c044 [dev.typeparams] cmd/compile: catch another mis-used OCALLMETH in backend
+ 2021-06-24 75ad323773 [dev.typeparams] test: skip -G=3 testing under GOEXPERIMENT=unified
+ 2021-06-24 808dca3b2d [dev.typeparams] cmd/compile: suppress liveness diagnostics of wrappers
+ 2021-06-24 ddb09af1b8 [dev.typeparams] cmd/compile:  add derived types and subdictionaries to dictionaries
+ 2021-06-24 df00abc61b [dev.typeparams] cmd/compile: skip escape analysis diagnostics for wrappers
+ 2021-06-24 b55cc6687d [dev.typeparams] cmd/compile: use r.hasTypeParams in typIdx
+ 2021-06-24 9bdbf73c98 [dev.typeparams] cmd/compile: simplify writer.collectDecls
+ 2021-06-23 ee4fc0c1bc [dev.typeparams] Fix issues related to dictionaries and method calls with embedded fields
+ 2021-06-23 8165256bc2 [dev.typeparams] cmd/compile/internal/syntax: go/ast-style walk API
+ 2021-06-23 a72a499c24 [dev.typeparams] cmd/compile: optimize wrapping of constant arguments
+ 2021-06-23 eb691fdd62 [dev.typeparams] cmd/compile: escape analysis of method expression calls
+ 2021-06-23 0a0e3a3dea [dev.typeparams] cmd/compile: move call logic from order.go to escape
+ 2021-06-23 574ec1c645 [dev.typeparams] cmd/compile: desugar ORECOVER into ORECOVERFP
+ 2021-06-23 9be8303df9 [dev.typeparams] cmd/compile: add ORECOVERFP, OGETCALLER{PC,SP} ops
+ 2021-06-23 70f4ab6565 [dev.typeparams] cmd/compile: remove SetClosureCalled(false) hacks
+ 2021-06-23 107b1fce64 [dev.typeparams] cmd/compile: explain why expandInline needed
+ 2021-06-23 99732b9070 [dev.typeparams] cmd/compile: refactor escape analysis of calls
+ 2021-06-23 1a445dab66 [dev.typeparams] cmd/compile: remove CallExpr.PreserveClosure
+ 2021-06-23 e59a19cceb [dev.typeparams] cmd/compile: simplify walkGoDefer
+ 2021-06-23 493e177639 [dev.typeparams] cmd/compile: allow typecheck of OCHECKNIL
+ 2021-06-23 c4e0c652fb [dev.typeparams] cmd/compile: refactor CaptureName
+ 2021-06-22 62095c66e0 [dev.typeparams] go/types: adjust logic for method expression arg naming
+ 2021-06-22 541612b974 [dev.typeparams] cmd/gofmt: remove typeparams guards
+ 2021-06-22 3e6219c6a9 [dev.typeparams] cmd/compile: split package escape into multiple files
+ 2021-06-22 077100dfcd [dev.typeparams] cmd/compile: remove special escape analysis tags
+ 2021-06-22 859d903b06 [dev.typeparams] cmd/compile: add -d=unifiedquirks for quirks mode
+ 2021-06-22 d626ba27bb [dev.typeparams] all: merge master (16e82be) into dev.typeparams
+ 2021-06-21 844c076359 [dev.typeparams] cmd/compile: simplify import* functions
+ 2021-06-21 e57da8e53c [dev.typeparams] cmd/compile: explain why reader.funcExt need to set n.Defn
+ 2021-06-21 3f7f72a258 [dev.typeparams] cmd/compile: fold reader checking type params logic to separate method
+ 2021-06-20 d24c90a153 [dev.typeparams] cmd/compile: explain how pkgReader.typIdx handles alias cyclic
+ 2021-06-18 3f7a3133da [dev.typeparams] cmd/compile: add "toolstash -cmp"-like test of -d=unified
+ 2021-06-18 e9c01f9804 [dev.typeparams] cmd/compile: add missing copy of Field.Embedded in type substituter.
+ 2021-06-18 6fa0437958 [dev.typeparams] cmd/compile: add documentation for unified IR pipeline
+ 2021-06-18 54fe57bc22 [dev.typeparams] cmd/compile: record writer's stack at export data sync points
+ 2021-06-18 78aa251ace [dev.typeparams] cmd/go: include new internal packages in TestNewReleaseRebuildsStalePackagesInGOPATH
+ 2021-06-18 2a7900762c [dev.typeparams] go/types: report better error for invalid untyped operation
+ 2021-06-18 90096f445e [dev.typeparams] cmd/compile/internal/syntax: convert (most) parser tests to new type set syntax
+ 2021-06-17 feec53c4e5 [dev.typeparams] cmd/compile: skip types2 GC test during bootstrapping
+ 2021-06-17 fb84d213a8 [dev.typeparams] reflect: support big endian architectures in callMethod
+ 2021-06-17 9f50d9a0b4 [dev.typeparams] internal/reflectlite: remove unused ptrSize
+ 2021-06-17 890a8407a9 [dev.typeparams] internal/reflectlite: use goarch.PtrSize instead of the duplicated ptrSize [generated]
+ 2021-06-17 bfd9b63f12 [dev.typeparams] reflect: delete unused ptrSize and PtrSize
+ 2021-06-17 95c104ee61 [dev.typeparams] reflect: use goarch.PtrSize instead of the duplicated ptrSize [generated]
+ 2021-06-17 2e600fb8b3 [dev.typeparams] runtime/internal/sys: remove unused Goarch* and Goos* constants
+ 2021-06-17 46e1e74a86 [dev.typeparams] runtime: replace Goarch* constants with internal/goarch versions [generated]
+ 2021-06-17 7b0e9cae66 [dev.typeparams] runtime: replace Goos* constants with internal/goos versions [generated]
+ 2021-06-17 81a6a4354b [dev.typeparams] internal/goarch,internal/goos: rename Goos and Goarch constants
+ 2021-06-17 33d1b82d16 [dev.typeparams] runtime/internal/sys: replace ArchFamily and constants with goarch
+ 2021-06-17 85b12a8563 [dev.typeparams] runtime,runtime/internal/sys: remove unused BigEndian
+ 2021-06-17 9a93072a07 [dev.typeparams] runtime/internal/sys: replace BigEndian with goarch.BigEndian [generated]
+ 2021-06-17 9c58e399a4 [dev.typeparams] runtime: fix import sort order [generated]
+ 2021-06-17 671954e72e [dev.typeparams] runtime/internal/sys: replace GOOS with goos.GOOS
+ 2021-06-17 5c028751bd [dev.typeparams] runtime/internal/sys: replace uses of GOARCH with goarch.GOARCH
+ 2021-06-17 6d89c90fb1 [dev.typeparams] runtime/internal/sys: remove unused PtrSize
+ 2021-06-17 6d85891b29 [dev.typeparams] runtime: replace uses of runtime/internal/sys.PtrSize with internal/goarch.PtrSize [generated]
+ 2021-06-17 122f5e16d6 [dev.typeparams] internal/goarch,internal/goos: explode runtime/internal/sys into pieces
+ 2021-06-17 804ecc2581 [dev.typeparams] all: add GOEXPERIMENT=unified knob
+ 2021-06-17 b14fd720a8 [dev.typeparams] cmd/compile: make types2 report better error for invalid untyped operation
+ 2021-06-17 8115ae198d [dev.typeparams] go/types: disallow ~T where T is a defined type or an interface
+ 2021-06-17 6237e441bc [dev.typeparams] go/types: disallow type list handling
+ 2021-06-17 6e50f4f111 [dev.typeparams] go/types: convert testdata/check tests to type set syntax
+ 2021-06-17 b6fc4d01a8 [dev.typeparams] go/types: convert testdata/fixedbugs tests to type set sytax
+ 2021-06-17 795f4475e5 [dev.typeparams] go/types: convert testdata/examples tests to type set sytax
+ 2021-06-17 8e14a9cf04 [dev.typeparams] go/types: eliminate need for unpack and asUnion functions
+ 2021-06-17 aecfd5c29e [dev.typeparams] go/types: clean up type set/union intersection
+ 2021-06-17 c7a460526e [dev.typeparams] go/types: replace Sum type with Union type
+ 2021-06-17 e7451f6616 [dev.typeparams] go/types: accept embedded interface elements
+ 2021-06-17 54f854fb41 [dev.typeparams] go/parser: accept embedded type literals
+ 2021-06-17 ab4b3c4b15 [dev.typeparams] go/parser: accept "~" and "|" interface elements
+ 2021-06-17 7c5d7a4caf [dev.typeparams] go/token, go/scanner: add the "~" operator
+ 2021-06-17 ad59efb027 [dev.typeparams] go/ast: remove the typeparams build constraint
+ 2021-06-16 1ba2074440 [dev.typeparams] cmd/compile/internal/types2: support local defined types
+ 2021-06-16 dd95a4e3db [dev.typeparams] cmd/compile: simplify SSA devirtualization
+ 2021-06-16 132ea56d29 [dev.typeparams] cmd/compile: fix crawling of embeddable types
+ 2021-06-16 8f95eaddd3 [dev.typeparams] cmd/compile: fix missing sync implicit types
+ 2021-06-16 a4121d7dd6 [dev.typeparams] Revert "[dev.typeparams] runtime: make deferproc take a func() argument"
+ 2021-06-16 4d6f9d60cf [dev.typeparams] all: merge master (785a8f6) into dev.typeparams
+ 2021-06-16 ee0420d3b5 [dev.typeparams] cmd/compile: factor out implicit/explicit handling
+ 2021-06-15 cf1ae5fc36 [dev.typeparams] cmd/compile: add -d=unified flag to enable unified IR
+ 2021-06-15 79cd1687e6 [dev.typeparams] cmd/compile: unified IR construction
+ 2021-06-14 ea438bda85 [dev.typeparams] all: merge master (fdab5be) into dev.typeparams
+ 2021-06-13 8eeaf961c5 [dev.typeparams] cmd/compile: move //go:embed -lang check to noder
+ 2021-06-12 f1b1c2f67f [dev.typeparams] cmd/compile: simplify NewClosureFunc
+ 2021-06-12 db7c868307 [dev.typeparams] test: add string quoting support to test/run.go
+ 2021-06-12 0132b91127 [dev.typeparams] cmd/compile: refactor closure construction
+ 2021-06-12 8f00eb0099 [dev.typeparams] cmd/compile: avoid ir.DeepCopy in noder.constDecl
+ 2021-06-12 2954f11ead [dev.typeparams] cmd/compile: scaffolding for export data experiments
+ 2021-06-11 c93d5d1a52 [dev.typeparams] all: always enable regabig on AMD64
+ 2021-06-11 2fe324858b [dev.typeparams] internal/buildcfg: always enable regabiwrappers on AMD64
+ 2021-06-11 e0e9fb8aff [dev.typeparams] runtime: simplify defer record allocation
+ 2021-06-11 4468e1cfb9 [dev.typeparams] runtime: allow newproc split stack
+ 2021-06-11 ef6c5be160 [dev.typeparams] cmd/compile: fix wrapper generation for imported generics
+ 2021-06-11 4a735ce068 [dev.typeparams] cmd/compile: add "check" field to noder.gcimports
+ 2021-06-11 61888d47c4 [dev.typeparams] cmd/compile: allow embedding Type.Vargen into Sym.Name
+ 2021-06-11 62e32dd386 [dev.typeparams] cmd/compile: extract SetBaseTypeIndex function
+ 2021-06-11 18788245ea [dev.typeparams] cmd/compile: add ir.TypeNodeAt
+ 2021-06-09 b20747334a [dev.typeparams] cmd/compile, runtime: simplify opendefer metadata
+ 2021-06-09 c0a86c10f1 [dev.typeparams] cmd/compile: simplify openDeferSave
+ 2021-06-08 74b0b2772a [dev.typeparams] cmd/compile, runtime: remove _defer.siz field
+ 2021-06-08 b80a4c56f0 [dev.typeparams] runtime: allow deferproc split stack
+ 2021-06-08 83da32749c [dev.typeparams] runtime: make deferproc take a func() argument
+ 2021-06-08 8e5304f729 [dev.typeparams] cmd/compile, runtime: remove the siz argument of newproc/deferproc
+ 2021-06-08 00d01b5786 [dev.typeparams] runtime: remove tracebackdefers
+ 2021-06-08 12b37b713f [dev.typeparams] runtime: remove variadic defer/go calls
+ 2021-06-08 5b350505da [dev.typeparams] cmd/compile: remove variadic defer calls
+ 2021-06-08 a9de78ac88 [dev.typeparams] cmd/compile, runtime: always enable defer/go wrapping
+ 2021-06-08 e58bddde70 [dev.typeparams] internal/goexperiment: regenerate generated files
+ 2021-06-08 0c40cb4a07 [dev.typeparams] cmd/compile/internal/types2: provide valid signature in errors involving method expressions
+ 2021-06-07 74d46381b2 [dev.typeparams] cmd/compile: do extra markObjects during iexport to deal with generics
+ 2021-06-07 ccfb0ce8df [dev.typeparams] cmd/compile: convert generic values to interface type using dictionary
+ 2021-06-07 cf4b6dc48e [dev.typeparams] cmd/compile: allow conversions from type parameter to interface
+ 2021-06-07 bcb3927cb5 [dev.typeparams] cmd/compile: introduce IsTypeParam() helper
+ 2021-06-07 f0c97219a3 Merge "[dev.typeparams] all: merge master (8212707) into dev.typeparams" into dev.typeparams
+ 2021-06-07 201d55e637 [dev.typeparams] cmd/compile: create .dict Param in the package of the instantiated function
+ 2021-06-07 0e39cdc0e9 [dev.typeparams] all: merge master (8212707) into dev.typeparams
+ 2021-06-07 7c8a5be2d6 [dev.typeparams] go/types: factor out constraint satisfaction check
+ 2021-06-07 7497e57a39 [dev.typeparams] go/types: simplify Interface accessors
+ 2021-06-07 2f26adc232 [dev.typeparams] go/types: re-use existing code for Interface.Complete
+ 2021-06-07 1395952075 [dev.typeparams] go/types: add Named.SetTParams and Named.Orig methods
+ 2021-06-07 991dca0112 [dev.typeparams] go/types: move signature checking into separate file
+ 2021-06-06 c23294d6b3 [dev.typeparams] cmd/compile/internal/types2: return Universe for ((*Package)(nil)).Scope()
+ 2021-06-05 a5be3eaee2 [dev.typeparams] cmd/compile: refactor export writing
+ 2021-06-05 4c072c94dc [dev.typeparams] cmd/compile: refactor import reading
+ 2021-06-05 4e001a8d9e [dev.typeparams] runtime/race: make test compatible with types2
+ 2021-06-05 246a5570be [dev.typeparams] cmd/compile: rename (types2.Inferred.)Targs to TArgs
+ 2021-06-05 692399fbaa [dev.typeparams] cmd/compile/internal/syntax: not all index expressions can be instantiated types
+ 2021-06-04 a94e4f5a85 [dev.typeparams] cmd/compile: point StructKeyExpr at the types.Field
+ 2021-06-04 bad388744b [dev.typeparams] cmd/compile: handle dictionaries for top-level instantiations
+ 2021-06-04 de61465156 [dev.typeparams] cmd/compile: allow inlining in instantiated functions
+ 2021-06-04 4cf7f5f694 [dev.typeparams] test: test regabidefers in live.go
+ 2021-06-04 3298c749ac [dev.typeparams] runtime: undo go'd closure argument workaround
+ 2021-06-04 46beeed0ac [dev.typeparams] cmd/compile: allow go'd closure to escape when compiling runtime
+ 2021-06-04 8e6dfe1b31 [dev.typeparams] cmd/compile: export/import of recursive generic types.
+ 2021-06-04 93a886a165 [dev.typeparams] go/types: move struct checking into separate file
+ 2021-06-04 ffc74ad5d3 [dev.typeparams] go/types: move interface checking into separate file
+ 2021-06-04 090a17c998 [dev.typeparams] go/types: use correct type parameter list in missingMethod
+ 2021-06-04 62c40878e4 [dev.typeparams] go/types: better recv Var for method expressions
+ 2021-06-04 e32fab145b [dev.typeparams] go/types: fix panic with nil package name
+ 2021-06-04 cd6e9df446 [dev.typeparams] go/types: print "incomplete" for interfaces in debug mode only
+ 2021-06-04 655246f99a [dev.typeparams] go/types: make TestManual work for directories
+ 2021-06-04 d7592ab424 [dev.typeparams] go/types: implement types.Instantiate
+ 2021-06-04 410fa4c75b [dev.typeparams] go/types: rename Inferred.Targs to TArgs
+ 2021-06-04 298149a915 [dev.typeparams] go/types: use Checker-provided type parameter IDs when possible
+ 2021-06-04 2175e2f573 [dev.typeparams] cmd/compile: lazy import resolution for types2
+ 2021-06-03 4d2b528795 [dev.typeparams] internal/buildcfg: turn on register ABI by default on ARM64
+ 2021-06-03 5f034f9b46 [dev.typeparams] internal/buildcfg: turn on regabireflect by default on ARM64
+ 2021-06-03 026480d06b [dev.typeparams] cmd/compile: allow nil Syms in Sym.Less
+ 2021-06-03 a2d6a2caeb [dev.typeparams] internal/buildcfg: turn on regabiwrappers by default on ARM64
+ 2021-06-03 55b4310acd [dev.typeparams] runtime: crash the GC at clobberdead pointer on ARM64
+ 2021-06-03 6b1e4430bb [dev.typeparams] cmd/compile: implement clobberdead mode on ARM64
+ 2021-06-03 1c947e4f31 [dev.typeparams] cmd/compile: properly copy tilde value for unions in types2-to-types1 conversion
+ 2021-06-03 e9ba0750b6 [dev.typeparams] reflect: guard abi_test.go with regabiargs build tag
+ 2021-06-03 28bd325e41 [dev.typeparams] runtime: use ABIInternal callbackWrap in callbackasm1 on ARM64
+ 2021-06-03 3de4986852 [dev.typeparams] runtime: call cgocallbackg indirectly on ARM64
+ 2021-06-03 5a40fab19f [dev.typeparams] runtime, internal/bytealg: port performance-critical functions to register ABI on ARM64
+ 2021-06-03 370ff5ff96 [dev.typeparams] test: update all the typeparam tests to use the new union/tilde syntax
+ 2021-06-03 5a008a92e8 [dev.typeparams] internal/bytealg: call memeqbody directly in memequal_varlen on ARM64
+ 2021-06-03 165d39a1d4 [dev.typeparams] test: adjust codegen test for register ABI on ARM64
+ 2021-06-03 b5f37faf3b [dev.typeparams] cmd/internal/goobj: add duffzero/duffcopy to builtin list
+ 2021-06-03 9c054f4137 [dev.typeparams] cmd/link: take function address in assembly in TestFuncAlign
+ 2021-06-03 95c618e99a [dev.typeparams] cmd/compile/internal/types2: add Config.AllowTypeLists to control type list handling
+ 2021-06-03 10d6b36ca3 [dev.typeparams] cmd/compile/internal/types2: disallow ~T where T is a defined type or an interface
+ 2021-06-02 8cdce85bdf [dev.typeparams] cmd/compile/internal/types2: convert testdata/check tests to type set sytax
+ 2021-06-02 c790964ae4 [dev.typeparams] cmd/compile/internal/types2: convert testdata/fixedbugs tests to type set sytax
+ 2021-06-02 9a99e728fe [dev.typeparams] cmd/compile/internal/types2: convert testdata/examples tests to type set sytax
+ 2021-06-02 d36b7d7bdd [dev.typeparams] cmd/compile/internal/importer: review of gcimporter_test.go
+ 2021-06-02 3c1d502a19 [dev.typeparams] cmd/compile/internal/types2: eliminate need for unpack and asUnion functions
+ 2021-06-02 848b58e473 [dev.typeparams] cmd/compile/internal/types2: clean up type set/union intersection
+ 2021-06-02 97cb0113a3 [dev.typeparams] cmd/compile: fix export/import of constants with typeparam type
+ 2021-06-02 6b1cdeaef3 [dev.typeparams] cmd/link: include "go build" output in test logs
+ 2021-06-02 c7b9811581 [dev.typeparams] cmd/compile/internal/importer: review of gcimporter.go
+ 2021-06-02 498a48327f [dev.typeparams] cmd/compile: sort iface fields before expansion
+ 2021-06-02 cc52fdd1f3 [dev.typeparams] cmd/compile/internal/importer: review of exportdata.go
+ 2021-06-02 8c5c5a9e69 [dev.typeparams] cmd/compile/internal/importer: review of support.go
+ 2021-06-02 589e32dbdf [dev.typeparams] cmd/compile/internal/types2: replace Sum type with Union type
+ 2021-06-02 7b876def6c [dev.typeparams] cmd/compile: add dictionary argument to generic functions
+ 2021-06-02 aa9cfdf775 [dev.typeparams] runtime: update ABIInternal assembly with register ABI on ARM64
+ 2021-06-02 0c123cdf8b [dev.typeparams] reflect: implement register ABI for MakeFunc etc. on ARM64
+ 2021-06-02 2e4b79949f [dev.typeparams] runtime: implement register ABI for reflectcall on ARM64
+ 2021-06-02 dc2cb529a8 [dev.typeparams] runtime: mark assembly functions called directly from compiler ABIInternal
+ 2021-06-02 d2b435117d test: fix error check messages for 2 types2 tests
+ 2021-06-02 b1f48e8add [dev.typeparams] cmd/compile: fix formatting
+ 2021-06-01 58ad36b359 [dev.typeparams] internal/buildcfg: allow regabi GOEXPERIMENTs on ARM64
+ 2021-06-01 c3639918d1 [dev.typeparams] internal/abi: define ARM64 register ABI constants
+ 2021-06-01 6633dc8b09 [dev.typeparams] reflect: call ABI0 spill/unspill functions on AMD64
+ 2021-06-01 e4003463ff [dev.typeparams] cmd/compile: match register-ABI version of memmove call on ARM64
+ 2021-06-01 8e7abefdaa [dev.typeparams] cmd/compile: update ARM64 CALL* ops for register ABI
+ 2021-06-01 c9d1a2bdd2 [dev.typeparams] all: merge master (2725522) into dev.typeparams
+ 2021-06-01 2580e9a160 [dev.typeparams] cmd/compile: refactor noder/irgen helpers
+ 2021-06-01 4b10e4c547 [dev.typeparams] cmd/compile: handle ONONAME in subster.node
+ 2021-05-31 f32f4f58d9 [dev.typeparams] cmd/compile: simplify formatting of defined types
+ 2021-05-27 22f5ece3b1 [dev.typeparams] cmd/compile/internal/noder: refactor irgen import handling
+ 2021-05-27 417955d151 [dev.typeparams] cmd/compile/internal/inline: refactor mkinlcall
+ 2021-05-27 88583a2a66 [dev.typeparams] test: trim list of expected -G=3 failures
+ 2021-05-27 ea522bc546 [dev.typeparams] cmd/compile: add and use ir.RawOrigExpr
+ 2021-05-27 de5d1aca5e [dev.typeparams] cmd/compile: tweaks to match types2
+ 2021-05-27 c2c1b53b39 [dev.typeparams] cmd/compile: use old export format if not compiling with generics
+ 2021-05-27 8c99e5db43 [dev.typeparams] cmd/compile/internal/types2: ensure that Named.check is nilled out once it is expanded
+ 2021-05-27 963f33b03b [dev.typeparams] cmd/compile: enable register args on ARM64
+ 2021-05-27 06df0ee7fa [dev.typeparams] cmd/compile: add arg/result register load/spill code on ARM64
+ 2021-05-26 1ec056244e [dev.typeparams] cmd/compile: inlining tweaks for toolstash
+ 2021-05-26 6da1661371 [dev.typeparams] cmd/compile: simplify inlining variadic calls
+ 2021-05-26 e99e9a6e01 [dev.typeparams] cmd/compile: simplify ~r/~b naming
+ 2021-05-26 4c68edd1fe [dev.typeparams] cmd/compile: add morestack arg spilling code on ARM64
+ 2021-05-26 a4b2a04bc5 [dev.typeparams] cmd/internal/obj/arm64: use ABI-compatible registers in function prologue
+ 2021-05-26 4bb927f82e [dev.typeparams] cmd/compile: define ARM64 parameter registers
+ 2021-05-26 cf23daeda3 [dev.typeparams] cmd/compile: do not schedule in-register args late, even for block control
+ 2021-05-26 4ed6317e73 [dev.typeparams] cmd/compile: always generate (*T).M wrappers for instantiated methods
+ 2021-05-26 b7f7d1cd7b [dev.typeparams] cmd/compile:  get type aliases working with generic types
+ 2021-05-26 95748d1b74 [dev.typeparams] cmd/compile: avoid some redundant type construction
+ 2021-05-26 fd54ae8b0c [dev.typeparams] cmd/compile: adding union support in types1
+ 2021-05-25 6c9e1c58bc [dev.typeparams] test: fix and update run.go's generics testing
+ 2021-05-25 5c1e119d48 [dev.typeparams] all: merge master (f22ec51) into dev.typeparams
+ 2021-05-24 155dc0e541 [dev.typeparams] cmd/compile/internal/types2: factor out constraint satisfaction check
+ 2021-05-24 5770d7a637 [dev.typeparams] cmd/compile/internal/types2: accept embedded interface elements
+ 2021-05-24 cc7ceea585 [dev.typeparams] cmd/compile/internal/types2: simplify Interface accessors
+ 2021-05-24 1608577e05 [dev.typeparams] cmd/compile/internal/types2: re-use existing code for Interface.Complete
+ 2021-05-24 d48f6d9f6f [dev.typeparams] Don't check typecheck(3) on transform, so no need to export/import it
+ 2021-05-24 4c50721cda [dev.typeparams] cmd/compile:  Fix handling of Name nodes during stenciling
+ 2021-05-24 dcaf785add [dev.typeparams] internal/buildcfg: enable defer/go wrapping everywhere
+ 2021-05-24 f642742678 [dev.typeparams] reflect: use internal/abi.FuncPCABI0 to take address of assembly functions
+ 2021-05-24 e0844acfc8 [dev.typeparams] runtime/pprof: replace funcPC with internal/abi.FuncPCABIInternal
+ 2021-05-24 ae26b45113 [dev.typeparams] cmd/compile/abi-internal.md: specify ARM64 register-based ABI
+ 2021-05-24 b18b2d372e [dev.typeparams] cmd/compile:  fix case where we were copying a raw Node
+ 2021-05-21 5b1120fac7 [dev.typeparams] cmd/compile: fix handling of Nname field in (*subster).tstruct.
+ 2021-05-21 8d2b4cb6cc [dev.typeparams] cmd/compile: fixing import of comm clauses/closures in generic functions
+ 2021-05-21 626e89c261 [dev.typeparams] runtime: replace funcPC with internal/abi.FuncPCABIInternal
+ 2021-05-21 6a81e063dd [dev.typeparams] runtime: fix misuse of funcPC
+ 2021-05-21 7d928460a1 [dev.typeparams] runtime: use internal/abi.FuncPCABI0 to reference ABI0 assembly symbols
+ 2021-05-21 0e0a1f94f3 [dev.typeparams] runtime: use ABI0 handler addresses on Windows/ARM64
+ 2021-05-21 fb42fb705d [dev.typeparams] runtime: use internal/abi.FuncPCABI0 to take address of assembly functions
+ 2021-05-21 21db1d193c [dev.typeparams] runtime: fix newproc arg size on ARM
+ 2021-05-21 b1a398cf0f [dev.typeparams] cmd/compile:  add import/export of calls to builtin functions
+ 2021-05-21 ccbfbb1c33 [dev.typeparams] cmd/compile: export OFUNCINST and OSELRECV2 nodes (for generic functions)
+ 2021-05-21 243076da64 [dev.typeparams] cmd/compile/internal/types2: move signature checking into separate file
+ 2021-05-21 cfe0250497 [dev.typeparams] cmd/compile/internal/types2: move struct checking into separate file
+ 2021-05-21 211244e172 [dev.typeparams] cmd/compile/internal/types2: move interface checking into separate file
+ 2021-05-21 7b3ee6102d [dev.typeparams] cmd/compile: move to new export version, keep reading previous version
+ 2021-05-21 15ad61aff5 [dev.typeparams] cmd/compile: get export/import of generic types & functions working
+ 2021-05-20 468efd5e2f [dev.typeparams] cmd/compile:  change method instantiations back to being functions
+ 2021-05-20 382c5dd5f7 [dev.typeparams] internal/buildcfg: turn on register ABI on all AMD64 platforms
+ 2021-05-20 240d6d00ca [dev.typeparams] cmd/link: mangle symbol ABI name on Plan 9
+ 2021-05-20 ed2001232a [dev.typeparams] runtime: use internal/abi.FuncPCABI0 for sigtramp PC on Plan 9
+ 2021-05-20 02117775d1 [dev.typeparams] cmd/compile, runtime: do not zero X15 on Plan 9
+ 2021-05-20 a5cd89b8c3 [dev.typeparams] runtime: use internal/abi.FuncPCABI0 and cgo_unsafe_args for Solaris syscall wrappers
+ 2021-05-19 6bdfff112f [dev.typeparams] cmd/compile/internal/types2: use correct type parameter list in missingMethod
+ 2021-05-19 eff66248ea [dev.typeparams] cmd/compile/internal/types2: implement package height
+ 2021-05-19 3f6f12972b [dev.typeparams] runtime: use internal/abi.FuncPCABI0 for sigtramp PC on DragonflyBSD
+ 2021-05-19 b69347d24a [dev.typeparams] cmd/compile: simplify tparam's type
+ 2021-05-19 701bd60646 [dev.typeparams] cmd/compile: simplify targ's type
+ 2021-05-19 c2966ae272 [dev.typeparams] cmd/compile/internal/ir: more position details in dump
+ 2021-05-19 fb79f6955e [dev.typeparams] cmd/compile/internal/importer: implement position reading
+ 2021-05-19 c92ae885d9 [dev.typeparams] cmd/compile/internal/types2: better recv Var for method expressions
+ 2021-05-19 90b6e72605 [dev.typeparams] cmd/compile/internal/types2: tweak anonymous parameter position
+ 2021-05-19 fc9e64cc98 [dev.typeparams] cmd/compile/internal/types2: fix types2 panic
+ 2021-05-19 c81562d99f [dev.typeparams] test: update regress tests for types2
+ 2021-05-19 81b22480cf [dev.typeparams] cmd/compile/internal/syntax: accept embedded type literals
+ 2021-05-18 f3fc8b5779 [dev.typeparams] cmd/compile: simplify type alias handling for export
+ 2021-05-18 140cd7c1d3 [dev.typeparams] runtime: use internal/abi.FuncPCABI0 for syscall wrappers on OpenBSD
+ 2021-05-18 bbc0059b03 [dev.typeparams] test: run more tests with -G=3
+ 2021-05-18 f208f1ac99 [dev.typeparams] cmd/compile/internal/ir: more useful Fatalfs
+ 2021-05-18 c7dd3e305d [dev.typeparams] all: merge master (690a8c3) into dev.typeparams
+ 2021-05-18 077f03f4d8 [dev.typeparams] runtime: use internal/abi.FuncPCABI0 for sigtramp PC on FreeBSD
+ 2021-05-17 f39200b037 [dev.typeparams] go/constant: implement Kind.String
+ 2021-05-14 0d1e293b23 [dev.typeparams] cmd/compile/internal/types2: print "incomplete" for interfaces in debug mode only
+ 2021-05-14 03ed590e51 [dev.typeparams] cmd/compile/internal/types2: use Checker-provided type parameter IDs when possible
+ 2021-05-13 c3fa51c9a2 cmd/compile: changed representation of typeparam bound in types1
+ 2021-05-13 9daf3cca82 [dev.typeparams] cmd/compile:  keep instantiated method as a method, rather than converting to function
+ 2021-05-12 04f65d394c [dev.typeparams] cmd/compile:  fix use of method values with stenciled methods
+ 2021-05-11 d2b3efcb90 [dev.typeparams] all: merge master (9b84814) into dev.typeparams

Change-Id: Idedf034141b432e69a19b076dcc10c2923f3ee7d
This commit is contained in:
Michael Matloob
2021-08-24 17:24:19 -04:00
1159 changed files with 42211 additions and 20379 deletions

View File

@@ -33,6 +33,7 @@ Aaron Jacobs <jacobsa@google.com>
Aaron Jensen <jensen.aaro@gmail.com>
Aaron Kemp <kemp.aaron@gmail.com>
Aaron Patterson <tenderlove@ruby-lang.org>
Aaron Sheah <aaronsheah@gmail.com>
Aaron Stein <aaronstein12@gmail.com>
Aaron Torres <tcboox@gmail.com>
Aaron Zinman <aaron@azinman.com>
@@ -47,6 +48,7 @@ Adam Harvey <aharvey@php.net>
Adam Kisala <adam.kisala@gmail.com>
Adam Langley <agl@golang.org>
Adam Medzinski <adam.medzinski@gmail.com>
Adam Mitha <adam.mitha@gmail.com>
Adam Shannon <adamkshannon@gmail.com>
Adam Shelton <aashelt90@gmail.com>
Adam Sindelar <adamsh@google.com>
@@ -54,6 +56,8 @@ Adam Thomason <athomason@gmail.com>
Adam Williams <pwnfactory@gmail.com>
Adam Woodbeck <adam@woodbeck.net>
Adarsh Ravichandran <adarshravichandran91@gmail.com>
Adel Rodríguez <adel.rodriguez@leftfieldlabs.com>
Adin Scannell <ascannell@google.com>
Aditya Harindar <aditya.harindar@gmail.com>
Aditya Mukerjee <dev@chimeracoder.net>
Adrian Hesketh <adrianhesketh@hushmail.com>
@@ -68,6 +72,7 @@ Afanasev Stanislav <phpprogger@gmail.com>
Agis Anastasopoulos <agis.anast@gmail.com>
Agniva De Sarker <agnivade@yahoo.co.in>
Ahmed W. Mones <oneofone@gmail.com>
Ahmet Aktürk <aakturk000@gmail.com>
Ahmet Alp Balkan <ahmetb@google.com>
Ahmet Soormally <ahmet@mangomm.co.uk>
Ahmy Yulrizka <yulrizka@gmail.com>
@@ -92,11 +97,13 @@ Alberto Bertogli <albertito@blitiri.com.ar>
Alberto Donizetti <alb.donizetti@gmail.com>
Alberto García Hierro <alberto@garciahierro.com> <alberto.garcia.hierro@gmail.com>
Alec Benzer <alec.benzer@gmail.com>
Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
Aleksa Sarai <cyphar@cyphar.com>
Aleksandar Dezelin <dezelin@gmail.com>
Aleksandr Lukinykh <a.lukinykh@xsolla.com>
Aleksandr Razumov <ar@cydev.ru>
Alekseev Artem <a.artem060@gmail.com>
Aleksei Tirman <aleksei.tirman@jetbrains.com>
Alessandro Arzilli <alessandro.arzilli@gmail.com>
Alessandro Baffa <alessandro.baffa@gmail.com>
Alex A Skinner <alex@lx.lc>
@@ -165,6 +172,7 @@ Ali Rizvi-Santiago <arizvisa@gmail.com>
Aliaksandr Valialkin <valyala@gmail.com>
Alice Merrick <amerrick@google.com>
Alif Rachmawadi <subosito@gmail.com>
Allan Guwatudde <guwats10@gmail.com>
Allan Simon <allan.simon@supinfo.com>
Allen Li <ayatane@google.com>
Alok Menghrajani <alok.menghrajani@gmail.com>
@@ -172,6 +180,7 @@ Alwin Doss <alwindoss84@gmail.com>
Aman Gupta <aman@tmm1.net>
Amarjeet Anand <amarjeetanandsingh@gmail.com>
Amir Mohammad Saied <amir@gluegadget.com>
Amit Kumar <mittalmailbox@gmail.com>
Amr Mohammed <merodiro@gmail.com>
Amrut Joshi <amrut.joshi@gmail.com>
An Long <aisk1988@gmail.com>
@@ -185,6 +194,7 @@ André Carvalho <asantostc@gmail.com>
André Martins <aanm90@gmail.com>
Andre Nathan <andrenth@gmail.com>
Andrea Nodari <andrea.nodari91@gmail.com>
Andrea Simonini <andrea.simonini@gmail.com>
Andrea Spadaccini <spadaccio@google.com>
Andreas Auernhammer <aead@mail.de>
Andreas Jellinghaus <andreas@ionisiert.de> <anj@google.com>
@@ -244,6 +254,7 @@ Andy Pan <panjf2000@gmail.com> <panjf2000@golangcn.org> <i@andypan.me>
Andy Walker <walkeraj@gmail.com>
Andy Wang <cbeuw.andy@gmail.com>
Andy Williams <andy@andy.xyz>
Andy Zhao <andyzhao@google.com>
Andzej Maciusovic <andzej.maciusovic@gmail.com>
Anfernee Yongkun Gui <anfernee.gui@gmail.com>
Angelo Bulfone <mbulfone@gmail.com>
@@ -269,6 +280,7 @@ Anton Kuklin <anton.a.kuklin@gmail.com>
Antonin Amand <antonin.amand@gmail.com>
Antonio Antelo <aantelov87@gmail.com>
Antonio Bibiano <antbbn@gmail.com>
Antonio Garcia <garcia.olais@gmail.com>
Antonio Huete Jimenez <tuxillo@quantumachine.net>
Antonio Murdaca <runcom@redhat.com>
Antonio Troina <thoeni@gmail.com>
@@ -292,8 +304,10 @@ Artem Khvastunov <artem.khvastunov@jetbrains.com>
Artem Kolin <artemkaxboy@gmail.com>
Arthur Fabre <arthur@arthurfabre.com>
Arthur Khashaev <arthur@khashaev.ru>
Artur M. Wolff <artur.m.wolff@gmail.com>
Artyom Pervukhin <artyom.pervukhin@gmail.com>
Arvindh Rajesh Tamilmani <art@a-30.net>
Ashish Bhate <ab.listsubs@gmail.com>
Ashish Gandhi <ag@ashishgandhi.org>
Asim Shankar <asimshankar@gmail.com>
Assel Meher <asselmeher@gmail.com>
@@ -325,6 +339,7 @@ Baokun Lee <nototon@gmail.com> <bk@golangcn.org>
Barnaby Keene <accounts@southcla.ws>
Bartosz Grzybowski <melkorm@gmail.com>
Bartosz Oler <brtsz@google.com>
Bassam Ojeil <bojeil@google.com>
Bastian Ike <bastian.ike@gmail.com>
Ben Burkert <ben@benburkert.com>
Ben Cartwright-Cox <Ben@Benjojo.co.uk>
@@ -332,6 +347,7 @@ Ben Eitzen <eitzenb@golang.org>
Ben Fried <ben.fried@gmail.com>
Ben Haines <bhainesva@gmail.com>
Ben Hoyt <benhoyt@gmail.com>
Ben Hutchings <ben.hutchings@essensium.com>
Ben Kraft <benkraft@khanacademy.org>
Ben Laurie <ben@links.org> <benl@google.com>
Ben Lubar <ben.lubar@gmail.com>
@@ -430,6 +446,7 @@ Carl Henrik Lunde <chlunde@ifi.uio.no>
Carl Jackson <carl@stripe.com>
Carl Johnson <me@carlmjohnson.net>
Carl Mastrangelo <notcarl@google.com>
Carl Menezes <carleeto@gmail.com>
Carl Shapiro <cshapiro@google.com> <cshapiro@golang.org>
Carlisia Campos <carlisia@grokkingtech.io>
Carlo Alberto Ferraris <cafxx@strayorange.com>
@@ -443,6 +460,7 @@ Carlos Iriarte <ciriarte@gmail.com>
Carlos Souza <carloshrsouza@gmail.com>
Carolyn Van Slyck <me@carolynvanslyck.com>
Carrie Bynon <cbynon@gmail.com>
Carson Hoffman <c@rsonhoffman.com>
Cary Hull <chull@google.com>
Case Nelson <case.nelson@gmail.com>
Casey Callendrello <squeed@gmail.com>
@@ -462,6 +480,7 @@ Charles Kenney <charlesc.kenney@gmail.com>
Charles L. Dorian <cldorian@gmail.com>
Charles Lee <zombie.fml@gmail.com>
Charles Weill <weill@google.com>
Charlie Moog <moogcharlie@gmail.com>
Charlotte Brandhorst-Satzkorn <catzkorn@gmail.com>
Chauncy Cullitan <chauncyc@google.com>
Chen Zhidong <njutczd@gmail.com>
@@ -516,6 +535,7 @@ Christopher Nelson <nadiasvertex@gmail.com>
Christopher Nielsen <m4dh4tt3r@gmail.com>
Christopher Redden <christopher.redden@gmail.com>
Christopher Swenson <cswenson@google.com>
Christopher Thomas <53317512+chrisssthomas@users.noreply.github.com>
Christopher Wedgwood <cw@f00f.org>
Christos Zoulas <christos@zoulas.com> <zoulasc@gmail.com>
Christy Perez <christy@linux.vnet.ibm.com>
@@ -541,6 +561,8 @@ Cosmos Nicolaou <cnicolaou@google.com>
Costin Chirvasuta <ctin@google.com>
Craig Citro <craigcitro@google.com>
Cristian Staretu <unclejacksons@gmail.com>
Cristo García <cgg.code@gmail.com>
cui fliter <imcusg@gmail.com>
Cuihtlauac ALVARADO <cuihtlauac.alvarado@orange.com>
Cuong Manh Le <cuong@orijtech.com>
Curtis La Graff <curtis@lagraff.me>
@@ -560,6 +582,7 @@ Dan Callahan <dan.callahan@gmail.com>
Dan Harrington <harringtond@google.com>
Dan Jacques <dnj@google.com>
Dan Johnson <computerdruid@google.com>
Dan McArdle <dmcardle@google.com>
Dan Peterson <dpiddy@gmail.com>
Dan Pupius <dan@medium.com>
Dan Scales <danscales@google.com>
@@ -611,6 +634,7 @@ Dave Russell <forfuncsake@gmail.com>
David Anderson <danderson@google.com>
David Barnett <dbarnett@google.com>
David Benjamin <davidben@google.com>
David Black <dblack@atlassian.com>
David Bond <davidsbond93@gmail.com>
David Brophy <dave@brophy.uk>
David Bürgin <676c7473@gmail.com>
@@ -654,6 +678,7 @@ Davor Kapsa <davor.kapsa@gmail.com>
Dean Eigenmann <7621705+decanus@users.noreply.github.com>
Dean Prichard <dean.prichard@gmail.com>
Deepak Jois <deepak.jois@gmail.com>
Deepak S <deepakspavoodath@gmail.com>
Denis Bernard <db047h@gmail.com>
Denis Brandolini <denis.brandolini@gmail.com>
Denis Isaev <idenx@yandex.com>
@@ -676,8 +701,10 @@ Dhiru Kholia <dhiru.kholia@gmail.com>
Dhruvdutt Jadhav <dhruvdutt.jadhav@gmail.com>
Di Xiao <dixiao@google.com>
Didier Spezia <didier.06@gmail.com>
Diego Medina <fmpwizard@gmail.com>
Diego Siqueira <diego9889@gmail.com>
Dieter Plaetinck <dieter@raintank.io>
Dilyn Corner <dilyn.corner@gmail.com>
Dimitri Sokolyuk <sokolyuk@gmail.com>
Dimitri Tcaciuc <dtcaciuc@gmail.com>
Dina Garmash <dgrmsh@gmail.com>
@@ -714,6 +741,7 @@ Doug Fawley <dfawley@google.com>
Douglas Danger Manley <doug.manley@gmail.com>
Drew Flower <drewvanstone@gmail.com>
Drew Hintz <adhintz@google.com>
Drew Richardson <drewrichardson@gmail.com>
Duco van Amstel <duco.vanamstel@gmail.com>
Duncan Holm <mail@frou.org>
Dustin Carlino <dcarlino@google.com>
@@ -735,6 +763,7 @@ Egon Elbre <egonelbre@gmail.com>
Ehren Kret <ehren.kret@gmail.com>
Eitan Adler <lists@eitanadler.com>
Eivind Uggedal <eivind@uggedal.com>
El Mostafa Idrassi <el.mostafa.idrassi@gmail.com>
Elbert Fliek <efliek@gmail.com>
Eldar Rakhimberdin <ibeono@gmail.com>
Elena Grahovac <elena@grahovac.me>
@@ -742,6 +771,7 @@ Eli Bendersky <eliben@google.com>
Elias Naur <mail@eliasnaur.com> <elias.naur@gmail.com>
Elliot Morrison-Reed <elliotmr@gmail.com>
Ellison Leão <ellisonleao@gmail.com>
Elvina Yakubova <elvinayakubova@gmail.com>
Emerson Lin <linyintor@gmail.com>
Emil Bektimirov <lefelys@gmail.com>
Emil Hessman <emil@hessman.se>
@@ -767,6 +797,7 @@ Eric Rescorla <ekr@rtfm.com>
Eric Roshan-Eisner <eric.d.eisner@gmail.com>
Eric Rutherford <erutherford@gmail.com>
Eric Rykwalder <e.rykwalder@gmail.com>
Eric Wang <wangchaogo1990@gmail.com>
Erick Tryzelaar <etryzelaar@google.com>
Erik Aigner <aigner.erik@gmail.com>
Erik Dubbelboer <erik@dubbelboer.com>
@@ -778,6 +809,7 @@ Ernest Chiang <ernest_chiang@htc.com>
Erwin Oegema <blablaechthema@hotmail.com>
Esko Luontola <esko.luontola@gmail.com>
Ethan Burns <eaburns@google.com>
Ethan Hur <ethan0311@gmail.com>
Ethan Miller <eamiller@us.ibm.com>
Euan Kemp <euank@euank.com>
Eugene Formanenko <mo4islona@gmail.com>
@@ -818,6 +850,7 @@ Felix Cornelius <9767036+fcornelius@users.noreply.github.com>
Felix Geisendörfer <haimuiba@gmail.com>
Felix Kollmann <fk@konsorten.de>
Ferenc Szabo <frncmx@gmail.com>
Fernandez Ludovic <lfernandez.dev@gmail.com>
Filip Gruszczyński <gruszczy@gmail.com>
Filip Haglund <drathier@users.noreply.github.com>
Filip Stanis <fstanis@google.com>
@@ -858,6 +891,7 @@ Gabriel Nelle <tehsphinx@web.de>
Gabriel Nicolas Avellaneda <avellaneda.gabriel@gmail.com>
Gabriel Rosenhouse <rosenhouse@gmail.com>
Gabriel Russell <gabriel.russell@gmail.com>
Gabriel Vasile <gabriel.vasile0793@gmail.com>
Gareth Paul Jones <gpj@foursquare.com>
Garret Kelly <gdk@google.com>
Garrick Evans <garrick@google.com>
@@ -891,6 +925,8 @@ Gianguido Sora` <g.sora4@gmail.com>
Gideon Jan-Wessel Redelinghuys <gjredelinghuys@gmail.com>
Giles Lean <giles.lean@pobox.com>
Giovanni Bajo <rasky@develer.com>
GitHub User @180909 (70465953) <734461790@qq.com>
GitHub User @6543 (24977596) <6543@obermui.de>
GitHub User @aca (50316549) <acadx0@gmail.com>
GitHub User @ajnirp (1688456) <ajnirp@users.noreply.github.com>
GitHub User @ajz01 (4744634) <ajzdenek@gmail.com>
@@ -904,10 +940,12 @@ GitHub User @bontequero (2674999) <bontequero@gmail.com>
GitHub User @cch123 (384546) <buaa.cch@gmail.com>
GitHub User @chainhelen (7046329) <chainhelen@gmail.com>
GitHub User @chanxuehong (3416908) <chanxuehong@gmail.com>
GitHub User @Cluas (10056928) <Cluas@live.cn>
GitHub User @cncal (23520240) <flycalvin@qq.com>
GitHub User @DQNEO (188741) <dqneoo@gmail.com>
GitHub User @Dreamacro (8615343) <chuainian@gmail.com>
GitHub User @dupoxy (1143957) <dupoxy@users.noreply.github.com>
GitHub User @EndlessCheng (7086966) <loli.con@qq.com>
GitHub User @erifan (31343225) <eric.fang@arm.com>
GitHub User @esell (9735165) <eujon.sellers@gmail.com>
GitHub User @fatedier (7346661) <fatedier@gmail.com>
@@ -916,12 +954,15 @@ GitHub User @geedchin (11672310) <geedchin@gmail.com>
GitHub User @GrigoriyMikhalkin (3637857) <grigoriymikhalkin@gmail.com>
GitHub User @hengwu0 (41297446) <41297446+hengwu0@users.noreply.github.com>
GitHub User @hitzhangjie (3725760) <hit.zhangjie@gmail.com>
GitHub User @hqpko (13887251) <whaibin01@hotmail.com>
GitHub User @itchyny (375258) <itchyny@hatena.ne.jp>
GitHub User @jinmiaoluo (39730824) <jinmiaoluo@icloud.com>
GitHub User @jopbrown (6345470) <msshane2008@gmail.com>
GitHub User @kazyshr (30496953) <kazyshr0301@gmail.com>
GitHub User @kc1212 (1093806) <kc1212@users.noreply.github.com>
GitHub User @komisan19 (18901496) <komiyama6219@gmail.com>
GitHub User @Kropekk (13366453) <kamilkropiewnicki@gmail.com>
GitHub User @lhl2617 (33488131) <l.h.lee2617@gmail.com>
GitHub User @linguohua (3434367) <lghchinaidea@gmail.com>
GitHub User @LotusFenn (13775899) <fenn.lotus@gmail.com>
GitHub User @ly303550688 (11519839) <yang.liu636@gmail.com>
@@ -936,10 +977,14 @@ GitHub User @OlgaVlPetrova (44112727) <OVPpetrova@gmail.com>
GitHub User @pityonline (438222) <pityonline@gmail.com>
GitHub User @po3rin (29445112) <abctail30@gmail.com>
GitHub User @pokutuna (57545) <popopopopokutuna@gmail.com>
GitHub User @povsister (11040951) <pov@mahou-shoujo.moe>
GitHub User @pytimer (17105586) <lixin20101023@gmail.com>
GitHub User @qcrao (7698088) <qcrao91@gmail.com>
GitHub User @ramenjuniti (32011829) <ramenjuniti@gmail.com>
GitHub User @saitarunreddy (21041941) <saitarunreddypalla@gmail.com>
GitHub User @SataQiu (9354727) <shidaqiu2018@gmail.com>
GitHub User @shogo-ma (9860598) <Choroma194@gmail.com>
GitHub User @sivchari (55221074) <shibuuuu5@gmail.com>
GitHub User @skanehira (7888591) <sho19921005@gmail.com>
GitHub User @soolaugust (10558124) <soolaugust@gmail.com>
GitHub User @surechen (7249331) <surechen17@gmail.com>
@@ -947,9 +992,12 @@ GitHub User @tatsumack (4510569) <tatsu.mack@gmail.com>
GitHub User @tell-k (26263) <ffk2005@gmail.com>
GitHub User @tennashi (10219626) <tennashio@gmail.com>
GitHub User @uhei (2116845) <uhei@users.noreply.github.com>
GitHub User @uji (49834542) <ujiprog@gmail.com>
GitHub User @unbyte (5772358) <i@shangyes.net>
GitHub User @uropek (39370426) <uropek@gmail.com>
GitHub User @utkarsh-extc (53217283) <utkarsh.extc@gmail.com>
GitHub User @witchard (4994659) <witchard@hotmail.co.uk>
GitHub User @wolf1996 (5901874) <ksgiv37@gmail.com>
GitHub User @yah01 (12216890) <kagaminehuan@gmail.com>
GitHub User @yuanhh (1298735) <yuan415030@gmail.com>
GitHub User @zikaeroh (48577114) <zikaeroh@gmail.com>
@@ -962,6 +1010,7 @@ Glenn Brown <glennb@google.com>
Glenn Lewis <gmlewis@google.com>
Gordon Klaus <gordon.klaus@gmail.com>
Gordon Tyler <gordon@doxxx.net>
Grace Han <hgrace503@gmail.com>
Graham King <graham4king@gmail.com>
Graham Miller <graham.miller@gmail.com>
Grant Griffiths <ggp493@gmail.com>
@@ -977,10 +1026,12 @@ Guilherme Caruso <gui.martinscaruso@gmail.com>
Guilherme Garnier <guilherme.garnier@gmail.com>
Guilherme Goncalves <guilhermeaugustosg@gmail.com>
Guilherme Rezende <guilhermebr@gmail.com>
Guilherme Souza <32180229+gqgs@users.noreply.github.com>
Guillaume J. Charmes <guillaume@charmes.net>
Guillaume Sottas <guillaumesottas@gmail.com>
Günther Noack <gnoack@google.com>
Guobiao Mei <meiguobiao@gmail.com>
Guodong Li <guodongli@google.com>
Guoliang Wang <iamwgliang@gmail.com>
Gustav Paul <gustav.paul@gmail.com>
Gustav Westling <gustav@westling.xyz>
@@ -995,6 +1046,7 @@ HAMANO Tsukasa <hamano@osstech.co.jp>
Han-Wen Nienhuys <hanwen@google.com>
Hang Qian <hangqian90@gmail.com>
Hanjun Kim <hallazzang@gmail.com>
Hanlin He <hanling.he@gmail.com>
Hanlin Shi <shihanlin9@gmail.com>
Haoran Luo <haoran.luo@chaitin.com>
Haosdent Huang <haosdent@gmail.com>
@@ -1026,18 +1078,19 @@ Herbie Ong <herbie@google.com>
Heschi Kreinick <heschi@google.com>
Hidetatsu Yaginuma <ygnmhdtt@gmail.com>
Hilko Bengen <bengen@hilluzination.de>
Himanshu Kishna Srivastava <28himanshu@gmail.com>
Hiroaki Nakamura <hnakamur@gmail.com>
Hiromichi Ema <ema.hiro@gmail.com>
Hironao OTSUBO <motemen@gmail.com>
Hiroshi Ioka <hirochachacha@gmail.com>
Hitoshi Mitake <mitake.hitoshi@gmail.com>
Holden Huang <ttyh061@gmail.com>
Songlin Jiang <hollowman@hollowman.ml>
Hong Ruiqi <hongruiqi@gmail.com>
Hongfei Tan <feilengcui008@gmail.com>
Horacio Duran <horacio.duran@gmail.com>
Horst Rutter <hhrutter@gmail.com>
Hossein Sheikh Attar <hattar@google.com>
Hossein Zolfi <hossein.zolfi@gmail.com>
Howard Zhang <howard.zhang@arm.com>
Hsin Tsao <tsao@google.com>
Hsin-Ho Yeh <yhh92u@gmail.com>
@@ -1054,11 +1107,14 @@ Ian Haken <ihaken@netflix.com>
Ian Kent <iankent85@gmail.com>
Ian Lance Taylor <iant@golang.org>
Ian Leue <ian@appboy.com>
Ian Mckay <iann0036@gmail.com>
Ian Tay <iantay@google.com>
Ian Woolf <btw515wolf2@gmail.com>
Ian Zapolsky <ianzapolsky@gmail.com>
Ibrahim AshShohail <ibra.sho@gmail.com>
Icarus Sparry <golang@icarus.freeuk.com>
Iccha Sethi <icchasethi@gmail.com>
Ichinose Shogo <shogo82148@gmail.com>
Idora Shinatose <idora.shinatose@gmail.com>
Ignacio Hagopian <jsign.uy@gmail.com>
Igor Bernstein <igorbernstein@google.com>
@@ -1068,6 +1124,7 @@ Igor Vashyst <ivashyst@gmail.com>
Igor Zhilianin <igor.zhilianin@gmail.com>
Ikko Ashimine <eltociear@gmail.com>
Illya Yalovyy <yalovoy@gmail.com>
Ilya Chukov <56119080+Elias506@users.noreply.github.com>
Ilya Sinelnikov <sidhmangh@gmail.com>
Ilya Tocar <ilya.tocar@intel.com>
INADA Naoki <songofacandy@gmail.com>
@@ -1122,6 +1179,7 @@ James Cowgill <James.Cowgill@imgtec.com>
James Craig Burley <james-github@burleyarch.com>
James David Chalfant <james.chalfant@gmail.com>
James Eady <jmeady@google.com>
James Fennell <jpfennell@google.com>
James Fysh <james.fysh@gmail.com>
James Gray <james@james4k.com>
James Hartig <fastest963@gmail.com>
@@ -1178,6 +1236,7 @@ Jason Wangsadinata <jwangsadinata@gmail.com>
Javier Kohen <jkohen@google.com>
Javier Revillas <jrevillas@massivedynamic.io>
Javier Segura <javism@gmail.com>
Jay Chen <chenjie@chenjie.info>
Jay Conrod <jayconrod@google.com>
Jay Lee <BusyJayLee@gmail.com>
Jay Taylor <outtatime@gmail.com>
@@ -1200,6 +1259,7 @@ Jeff Johnson <jrjohnson@google.com>
Jeff R. Allen <jra@nella.org> <jeff.allen@gmail.com>
Jeff Sickel <jas@corpus-callosum.com>
Jeff Wendling <jeff@spacemonkey.com>
Jeff Widman <jeff@jeffwidman.com>
Jeffrey H <jeffreyh192@gmail.com>
Jelte Fennema <github-tech@jeltef.nl>
Jens Frederich <jfrederich@gmail.com>
@@ -1210,6 +1270,7 @@ Jeremy Faller <jeremy@golang.org>
Jeremy Jackins <jeremyjackins@gmail.com>
Jeremy Jay <jeremy@pbnjay.com>
Jeremy Schlatter <jeremy.schlatter@gmail.com>
Jero Bado <tokidokitalkyou@gmail.com>
Jeroen Bobbeldijk <jerbob92@gmail.com>
Jeroen Simonetti <jeroen@simonetti.nl>
Jérôme Doucet <jerdct@gmail.com>
@@ -1251,6 +1312,8 @@ Joe Richey <joerichey@google.com>
Joe Shaw <joe@joeshaw.org>
Joe Sylve <joe.sylve@gmail.com>
Joe Tsai <joetsai@digital-static.net>
Joel Courtney <euphemize@gmail.com>
Joel Ferrier <joelferrier@google.com>
Joel Sing <joel@sing.id.au> <jsing@google.com>
Joël Stemmer <jstemmer@google.com>
Joel Stemmer <stemmertech@gmail.com>
@@ -1260,7 +1323,9 @@ Johan Euphrosine <proppy@google.com>
Johan Jansson <johan.jansson@iki.fi>
Johan Knutzen <johan@senri.se>
Johan Sageryd <j@1616.se>
Johannes Huning <johannes.huning@gmail.com>
John Asmuth <jasmuth@gmail.com>
John Bampton <jbampton@gmail.com>
John Beisley <huin@google.com>
John C Barstow <jbowtie@amathaine.com>
John DeNero <denero@google.com>
@@ -1269,6 +1334,7 @@ John Gibb <johngibb@gmail.com>
John Gilik <john@jgilik.com>
John Graham-Cumming <jgc@jgc.org> <jgrahamc@gmail.com>
John Howard Palevich <jack.palevich@gmail.com>
John Jago <johnjago@protonmail.com>
John Jeffery <jjeffery@sp.com.au>
John Jenkins <twodopeshaggy@gmail.com>
John Leidegren <john.leidegren@gmail.com>
@@ -1320,6 +1386,7 @@ Josa Gesell <josa@gesell.me>
Jose Luis Vázquez González <josvazg@gmail.com>
Joseph Bonneau <jcb@google.com>
Joseph Holsten <joseph@josephholsten.com>
Joseph Morag <sefim96@gmail.com>
Josh Baum <joshbaum@google.com>
Josh Bleecher Snyder <josharian@gmail.com>
Josh Chorlton <jchorlton@gmail.com>
@@ -1327,12 +1394,14 @@ Josh Deprez <josh.deprez@gmail.com>
Josh Goebel <dreamer3@gmail.com>
Josh Hoak <jhoak@google.com>
Josh Holland <jrh@joshh.co.uk>
Josh Rickmar <jrick@companyzero.com>
Josh Roppo <joshroppo@gmail.com>
Josh Varga <josh.varga@gmail.com>
Joshua Bezaleel Abednego <joshua.bezaleel@gmail.com>
Joshua Boelter <joshua.boelter@intel.com>
Joshua Chase <jcjoshuachase@gmail.com>
Joshua Crowgey <jcrowgey@uw.edu>
Joshua Harshman <joshgreyhat@gmail.com>
Joshua M. Clulow <josh.clulow@joyent.com>
Joshua Rubin <joshua@rubixconsulting.com>
Josselin Costanzi <josselin@costanzi.fr>
@@ -1353,6 +1422,7 @@ Julie Qiu <julie@golang.org>
Julien Kauffmann <julien.kauffmann@freelan.org>
Julien Salleyron <julien.salleyron@gmail.com>
Julien Schmidt <google@julienschmidt.com>
Julien Tant <julien@craftyx.fr>
Julio Montes <julio.montes@intel.com>
Jun Zhang <jim.zoumo@gmail.com>
Junchen Li <junchen.li@arm.com>
@@ -1419,10 +1489,12 @@ Kenta Mori <zoncoen@gmail.com>
Kerollos Magdy <kerolloz@yahoo.com>
Ketan Parmar <ketanbparmar@gmail.com>
Kevan Swanberg <kevswanberg@gmail.com>
Kevin Albertson <kevin.albertson@mongodb.com>
Kevin Ballard <kevin@sb.org>
Kevin Burke <kev@inburke.com>
Kévin Dunglas <dunglas@gmail.com>
Kevin Gillette <extemporalgenome@gmail.com>
Kevin Herro <kevin109104@gmail.com>
Kevin Kirsche <kev.kirsche@gmail.com>
Kevin Klues <klueska@gmail.com> <klueska@google.com>
Kevin Malachowski <chowski@google.com>
@@ -1457,6 +1529,7 @@ Koya IWAMURA <kiwamura0314@gmail.com>
Kris Kwiatkowski <kris@cloudflare.com>
Kris Nova <kris@nivenly.com>
Kris Rousey <krousey@google.com>
Krishna Birla <krishnabirla16@gmail.com>
Kristopher Watts <traetox@gmail.com>
Krzysztof Dąbrowski <krzysdabro@live.com>
Kshitij Saraogi <kshitijsaraogi@gmail.com>
@@ -1480,6 +1553,7 @@ Lajos Papp <lalyos@yahoo.com>
Lakshay Garg <lakshay.garg.1996@gmail.com>
Lann Martin <lannm@google.com>
Lanre Adelowo <yo@lanre.wtf>
Lapo Luchini <lapo@lapo.it>
Larry Clapp <larry@theclapp.org>
Larry Hosken <lahosken@golang.org>
Lars Jeppesen <jeppesen.lars@gmail.com>
@@ -1496,6 +1570,7 @@ Leigh McCulloch <leighmcc@gmail.com>
Leo Antunes <leo@costela.net>
Leo Rudberg <ljr@google.com>
Leon Klingele <git@leonklingele.de>
Leonard Wang <wangdeyu0907@gmail.com>
Leonardo Comelli <leonardo.comelli@gmail.com>
Leonel Quinteros <leonel.quinteros@gmail.com>
Lev Shamardin <shamardin@gmail.com>
@@ -1506,7 +1581,9 @@ Lily Chung <lilithkchung@gmail.com>
Lingchao Xin <douglarek@gmail.com>
Lion Yang <lion@aosc.xyz>
Liz Rice <liz@lizrice.com>
Lize Cai <lizzzcai1@gmail.com>
Lloyd Dewolf <foolswisdom@gmail.com>
Lluís Batlle i Rossell <viric@viric.name>
Lorenz Bauer <lmb@cloudflare.com>
Lorenz Brun <lorenz@brun.one>
Lorenz Nickel <mail@lorenznickel.de>
@@ -1531,6 +1608,7 @@ Lukasz Milewski <lmmilewski@gmail.com>
Luke Champine <luke.champine@gmail.com>
Luke Curley <qpingu@gmail.com>
Luke Granger-Brown <git@lukegb.com>
Luke Shumaker <lukeshu@datawire.io>
Luke Young <bored-engineer@users.noreply.github.com>
Luna Duclos <luna.duclos@palmstonegames.com>
Luuk van Dijk <lvd@golang.org> <lvd@google.com>
@@ -1550,6 +1628,7 @@ Mal Curtis <mal@mal.co.nz>
Manfred Touron <m@42.am>
Manigandan Dharmalingam <manigandan.jeff@gmail.com>
Manish Goregaokar <manishsmail@gmail.com>
Manlio Perillo <manlio.perillo@gmail.com>
Manoj Dayaram <platform-dev@moovweb.com> <manoj.dayaram@moovweb.com>
Mansour Rahimi <rahimi.mnr@gmail.com>
Manu Garg <manugarg@google.com>
@@ -1646,6 +1725,8 @@ Matt Joiner <anacrolix@gmail.com>
Matt Jones <mrjones@google.com>
Matt Juran <thepciet@gmail.com>
Matt Layher <mdlayher@gmail.com>
Matt Masurka <masurka@google.com>
Matt Pearring <broskies@google.com>
Matt Reiferson <mreiferson@gmail.com>
Matt Robenolt <matt@ydekproductions.com>
Matt Strong <mstrong1341@gmail.com>
@@ -1659,9 +1740,12 @@ Matthew Denton <mdenton@skyportsystems.com>
Matthew Holt <Matthew.Holt+git@gmail.com>
Matthew Horsnell <matthew.horsnell@gmail.com>
Matthew Waters <mwwaters@gmail.com>
Matthias Frei <matthias.frei@inf.ethz.ch>
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
Matthieu Olivier <olivier.matthieu@gmail.com>
Matthijs Kooijman <matthijs@stdin.nl>
Mattias Appelgren <mattias@ppelgren.se>
Mauricio Alvarado <mauricio.alvarado@leftfieldlabs.com>
Max Drosdo.www <g1ran1q@gmail.com>
Max Riveiro <kavu13@gmail.com>
Max Schmitt <max@schmitt.mx>
@@ -1677,9 +1761,11 @@ Máximo Cuadros Ortiz <mcuadros@gmail.com>
Maxwell Krohn <themax@gmail.com>
Maya Rashish <maya@NetBSD.org>
Mayank Kumar <krmayankk@gmail.com>
Mehrad Sadeghi <2012.linkinpark@gmail.com>
Meir Fischer <meirfischer@gmail.com>
Meng Zhuo <mengzhuo1203@gmail.com> <mzh@golangcn.org>
Mhd Sulhan <m.shulhan@gmail.com>
Mia Zhu <CrystalZhu1025getu@gmail.com>
Micah Stetson <micah.stetson@gmail.com>
Michael Anthony Knyszek <mknyszek@google.com>
Michael Brandenburg <mbrandenburg@bolste.com>
@@ -1730,8 +1816,10 @@ Michal Franc <lam.michal.franc@gmail.com>
Michał Łowicki <mlowicki@gmail.com>
Michal Pristas <michal.pristas@gmail.com>
Michal Rostecki <mrostecki@suse.de>
Michal Stokluska <mstoklus@redhat.com>
Michalis Kargakis <michaliskargakis@gmail.com>
Michel Lespinasse <walken@google.com>
Michel Levieux <mlevieux42@gmail.com>
Michele Di Pede <michele.di.pede@gmail.com>
Mickael Kerjean <mickael.kerjean@gmail.com>
Mickey Reiss <mickeyreiss@gmail.com>
@@ -1790,7 +1878,9 @@ Muir Manders <muir@mnd.rs>
Mukesh Sharma <sharma.mukesh439@gmail.com>
Mura Li <mura_li@castech.com.tw>
Mykhailo Lesyk <mikhail@lesyk.org>
Nahum Shalman <nahamu@gmail.com>
Naman Aggarwal <aggarwal.nam@gmail.com>
Naman Gera <namangera15@gmail.com>
Nan Deng <monnand@gmail.com>
Nao Yonashiro <owan.orisano@gmail.com>
Naoki Kanatani <k12naoki@gmail.com>
@@ -1818,6 +1908,7 @@ Neven Sajko <nsajko@gmail.com>
Nevins Bartolomeo <nevins.bartolomeo@gmail.com>
Niall Sheridan <nsheridan@gmail.com>
Nic Day <nic.day@me.com>
Nicholas Asimov <nicholas@asimov.me>
Nicholas Katsaros <nick@nickkatsaros.com>
Nicholas Maniscalco <nicholas@maniscalco.com>
Nicholas Ng <nickng@nickng.io>
@@ -1847,6 +1938,7 @@ Nik Nyby <nnyby@columbia.edu>
Nikhil Benesch <nikhil.benesch@gmail.com>
Nikita Gillmann <nikita@n0.is> <ng0@n0.is>
Nikita Kryuchkov <nkryuchkov10@gmail.com>
Nikita Melekhin <nimelehin@gmail.com>
Nikita Vanyasin <nikita.vanyasin@gmail.com>
Niklas Schnelle <niklas.schnelle@gmail.com>
Niko Dziemba <niko@dziemba.com>
@@ -1858,6 +1950,7 @@ Niranjan Godbole <niranjan8192@gmail.com>
Nishanth Shanmugham <nishanth.gerrard@gmail.com>
Noah Campbell <noahcampbell@gmail.com>
Noah Goldman <noahg34@gmail.com>
Noah Santschi-Cooney <noah@santschi-cooney.ch>
Noble Johnson <noblepoly@gmail.com>
Nodir Turakulov <nodir@google.com>
Noel Georgi <git@frezbo.com>
@@ -1894,6 +1987,7 @@ Pablo Rozas Larraondo <pablo.larraondo@anu.edu.au>
Pablo Santiago Blum de Aguiar <scorphus@gmail.com>
Padraig Kitterick <padraigkitterick@gmail.com>
Pallat Anchaleechamaikorn <yod.pallat@gmail.com>
Pan Chenglong <1004907659@qq.com>
Panos Georgiadis <pgeorgiadis@suse.de>
Pantelis Sampaziotis <psampaz@gmail.com>
Paolo Giarrusso <p.giarrusso@gmail.com>
@@ -1947,6 +2041,7 @@ Paulo Casaretto <pcasaretto@gmail.com>
Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
Paulo Gomes <paulo.gomes.uk@gmail.com>
Pavel Paulau <pavel.paulau@gmail.com>
Pavel Watson <watsonpavel@gmail.com>
Pavel Zinovkin <pavel.zinovkin@gmail.com>
Pavlo Sumkin <ymkins@gmail.com>
Pawel Knap <pawelknap88@gmail.com>
@@ -1954,6 +2049,8 @@ Pawel Szczur <filemon@google.com>
Paweł Szulik <pawel.szulik@intel.com>
Pei Xian Chee <luciolas1991@gmail.com>
Pei-Ming Wu <p408865@gmail.com>
Pen Tree <appletree2479@outlook.com>
Peng Gao <peng.gao.dut@gmail.com>
Percy Wegmann <ox.to.a.cart@gmail.com>
Perry Abbott <perry.j.abbott@gmail.com>
Petar Dambovaliev <petar.atanasov.1987@gmail.com>
@@ -1992,6 +2089,7 @@ Philip Brown <phil@bolthole.com>
Philip Hofer <phofer@umich.edu>
Philip K. Warren <pkwarren@gmail.com>
Philip Nelson <me@pnelson.ca>
Philipp Sauter <sauterp@protonmail.com>
Philipp Stephani <phst@google.com>
Phillip Campbell <15082+phillc@users.noreply.github.com>
Pierre Carru <pierre.carru@eshard.com>
@@ -2007,6 +2105,7 @@ Poh Zi How <poh.zihow@gmail.com>
Polina Osadcha <polliosa@google.com>
Pontus Leitzler <leitzler@gmail.com>
Povilas Versockas <p.versockas@gmail.com>
Prajwal Koirala <16564273+Prajwal-Koirala@users.noreply.github.com>
Prasanga Siripala <pj@pjebs.com.au>
Prasanna Swaminathan <prasanna@mediamath.com>
Prashant Agrawal <prashant.a.vjti@gmail.com>
@@ -2027,11 +2126,13 @@ Quim Muntal <quimmuntal@gmail.com>
Quinn Slack <sqs@sourcegraph.com>
Quinten Yearsley <qyearsley@chromium.org>
Quoc-Viet Nguyen <afelion@gmail.com>
Rabin Gaire <rabingaire20@gmail.com>
Radek Simko <radek.simko@gmail.com>
Radek Sohlich <sohlich@gmail.com>
Radu Berinde <radu@cockroachlabs.com>
Rafal Jeczalik <rjeczalik@gmail.com>
Raghavendra Nagaraj <jamdagni86@gmail.com>
Rahul Bajaj <rahulrb0509@gmail.com>
Rahul Chaudhry <rahulchaudhry@chromium.org>
Rahul Wadhwani <rahulwadhwani21@gmail.com>
Raif S. Naffah <go@naffah-raif.name>
@@ -2041,12 +2142,14 @@ Rajender Reddy Kompally <rajenderreddykompally@gmail.com>
Ralph Corderoy <ralph@inputplus.co.uk>
Ramazan AYYILDIZ <rayyildiz@gmail.com>
Ramesh Dharan <dharan@google.com>
Randy Reddig <randy@alta.software>
Raph Levien <raph@google.com>
Raphael Geronimi <raphael.geronimi@gmail.com>
Raul Silvera <rsilvera@google.com>
Ravil Bikbulatov <weeellz12@gmail.com>
RaviTeja Pothana <ravi.tezu@gmail.com>
Ray Tung <rtung@thoughtworks.com>
Ray Wu <ray@liftoff.io>
Raymond Kazlauskas <raima220@gmail.com>
Rebecca Stambler <rstambler@golang.org>
Reilly Watson <reillywatson@gmail.com>
@@ -2066,6 +2169,7 @@ Richard Eric Gavaletz <gavaletz@gmail.com>
Richard Gibson <richard.gibson@gmail.com>
Richard Miller <miller.research@gmail.com>
Richard Musiol <mail@richard-musiol.de> <neelance@gmail.com>
Richard Pickering <richard.pickering@hotmail.co.uk>
Richard Ulmer <codesoap@mailbox.org>
Richard Wilkes <wilkes@me.com>
Rick Arnold <rickarnoldjr@gmail.com>
@@ -2124,6 +2228,7 @@ Rowan Worth <sqweek@gmail.com>
Rudi Kramer <rudi.kramer@gmail.com>
Rui Ueyama <ruiu@google.com>
Ruixin Bao <ruixin.bao@ibm.com>
Ruslan Andreev <ruslan.andreev@huawei.com>
Ruslan Nigmatullin <elessar@dropbox.com>
Russ Cox <rsc@golang.org>
Russell Haering <russellhaering@gmail.com>
@@ -2141,6 +2246,7 @@ Ryan Seys <ryan@ryanseys.com>
Ryan Slade <ryanslade@gmail.com>
Ryan Zhang <ryan.zhang@docker.com>
Ryoichi KATO <ryo1kato@gmail.com>
Ryoya Sekino <ryoyasekino1993@gmail.com>
Ryuji Iwata <qt.luigi@gmail.com>
Ryuma Yoshida <ryuma.y1117@gmail.com>
Ryuzo Yamamoto <ryuzo.yamamoto@gmail.com>
@@ -2176,8 +2282,10 @@ Sardorbek Pulatov <sardorbek.pulatov@outlook.com>
Sascha Brawer <sascha@brawer.ch>
Sasha Lionheart <lionhearts@google.com>
Sasha Sobol <sasha@scaledinference.com>
Satoru Kitaguchi <rule.the.fate.myfirststory@gmail.com>
Scott Barron <scott.barron@github.com>
Scott Bell <scott@sctsm.com>
Scott Cotton <scott@mindowl.com>
Scott Crunkleton <crunk1@gmail.com>
Scott Ferguson <scottwferg@gmail.com>
Scott Lawrence <bytbox@gmail.com>
@@ -2191,6 +2299,7 @@ Sean Chittenden <seanc@joyent.com>
Sean Christopherson <sean.j.christopherson@intel.com>
Sean Dolphin <Sean.Dolphin@kpcompass.com>
Sean Harger <sharger@google.com>
Sean Harrington <sean.harrington@leftfieldlabs.com>
Sean Hildebrand <seanwhildebrand@gmail.com>
Sean Liao <seankhliao@gmail.com>
Sean Rees <sean@erifax.org>
@@ -2212,6 +2321,7 @@ Sergey Dobrodey <sergey.dobrodey@synesis.ru>
Sergey Frolov <sfrolov@google.com>
Sergey Glushchenko <gsserge@gmail.com>
Sergey Ivanov <ser1325@gmail.com>
Sergey Kacheev <S.Kacheev@gmail.com>
Sergey Lukjanov <me@slukjanov.name>
Sergey Mishin <sergeymishine@gmail.com>
Sergey Mudrik <sergey.mudrik@gmail.com>
@@ -2223,6 +2333,7 @@ Serhat Giydiren <serhatgiydiren@gmail.com>
Serhii Aheienko <serhii.aheienko@gmail.com>
Seth Hoenig <seth.a.hoenig@gmail.com>
Seth Vargo <sethvargo@gmail.com>
Shaba Abhiram <shabarivas.abhiram@gmail.com>
Shahar Kohanim <skohanim@gmail.com>
Shailesh Suryawanshi <ss.shailesh28@gmail.com>
Shamil Garatuev <garatuev@gmail.com>
@@ -2250,9 +2361,13 @@ Shivakumar GN <shivakumar.gn@gmail.com>
Shivani Singhal <shivani.singhal2804@gmail.com>
Shivansh Rai <shivansh@freebsd.org>
Shivashis Padhi <shivashispadhi@gmail.com>
Shoshin Nikita <shoshin_nikita@fastmail.com>
Shota Sugiura <s.shota.710.3506@gmail.com>
Shubham Sharma <shubham.sha12@gmail.com>
Shuhei Takahashi <nya@chromium.org>
Shun Fan <sfan@google.com>
Silvan Jegen <s.jegen@gmail.com>
Simão Gomes Viana <simaogmv@gmail.com>
Simarpreet Singh <simar@linux.com>
Simon Drake <simondrake1990@gmail.com>
Simon Ferquel <simon.ferquel@docker.com>
@@ -2267,13 +2382,16 @@ Sina Siadat <siadat@gmail.com>
Sjoerd Siebinga <sjoerd.siebinga@gmail.com>
Sokolov Yura <funny.falcon@gmail.com>
Song Gao <song@gao.io>
Song Lim <songlim327@gmail.com>
Songjiayang <songjiayang1@gmail.com>
Songlin Jiang <hollowman@hollowman.ml>
Soojin Nam <jsunam@gmail.com>
Søren L. Hansen <soren@linux2go.dk>
Sparrow Li <liyuancylx@gmail.com>
Spencer Kocot <spencerkocot@gmail.com>
Spencer Nelson <s@spenczar.com>
Spencer Tung <spencertung@google.com>
Spenser Black <spenserblack01@gmail.com>
Spring Mc <heresy.mc@gmail.com>
Srdjan Petrovic <spetrovic@google.com>
Sridhar Venkatakrishnan <sridhar@laddoo.net>
@@ -2324,6 +2442,7 @@ Suyash <dextrous93@gmail.com>
Suzy Mueller <suzmue@golang.org>
Sven Almgren <sven@tras.se>
Sven Blumenstein <svbl@google.com>
Sven Lee <lee1300394324@gmail.com>
Sven Taute <sven.taute@gmail.com>
Sylvain Zimmer <sylvain@sylvainzimmer.com>
Syohei YOSHIDA <syohex@gmail.com>
@@ -2406,12 +2525,14 @@ Tiwei Bie <tiwei.btw@antgroup.com>
Tobias Assarsson <tobias.assarsson@gmail.com>
Tobias Columbus <tobias.columbus@gmail.com> <tobias.columbus@googlemail.com>
Tobias Klauser <tklauser@distanz.ch>
Tobias Kohlbau <tobias@kohlbau.de>
Toby Burress <kurin@google.com>
Todd Kulesza <tkulesza@google.com>
Todd Neal <todd@tneal.org>
Todd Wang <toddwang@gmail.com>
Tom Anthony <git@tomanthony.co.uk>
Tom Bergan <tombergan@google.com>
Tom Freudenberg <tom.freudenberg@4commerce.de>
Tom Heng <zhm20070928@gmail.com>
Tom Lanyon <tomlanyon@google.com>
Tom Levy <tomlevy93@gmail.com>
@@ -2440,6 +2561,7 @@ Toshiki Shima <hayabusa1419@gmail.com>
Totoro W <tw19881113@gmail.com>
Travis Bischel <travis.bischel@gmail.com>
Travis Cline <travis.cline@gmail.com>
Trevor Dixon <trevordixon@gmail.com>
Trevor Strohman <trevor.strohman@gmail.com>
Trey Lawrence <lawrence.trey@gmail.com>
Trey Roessig <trey.roessig@gmail.com>
@@ -2463,6 +2585,7 @@ Tzach Shabtay <tzachshabtay@gmail.com>
Tzu-Chiao Yeh <su3g4284zo6y7@gmail.com>
Tzu-Jung Lee <roylee17@currant.com>
Udalov Max <re.udalov@gmail.com>
Uddeshya Singh <singhuddeshyaofficial@gmail.com>
Ugorji Nwoke <ugorji@gmail.com>
Ulf Holm Nielsen <doktor@dyregod.dk>
Ulrich Kunitz <uli.kunitz@gmail.com>
@@ -2475,6 +2598,7 @@ Vadim Grek <vadimprog@gmail.com>
Vadim Vygonets <unixdj@gmail.com>
Val Polouchkine <vpolouch@justin.tv>
Valentin Vidic <vvidic@valentin-vidic.from.hr>
Vaughn Iverson <vsivsi@yahoo.com>
Vee Zhang <veezhang@126.com> <vveezhang@gmail.com>
Vega Garcia Luis Alfonso <vegacom@gmail.com>
Venil Noronha <veniln@vmware.com>
@@ -2491,6 +2615,7 @@ Vincent Batts <vbatts@hashbangbash.com> <vbatts@gmail.com>
Vincent Vanackere <vincent.vanackere@gmail.com>
Vinu Rajashekhar <vinutheraj@gmail.com>
Vish Subramanian <vish@google.com>
Vishal Dalwadi <dalwadivishal26@gmail.com>
Vishvananda Ishaya <vishvananda@gmail.com>
Visweswara R <r.visweswara@gmail.com>
Vitaly Zdanevich <zdanevich.vitaly@ya.ru>
@@ -2542,6 +2667,7 @@ Willem van der Schyff <willemvds@gmail.com>
William Chan <willchan@chromium.org>
William Chang <mr.williamchang@gmail.com>
William Josephson <wjosephson@gmail.com>
William Langford <wlangfor@gmail.com>
William Orr <will@worrbase.com> <ay1244@gmail.com>
William Poussier <william.poussier@gmail.com>
Wisdom Omuya <deafgoat@gmail.com>
@@ -2550,6 +2676,7 @@ Xi Ruoyao <xry23333@gmail.com>
Xia Bin <snyh@snyh.org>
Xiangdong Ji <xiangdong.ji@arm.com>
Xiaodong Liu <teaofmoli@gmail.com>
Xing Gao <18340825824@163.com>
Xing Xing <mikespook@gmail.com>
Xingqang Bai <bxq2011hust@qq.com>
Xu Fei <badgangkiller@gmail.com>
@@ -2571,6 +2698,7 @@ Yasha Bubnov <girokompass@gmail.com>
Yasser Abdolmaleki <yasser@yasser.ca>
Yasuharu Goto <matope.ono@gmail.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
Yasutaka Shinzaki <shinzaki@yasu26.tech>
Yasuyuki Oka <yasuyk@gmail.com>
Yazen Shunnar <yazen.shunnar@gmail.com>
Yestin Sun <ylh@pdx.edu>
@@ -2583,14 +2711,18 @@ Yorman Arias <cixtords@gmail.com>
Yoshiyuki Kanno <nekotaroh@gmail.com> <yoshiyuki.kanno@stoic.co.jp>
Yoshiyuki Mineo <yoshiyuki.mineo@gmail.com>
Yosuke Akatsuka <yosuke.akatsuka@gmail.com>
Youfu Zhang <zhangyoufu@gmail.com>
Yu Heng Zhang <annita.zhang@cn.ibm.com>
Yu Xuan Zhang <zyxsh@cn.ibm.com>
Yu, Li-Yu <afg984@gmail.com>
Yuichi Kishimoto <yk2220s@gmail.com>
Yuichi Nishiwaki <yuichi.nishiwaki@gmail.com>
Yuji Yaginuma <yuuji.yaginuma@gmail.com>
Yuki Ito <mrno110y@gmail.com>
Yuki OKUSHI <huyuumi.dev@gmail.com>
Yuki Yugui Sonoda <yugui@google.com>
Yukihiro Nishinaka <6elpinal@gmail.com>
YunQiang Su <syq@debian.org>
Yury Smolsky <yury@smolsky.by>
Yusuke Kagiwada <block.rxckin.beats@gmail.com>
Yuusei Kuwana <kuwana@kumama.org>
@@ -2599,6 +2731,7 @@ Yves Junqueira <yvesj@google.com> <yves.junqueira@gmail.com>
Zac Bergquist <zbergquist99@gmail.com>
Zach Bintliff <zbintliff@gmail.com>
Zach Gershman <zachgersh@gmail.com>
Zach Hoffman <zrhoffman@apache.org>
Zach Jones <zachj1@gmail.com>
Zachary Amsden <zach@thundertoken.com>
Zachary Gershman <zgershman@pivotal.io>
@@ -2617,6 +2750,7 @@ Zhou Peng <p@ctriple.cn>
Ziad Hatahet <hatahet@gmail.com>
Ziheng Liu <lzhfromustc@gmail.com>
Zorion Arrizabalaga <zorionk@gmail.com>
Zvonimir Pavlinovic <zpavlinovic@google.com>
Zyad A. Ali <zyad.ali.me@gmail.com>
Максадбек Ахмедов <a.maksadbek@gmail.com>
Максим Федосеев <max.faceless.frei@gmail.com>

View File

@@ -0,0 +1,108 @@
pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (darwin-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (darwin-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (darwin-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (darwin-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (freebsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (freebsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (freebsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (freebsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (freebsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (freebsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (freebsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (freebsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (freebsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (freebsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (freebsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (freebsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (freebsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (freebsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (freebsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (freebsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (freebsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (freebsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (freebsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (freebsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (freebsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (linux-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (linux-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (linux-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (linux-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (linux-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (linux-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (linux-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (linux-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (linux-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (linux-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (linux-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (linux-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (linux-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (linux-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (linux-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (linux-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (linux-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (linux-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (linux-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (linux-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (linux-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (netbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (netbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (netbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (netbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (netbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (netbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (netbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (netbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (netbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (netbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (netbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (netbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (netbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (netbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (netbsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (netbsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (netbsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (netbsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (netbsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (netbsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (netbsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (netbsd-arm64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (netbsd-arm64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (netbsd-arm64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (netbsd-arm64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (netbsd-arm64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (netbsd-arm64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (netbsd-arm64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (openbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (openbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (openbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (openbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (openbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (openbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (openbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (openbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (windows-386), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error
pkg syscall (windows-386), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error
pkg syscall (windows-amd64), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error
pkg syscall (windows-amd64), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error

View File

@@ -166,7 +166,7 @@ jumps and branches.
</li>
<li>
<code>SP</code>: Stack pointer: top of stack.
<code>SP</code>: Stack pointer: the highest address within the local stack frame.
</li>
</ul>
@@ -216,7 +216,7 @@ If a Go prototype does not name its result, the expected assembly name is <code>
The <code>SP</code> pseudo-register is a virtual stack pointer
used to refer to frame-local variables and the arguments being
prepared for function calls.
It points to the top of the local stack frame, so references should use negative offsets
It points to the highest address within the local stack frame, so references should use negative offsets
in the range [framesize, 0):
<code>x-8(SP)</code>, <code>y-4(SP)</code>, and so on.
</p>
@@ -409,7 +409,7 @@ The linker will choose one of the duplicates to use.
(For <code>TEXT</code> items.)
Don't insert the preamble to check if the stack must be split.
The frame for the routine, plus anything it calls, must fit in the
spare space at the top of the stack segment.
spare space remaining in the current stack segment.
Used to protect routines such as the stack splitting code itself.
</li>
<li>
@@ -460,7 +460,7 @@ Only valid on functions that declare a frame size of 0.
<code>TOPFRAME</code> = 2048
<br>
(For <code>TEXT</code> items.)
Function is the top of the call stack. Traceback should stop at this function.
Function is the outermost frame of the call stack. Traceback should stop at this function.
</li>
</ul>

File diff suppressed because it is too large Load Diff

101
doc/go1.18.html Normal file
View File

@@ -0,0 +1,101 @@
<!--{
"Title": "Go 1.18 Release Notes",
"Path": "/doc/go1.18"
}-->
<!--
NOTE: In this document and others in this directory, the convention is to
set fixed-width phrases with non-fixed-width spaces, as in
<code>hello</code> <code>world</code>.
Do not send CLs removing the interior tags from such phrases.
-->
<style>
main ul li { margin: 0.5em 0; }
</style>
<h2 id="introduction">DRAFT RELEASE NOTES — Introduction to Go 1.18</h2>
<p>
<strong>
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.
</strong>
</p>
<h2 id="language">Changes to the language</h2>
<p>
TODO: complete this section
</p>
<h2 id="ports">Ports</h2>
<p>
TODO: complete this section, or delete if not needed
</p>
<h2 id="tools">Tools</h2>
<p>
TODO: complete this section, or delete if not needed
</p>
<h3 id="go-command">Go command</h3>
<p>
TODO: complete this section, or delete if not needed
</p>
<h2 id="runtime">Runtime</h2>
<p>
TODO: complete this section, or delete if not needed
</p>
<h2 id="compiler">Compiler</h2>
<p>
TODO: complete this section, or delete if not needed
</p>
<h2 id="linker">Linker</h2>
<p>
TODO: complete this section, or delete if not needed
</p>
<h2 id="library">Core library</h2>
<p>
TODO: complete this section
</p>
<h3 id="minor_library_changes">Minor changes to the library</h3>
<p>
As always, there are various minor changes and updates to the library,
made with the Go 1 <a href="/doc/go1compat">promise of compatibility</a>
in mind.
</p>
<p>
TODO: complete this section
</p>
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
<dd>
<p><!-- CL 336550 -->
The new function <a href="/pkg/syscall/?GOOS=windows#SyscallN"><code>SyscallN</code></a>
has been introduced for Windows, allowing for calls with arbitrary number
of arguments. As results,
<a href="/pkg/syscall/?GOOS=windows#Syscall"><code>Syscall</code></a>,
<a href="/pkg/syscall/?GOOS=windows#Syscall6"><code>Syscall6</code></a>,
<a href="/pkg/syscall/?GOOS=windows#Syscall9"><code>Syscall9</code></a>,
<a href="/pkg/syscall/?GOOS=windows#Syscall12"><code>Syscall12</code></a>,
<a href="/pkg/syscall/?GOOS=windows#Syscall15"><code>Syscall15</code></a>, and
<a href="/pkg/syscall/?GOOS=windows#Syscall18"><code>Syscall18</code></a> are
deprecated in favor of <a href="/pkg/syscall/?GOOS=windows#SyscallN"><code>SyscallN</code></a>.
</p>
</dd>
</dl><!-- syscall -->

View File

@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of Jul 26, 2021",
"Subtitle": "Version of Aug 23, 2021",
"Path": "/ref/spec"
}-->
@@ -3000,6 +3000,18 @@ method value; the saved copy is then used as the receiver in any calls,
which may be executed later.
</p>
<pre>
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
</pre>
<p>
The type <code>T</code> may be an interface or non-interface type.
</p>
@@ -4329,6 +4341,7 @@ a <a href="#Run_time_panics">run-time panic</a> occurs.
<pre>
s := make([]byte, 2, 4)
s0 := (*[0]byte)(s) // s0 != nil
s1 := (*[1]byte)(s[1:]) // &amp;s1[0] == &amp;s[1]
s2 := (*[2]byte)(s) // &amp;s2[0] == &amp;s[0]
s4 := (*[4]byte)(s) // panics: len([4]byte) > len(s)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

9
misc/cgo/test/testdata/issue43639.go vendored Normal file
View File

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

View File

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

View File

@@ -42,6 +42,7 @@ func TestMSAN(t *testing.T) {
{src: "msan5.go"},
{src: "msan6.go"},
{src: "msan7.go"},
{src: "msan8.go"},
{src: "msan_fail.go", wantErr: true},
}
for _, tc := range cases {

View File

@@ -0,0 +1,109 @@
// Copyright 2021 The Go Authors. 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 <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <sanitizer/msan_interface.h>
// cgoTracebackArg is the type of the argument passed to msanGoTraceback.
struct cgoTracebackArg {
uintptr_t context;
uintptr_t sigContext;
uintptr_t* buf;
uintptr_t max;
};
// msanGoTraceback is registered as the cgo traceback function.
// This will be called when a signal occurs.
void msanGoTraceback(void* parg) {
struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
arg->buf[0] = 0;
}
// msanGoWait will be called with all registers undefined as far as
// msan is concerned. It just waits for a signal.
// Because the registers are msan-undefined, the signal handler will
// be invoked with all registers msan-undefined.
__attribute__((noinline))
void msanGoWait(unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a6) {
sigset_t mask;
sigemptyset(&mask);
sigsuspend(&mask);
}
// msanGoSignalThread is the thread ID of the msanGoLoop thread.
static pthread_t msanGoSignalThread;
// msanGoSignalThreadSet is used to record that msanGoSignalThread
// has been initialized. This is accessed atomically.
static int32_t msanGoSignalThreadSet;
// uninit is explicitly poisoned, so that we can make all registers
// undefined by calling msanGoWait.
static unsigned long uninit;
// msanGoLoop loops calling msanGoWait, with the arguments passed
// such that msan thinks that they are undefined. msan permits
// undefined values to be used as long as they are not used to
// for conditionals or for memory access.
void msanGoLoop() {
int i;
msanGoSignalThread = pthread_self();
__atomic_store_n(&msanGoSignalThreadSet, 1, __ATOMIC_SEQ_CST);
// Force uninit to be undefined for msan.
__msan_poison(&uninit, sizeof uninit);
for (i = 0; i < 100; i++) {
msanGoWait(uninit, uninit, uninit, uninit, uninit, uninit);
}
}
// msanGoReady returns whether msanGoSignalThread is set.
int msanGoReady() {
return __atomic_load_n(&msanGoSignalThreadSet, __ATOMIC_SEQ_CST) != 0;
}
// msanGoSendSignal sends a signal to the msanGoLoop thread.
void msanGoSendSignal() {
pthread_kill(msanGoSignalThread, SIGWINCH);
}
*/
import "C"
import (
"runtime"
"time"
)
func main() {
runtime.SetCgoTraceback(0, C.msanGoTraceback, nil, nil)
c := make(chan bool)
go func() {
defer func() { c <- true }()
C.msanGoLoop()
}()
for C.msanGoReady() == 0 {
time.Sleep(time.Microsecond)
}
loop:
for {
select {
case <-c:
break loop
default:
C.msanGoSendSignal()
time.Sleep(time.Microsecond)
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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] }

View File

@@ -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{}

View File

@@ -1021,12 +1021,12 @@ func TestParsePAX(t *testing.T) {
func TestReadOldGNUSparseMap(t *testing.T) {
populateSparseMap := func(sa sparseArray, sps []string) []string {
for i := 0; len(sps) > 0 && i < sa.MaxEntries(); i++ {
copy(sa.Entry(i), sps[0])
for i := 0; len(sps) > 0 && i < sa.maxEntries(); i++ {
copy(sa.entry(i), sps[0])
sps = sps[1:]
}
if len(sps) > 0 {
copy(sa.IsExtended(), "\x80")
copy(sa.isExtended(), "\x80")
}
return sps
}
@@ -1034,19 +1034,19 @@ func TestReadOldGNUSparseMap(t *testing.T) {
makeInput := func(format Format, size string, sps ...string) (out []byte) {
// Write the initial GNU header.
var blk block
gnu := blk.GNU()
sparse := gnu.Sparse()
copy(gnu.RealSize(), size)
gnu := blk.toGNU()
sparse := gnu.sparse()
copy(gnu.realSize(), size)
sps = populateSparseMap(sparse, sps)
if format != FormatUnknown {
blk.SetFormat(format)
blk.setFormat(format)
}
out = append(out, blk[:]...)
// Write extended sparse blocks.
for len(sps) > 0 {
var blk block
sps = populateSparseMap(blk.Sparse(), sps)
sps = populateSparseMap(blk.toSparse(), sps)
out = append(out, blk[:]...)
}
return out
@@ -1359,7 +1359,7 @@ func TestFileReader(t *testing.T) {
wantCnt int64
wantErr error
}
testRemaining struct { // LogicalRemaining() == wantLCnt, PhysicalRemaining() == wantPCnt
testRemaining struct { // logicalRemaining() == wantLCnt, physicalRemaining() == wantPCnt
wantLCnt int64
wantPCnt int64
}
@@ -1596,11 +1596,11 @@ func TestFileReader(t *testing.T) {
t.Errorf("test %d.%d, expected %d more operations", i, j, len(f.ops))
}
case testRemaining:
if got := fr.LogicalRemaining(); got != tf.wantLCnt {
t.Errorf("test %d.%d, LogicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt)
if got := fr.logicalRemaining(); got != tf.wantLCnt {
t.Errorf("test %d.%d, logicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt)
}
if got := fr.PhysicalRemaining(); got != tf.wantPCnt {
t.Errorf("test %d.%d, PhysicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt)
if got := fr.physicalRemaining(); got != tf.wantPCnt {
t.Errorf("test %d.%d, physicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt)
}
default:
t.Fatalf("test %d.%d, unknown test operation: %T", i, j, tf)

View File

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

View File

@@ -987,11 +987,11 @@ func TestIssue12594(t *testing.T) {
// The prefix field should never appear in the GNU format.
var blk block
copy(blk[:], b.Bytes())
prefix := string(blk.USTAR().Prefix())
prefix := string(blk.toUSTAR().prefix())
if i := strings.IndexByte(prefix, 0); i >= 0 {
prefix = prefix[:i] // Truncate at the NUL terminator
}
if blk.GetFormat() == FormatGNU && len(prefix) > 0 && strings.HasPrefix(name, prefix) {
if blk.getFormat() == FormatGNU && len(prefix) > 0 && strings.HasPrefix(name, prefix) {
t.Errorf("test %d, found prefix in GNU format: %s", i, prefix)
}
@@ -1029,7 +1029,7 @@ func TestFileWriter(t *testing.T) {
wantCnt int64
wantErr error
}
testRemaining struct { // LogicalRemaining() == wantLCnt, PhysicalRemaining() == wantPCnt
testRemaining struct { // logicalRemaining() == wantLCnt, physicalRemaining() == wantPCnt
wantLCnt int64
wantPCnt int64
}
@@ -1292,11 +1292,11 @@ func TestFileWriter(t *testing.T) {
t.Errorf("test %d.%d, expected %d more operations", i, j, len(f.ops))
}
case testRemaining:
if got := fw.LogicalRemaining(); got != tf.wantLCnt {
t.Errorf("test %d.%d, LogicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt)
if got := fw.logicalRemaining(); got != tf.wantLCnt {
t.Errorf("test %d.%d, logicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt)
}
if got := fw.PhysicalRemaining(); got != tf.wantPCnt {
t.Errorf("test %d.%d, PhysicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt)
if got := fw.physicalRemaining(); got != tf.wantPCnt {
t.Errorf("test %d.%d, physicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt)
}
default:
t.Fatalf("test %d.%d, unknown test operation: %T", i, j, tf)

View File

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

View File

@@ -1384,3 +1384,21 @@ func TestCVE202133196(t *testing.T) {
t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
}
}
func TestCVE202139293(t *testing.T) {
// directory size is so large, that the check in Reader.init
// overflows when subtracting from the archive size, causing
// the pre-allocation check to be bypassed.
data := []byte{
0x50, 0x4b, 0x06, 0x06, 0x05, 0x06, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0x50, 0xfe, 0x00, 0xff, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xff,
}
_, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err != ErrFormat {
t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
}
}

View File

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

View File

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

View File

@@ -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"
@@ -419,4 +419,8 @@ TEXT errors(SB),$0
ADD R1>>2, RSP, R3 // ERROR "illegal combination"
ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference"
CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4"
MOVD.P y+8(FP), R1 // ERROR "illegal combination"
MOVD.W x-8(SP), R1 // ERROR "illegal combination"
LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination"
LDP.W x+8(SP), (R0, R1) // ERROR "illegal combination"
RET

View File

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

View File

@@ -505,6 +505,128 @@ control bits specified by the ELF AMD64 ABI.
The x87 floating-point control word is not used by Go on amd64.
### arm64 architecture
The arm64 architecture uses R0 R15 for integer arguments and results.
It uses F0 F15 for floating-point arguments and results.
*Rationale*: 16 integer registers and 16 floating-point registers are
more than enough for passing arguments and results for practically all
functions (see Appendix). While there are more registers available,
using more registers provides little benefit. Additionally, it will add
overhead on code paths where the number of arguments are not statically
known (e.g. reflect call), and will consume more stack space when there
is only limited stack space available to fit in the nosplit limit.
Registers R16 and R17 are permanent scratch registers. They are also
used as scratch registers by the linker (Go linker and external
linker) in trampolines.
Register R18 is reserved and never used. It is reserved for the OS
on some platforms (e.g. macOS).
Registers R19 R25 are permanent scratch registers. In addition,
R27 is a permanent scratch register used by the assembler when
expanding instructions.
Floating-point registers F16 F31 are also permanent scratch
registers.
Special-purpose registers are as follows:
| Register | Call meaning | Return meaning | Body meaning |
| --- | --- | --- | --- |
| RSP | Stack pointer | Same | Same |
| R30 | Link register | Same | Scratch (non-leaf functions) |
| R29 | Frame pointer | Same | Same |
| R28 | Current goroutine | Same | Same |
| R27 | Scratch | Scratch | Scratch |
| R26 | Closure context pointer | Scratch | Scratch |
| R18 | Reserved (not used) | Same | Same |
| ZR | Zero value | Same | Same |
*Rationale*: These register meanings are compatible with Gos
stack-based calling convention.
*Rationale*: The link register, R30, holds the function return
address at the function entry. For functions that have frames
(including most non-leaf functions), R30 is saved to stack in the
function prologue and restored in the epilogue. Within the function
body, R30 can be used as a scratch register.
*Implementation note*: Registers with fixed meaning at calls but not
in function bodies must be initialized by "injected" calls such as
signal-based panics.
#### Stack layout
The stack pointer, RSP, grows down and is always aligned to 16 bytes.
*Rationale*: The arm64 architecture requires the stack pointer to be
16-byte aligned.
A function's stack frame, after the frame is created, is laid out as
follows:
+------------------------------+
| ... locals ... |
| ... outgoing arguments ... |
| return PC | ← RSP points to
| frame pointer on entry |
+------------------------------+ ↓ lower addresses
The "return PC" is loaded to the link register, R30, as part of the
arm64 `CALL` operation.
On entry, a function subtracts from RSP to open its stack frame, and
saves the values of R30 and R29 at the bottom of the frame.
Specifically, R30 is saved at 0(RSP) and R29 is saved at -8(RSP),
after RSP is updated.
A leaf function that does not require any stack space may omit the
saved R30 and R29.
The Go ABI's use of R29 as a frame pointer register is compatible with
arm64 architecture requirement so that Go can inter-operate with platform
debuggers and profilers.
This stack layout is used by both register-based (ABIInternal) and
stack-based (ABI0) calling conventions.
#### Flags
The arithmetic status flags (NZCV) are treated like scratch registers
and not preserved across calls.
All other bits in PSTATE are system flags and are not modified by Go.
The floating-point status register (FPSR) is treated like scratch
registers and not preserved across calls.
At calls, the floating-point control register (FPCR) bits are always
set as follows:
| Flag | Bit | Value | Meaning |
| --- | --- | --- | --- |
| DN | 25 | 0 | Propagate NaN operands |
| FZ | 24 | 0 | Do not flush to zero |
| RC | 23/22 | 0 (RN) | Round to nearest, choose even if tied |
| IDE | 15 | 0 | Denormal operations trap disabled |
| IXE | 12 | 0 | Inexact trap disabled |
| UFE | 11 | 0 | Underflow trap disabled |
| OFE | 10 | 0 | Overflow trap disabled |
| DZE | 9 | 0 | Divide-by-zero trap disabled |
| IOE | 8 | 0 | Invalid operations trap disabled |
| NEP | 2 | 0 | Scalar operations do not affect higher elements in vector registers |
| AH | 1 | 0 | No alternate handling of de-normal inputs |
| FIZ | 0 | 0 | Do not zero de-normals |
*Rationale*: Having a fixed FPCR control configuration allows Go
functions to use floating-point and vector (SIMD) operations without
modifying or saving the FPCR.
Functions are allowed to modify it between calls (as long as they
restore it), but as of this writing Go code never does.
## Future directions
### Spill path improvements

View File

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

View File

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

View File

@@ -823,7 +823,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Reg = v.Args[0].Reg()
ssagen.AddAux2(&p.To, v, sc.Off64())
case ssa.OpAMD64MOVOstorezero:
if !buildcfg.Experiment.RegabiG || s.ABI != obj.ABIInternal {
if s.ABI != obj.ABIInternal {
// zero X15 manually
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
}
@@ -914,7 +914,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpAMD64DUFFZERO:
if !buildcfg.Experiment.RegabiG || s.ABI != obj.ABIInternal {
if s.ABI != obj.ABIInternal {
// zero X15 manually
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
}
@@ -997,22 +997,26 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
// Closure pointer is DX.
ssagen.CheckLoweredGetClosurePtr(v)
case ssa.OpAMD64LoweredGetG:
if buildcfg.Experiment.RegabiG && s.ABI == obj.ABIInternal {
if s.ABI == obj.ABIInternal {
v.Fatalf("LoweredGetG should not appear in ABIInternal")
}
r := v.Reg()
getgFromTLS(s, r)
case ssa.OpAMD64CALLstatic:
if buildcfg.Experiment.RegabiG && s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal {
if s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal {
// zeroing X15 when entering ABIInternal from ABI0
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
}
// set G register from TLS
getgFromTLS(s, x86.REG_R14)
}
s.Call(v)
if buildcfg.Experiment.RegabiG && s.ABI == obj.ABIInternal && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABI0 {
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)
}
@@ -1304,9 +1308,11 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
case ssa.BlockRet:
s.Prog(obj.ARET)
case ssa.BlockRetJmp:
if buildcfg.Experiment.RegabiG && s.ABI == obj.ABI0 && b.Aux.(*obj.LSym).ABI() == obj.ABIInternal {
if s.ABI == obj.ABI0 && b.Aux.(*obj.LSym).ABI() == obj.ABIInternal {
// zeroing X15 when entering ABIInternal from ABI0
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)
}
@@ -1348,20 +1354,15 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
}
}
func loadRegResults(s *ssagen.State, f *ssa.Func) {
for _, o := range f.OwnAux.ABIInfo().OutParams() {
n := o.Name.(*ir.Name)
rts, offs := o.RegisterTypesAndOffsets()
for i := range o.Registers {
p := s.Prog(loadByType(rts[i]))
p.From.Type = obj.TYPE_MEM
p.From.Name = obj.NAME_AUTO
p.From.Sym = n.Linksym()
p.From.Offset = n.FrameOffset() + offs[i]
p.To.Type = obj.TYPE_REG
p.To.Reg = ssa.ObjRegForAbiReg(o.Registers[i], f.Config)
}
}
func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
p := s.Prog(loadByType(t))
p.From.Type = obj.TYPE_MEM
p.From.Name = obj.NAME_AUTO
p.From.Sym = n.Linksym()
p.From.Offset = n.FrameOffset() + off
p.To.Type = obj.TYPE_REG
p.To.Reg = reg
return p
}
func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {

View File

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

View File

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

View File

@@ -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"
@@ -161,6 +162,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,
@@ -1101,8 +1114,34 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
v.Fatalf("FlagConstant op should never make it to codegen %v", v.LongString())
case ssa.OpARM64InvertFlags:
v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
case ssa.OpClobber, ssa.OpClobberReg:
// TODO: implement for clobberdead experiment. Nop is ok for now.
case ssa.OpClobber:
// MOVW $0xdeaddead, REGTMP
// MOVW REGTMP, (slot)
// MOVW REGTMP, 4(slot)
p := s.Prog(arm64.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0xdeaddead
p.To.Type = obj.TYPE_REG
p.To.Reg = arm64.REGTMP
p = s.Prog(arm64.AMOVW)
p.From.Type = obj.TYPE_REG
p.From.Reg = arm64.REGTMP
p.To.Type = obj.TYPE_MEM
p.To.Reg = arm64.REGSP
ssagen.AddAux(&p.To, v)
p = s.Prog(arm64.AMOVW)
p.From.Type = obj.TYPE_REG
p.From.Reg = arm64.REGTMP
p.To.Type = obj.TYPE_MEM
p.To.Reg = arm64.REGSP
ssagen.AddAux2(&p.To, v, v.AuxInt+4)
case ssa.OpClobberReg:
x := uint64(0xdeaddeaddeaddead)
p := s.Prog(arm64.AMOVD)
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(x)
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
default:
v.Fatalf("genValue not implemented: %s", v.LongString())
}
@@ -1266,3 +1305,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
}

View File

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

View File

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

View File

@@ -44,8 +44,11 @@ type DebugFlags struct {
Panic int `help:"show all compiler panics"`
Slice int `help:"print information about slice compilation"`
SoftFloat int `help:"force compiler to emit soft-float code"`
SyncFrames int `help:"how many writer stack frames to include at sync points in unified export data"`
TypeAssert int `help:"print information about type assertion inlining"`
TypecheckInl int `help:"eager typechecking of inline function bodies"`
Unified int `help:"enable unified IR construction"`
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"`

View File

@@ -140,6 +140,7 @@ type CmdFlags struct {
// ParseFlags parses the command-line flags into Flag.
func ParseFlags() {
Flag.G = 3
Flag.I = addImportDir
Flag.LowerC = 1
@@ -159,7 +160,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

View File

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

View File

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

View File

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

View File

@@ -38,6 +38,7 @@ func Func(fn *ir.Func) {
}
}
ir.VisitList(fn.Body, markHiddenClosureDead)
fn.Body = []ir.Node{ir.NewBlockStmt(base.Pos, nil)}
}
@@ -62,9 +63,11 @@ func stmts(nn *ir.Nodes) {
if ir.IsConst(n.Cond, constant.Bool) {
var body ir.Nodes
if ir.BoolVal(n.Cond) {
ir.VisitList(n.Else, markHiddenClosureDead)
n.Else = ir.Nodes{}
body = n.Body
} else {
ir.VisitList(n.Body, markHiddenClosureDead)
n.Body = ir.Nodes{}
body = n.Else
}
@@ -150,3 +153,13 @@ func expr(n ir.Node) ir.Node {
}
return n
}
func markHiddenClosureDead(n ir.Node) {
if n.Op() != ir.OCLOSURE {
return
}
clo := n.(*ir.ClosureExpr)
if clo.Func.IsHiddenClosure() {
clo.Func.SetIsDeadcodeClosure(true)
}
}

View File

@@ -214,7 +214,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir
Type: base.Ctxt.Lookup(typename),
DeclFile: declpos.RelFilename(),
DeclLine: declpos.RelLine(),
DeclCol: declpos.Col(),
DeclCol: declpos.RelCol(),
InlIndex: int32(inlIndex),
ChildIndex: -1,
})
@@ -371,7 +371,7 @@ func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
Type: base.Ctxt.Lookup(typename),
DeclFile: declpos.RelFilename(),
DeclLine: declpos.RelLine(),
DeclCol: declpos.Col(),
DeclCol: declpos.RelCol(),
InlIndex: int32(inlIndex),
ChildIndex: -1,
}
@@ -475,7 +475,7 @@ func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var
StackOffset: ssagen.StackOffset(debug.Slots[debug.VarSlots[varID][0]]),
DeclFile: declpos.RelFilename(),
DeclLine: declpos.RelLine(),
DeclCol: declpos.Col(),
DeclCol: declpos.RelCol(),
InlIndex: int32(inlIndex),
ChildIndex: -1,
}

View File

@@ -244,7 +244,7 @@ func makePreinlineDclMap(fnsym *obj.LSym) map[varPos]int {
DeclName: unversion(n.Sym().Name),
DeclFile: pos.RelFilename(),
DeclLine: pos.RelLine(),
DeclCol: pos.Col(),
DeclCol: pos.RelCol(),
}
if _, found := m[vp]; found {
// We can see collisions (variables with the same name/file/line/col) in obfuscated or machine-generated code -- see issue 44378 for an example. Skip duplicates in such cases, since it is unlikely that a human will be debugging such code.

View File

@@ -0,0 +1,120 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package escape
import (
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
)
// addr evaluates an addressable expression n and returns a hole
// that represents storing into the represented location.
func (e *escape) addr(n ir.Node) hole {
if n == nil || ir.IsBlank(n) {
// Can happen in select case, range, maybe others.
return e.discardHole()
}
k := e.heapHole()
switch n.Op() {
default:
base.Fatalf("unexpected addr: %v", n)
case ir.ONAME:
n := n.(*ir.Name)
if n.Class == ir.PEXTERN {
break
}
k = e.oldLoc(n).asHole()
case ir.OLINKSYMOFFSET:
break
case ir.ODOT:
n := n.(*ir.SelectorExpr)
k = e.addr(n.X)
case ir.OINDEX:
n := n.(*ir.IndexExpr)
e.discard(n.Index)
if n.X.Type().IsArray() {
k = e.addr(n.X)
} else {
e.discard(n.X)
}
case ir.ODEREF, ir.ODOTPTR:
e.discard(n)
case ir.OINDEXMAP:
n := n.(*ir.IndexExpr)
e.discard(n.X)
e.assignHeap(n.Index, "key of map put", n)
}
return k
}
func (e *escape) addrs(l ir.Nodes) []hole {
var ks []hole
for _, n := range l {
ks = append(ks, e.addr(n))
}
return ks
}
func (e *escape) assignHeap(src ir.Node, why string, where ir.Node) {
e.expr(e.heapHole().note(where, why), src)
}
// assignList evaluates the assignment dsts... = srcs....
func (e *escape) assignList(dsts, srcs []ir.Node, why string, where ir.Node) {
ks := e.addrs(dsts)
for i, k := range ks {
var src ir.Node
if i < len(srcs) {
src = srcs[i]
}
if dst := dsts[i]; dst != nil {
// Detect implicit conversion of uintptr to unsafe.Pointer when
// storing into reflect.{Slice,String}Header.
if dst.Op() == ir.ODOTPTR && ir.IsReflectHeaderDataField(dst) {
e.unsafeValue(e.heapHole().note(where, why), src)
continue
}
// Filter out some no-op assignments for escape analysis.
if src != nil && isSelfAssign(dst, src) {
if base.Flag.LowerM != 0 {
base.WarnfAt(where.Pos(), "%v ignoring self-assignment in %v", e.curfn, where)
}
k = e.discardHole()
}
}
e.expr(k.note(where, why), src)
}
e.reassigned(ks, where)
}
// reassigned marks the locations associated with the given holes as
// reassigned, unless the location represents a variable declared and
// assigned exactly once by where.
func (e *escape) reassigned(ks []hole, where ir.Node) {
if as, ok := where.(*ir.AssignStmt); ok && as.Op() == ir.OAS && as.Y == nil {
if dst, ok := as.X.(*ir.Name); ok && dst.Op() == ir.ONAME && dst.Defn == nil {
// Zero-value assignment for variable declared without an
// explicit initial value. Assume this is its initialization
// statement.
return
}
}
for _, k := range ks {
loc := k.dst
// Variables declared by range statements are assigned on every iteration.
if n, ok := loc.n.(*ir.Name); ok && n.Defn == where && where.Op() != ir.ORANGE {
continue
}
loc.reassigned = true
}
}

View File

@@ -0,0 +1,428 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package escape
import (
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/src"
)
// call evaluates a call expressions, including builtin calls. ks
// should contain the holes representing where the function callee's
// results flows.
func (e *escape) call(ks []hole, call ir.Node) {
var init ir.Nodes
e.callCommon(ks, call, &init, nil)
if len(init) != 0 {
call.(*ir.CallExpr).PtrInit().Append(init...)
}
}
func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir.Func) {
// argumentPragma handles escape analysis of argument *argp to the
// given hole. If the function callee is known, pragma is the
// function's pragma flags; otherwise 0.
argumentFunc := func(fn *ir.Name, k hole, argp *ir.Node) {
e.rewriteArgument(argp, init, call, fn, wrapper)
e.expr(k.note(call, "call parameter"), *argp)
}
argument := func(k hole, argp *ir.Node) {
argumentFunc(nil, k, argp)
}
switch call.Op() {
default:
ir.Dump("esc", call)
base.Fatalf("unexpected call op: %v", call.Op())
case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER:
call := call.(*ir.CallExpr)
typecheck.FixVariadicCall(call)
typecheck.FixMethodCall(call)
// Pick out the function callee, if statically known.
//
// TODO(mdempsky): Change fn from *ir.Name to *ir.Func, but some
// functions (e.g., runtime builtins, method wrappers, generated
// eq/hash functions) don't have it set. Investigate whether
// that's a concern.
var fn *ir.Name
switch call.Op() {
case ir.OCALLFUNC:
// If we have a direct call to a closure (not just one we were
// able to statically resolve with ir.StaticValue), mark it as
// such so batch.outlives can optimize the flow results.
if call.X.Op() == ir.OCLOSURE {
call.X.(*ir.ClosureExpr).Func.SetClosureCalled(true)
}
switch v := ir.StaticValue(call.X); v.Op() {
case ir.ONAME:
if v := v.(*ir.Name); v.Class == ir.PFUNC {
fn = v
}
case ir.OCLOSURE:
fn = v.(*ir.ClosureExpr).Func.Nname
case ir.OMETHEXPR:
fn = ir.MethodExprName(v)
}
case ir.OCALLMETH:
base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
}
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))
}
}
var recvp *ir.Node
if call.Op() == ir.OCALLFUNC {
// Evaluate callee function expression.
//
// Note: We use argument and not argumentFunc, because while
// call.X here may be an argument to runtime.{new,defer}proc,
// it's not an argument to fn itself.
argument(e.discardHole(), &call.X)
} else {
recvp = &call.X.(*ir.SelectorExpr).X
}
args := call.Args
if recv := fntype.Recv(); recv != nil {
if recvp == nil {
// Function call using method expression. Recevier argument is
// at the front of the regular arguments list.
recvp = &args[0]
args = args[1:]
}
argumentFunc(fn, e.tagHole(ks, fn, recv), recvp)
}
for i, param := range fntype.Params().FieldSlice() {
argumentFunc(fn, e.tagHole(ks, fn, param), &args[i])
}
case ir.OINLCALL:
call := call.(*ir.InlinedCallExpr)
e.stmts(call.Body)
for i, result := range call.ReturnVars {
k := e.discardHole()
if ks != nil {
k = ks[i]
}
e.expr(k, result)
}
case ir.OAPPEND:
call := call.(*ir.CallExpr)
args := call.Args
// 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 i := 1; i < len(args); i++ {
argument(e.heapHole(), &args[i])
}
}
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)
fixRecoverCall(call)
for i := range call.Args {
argument(e.discardHole(), &call.Args[i])
}
case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE:
call := call.(*ir.UnaryExpr)
argument(e.discardHole(), &call.X)
case ir.OUNSAFEADD, ir.OUNSAFESLICE:
call := call.(*ir.BinaryExpr)
argument(ks[0], &call.X)
argument(e.discardHole(), &call.Y)
}
}
// goDeferStmt analyzes a "go" or "defer" statement.
//
// In the process, it also normalizes the statement to always use a
// simple function call with no arguments and no results. For example,
// it rewrites:
//
// defer f(x, y)
//
// into:
//
// x1, y1 := x, y
// defer func() { f(x1, y1) }()
func (e *escape) goDeferStmt(n *ir.GoDeferStmt) {
k := e.heapHole()
if n.Op() == ir.ODEFER && e.loopDepth == 1 {
// Top-level defer arguments don't escape to the heap,
// but they do need to last until they're invoked.
k = e.later(e.discardHole())
// force stack allocation of defer record, unless
// open-coded defers are used (see ssa.go)
n.SetEsc(ir.EscNever)
}
call := n.Call
init := n.PtrInit()
init.Append(ir.TakeInit(call)...)
e.stmts(*init)
// If the function is already a zero argument/result function call,
// just escape analyze it normally.
if call, ok := call.(*ir.CallExpr); ok && call.Op() == ir.OCALLFUNC {
if sig := call.X.Type(); sig.NumParams()+sig.NumResults() == 0 {
if clo, ok := call.X.(*ir.ClosureExpr); ok && n.Op() == ir.OGO {
clo.IsGoWrap = true
}
e.expr(k, call.X)
return
}
}
// Create a new no-argument function that we'll hand off to defer.
fn := ir.NewClosureFunc(n.Pos(), true)
fn.SetWrapper(true)
fn.Nname.SetType(types.NewSignature(types.LocalPkg, nil, nil, nil, nil))
fn.Body = []ir.Node{call}
clo := fn.OClosure
if n.Op() == ir.OGO {
clo.IsGoWrap = true
}
e.callCommon(nil, call, init, fn)
e.closures = append(e.closures, closure{e.spill(k, clo), clo})
// Create new top level call to closure.
n.Call = ir.NewCallExpr(call.Pos(), ir.OCALL, clo, nil)
ir.WithFunc(e.curfn, func() {
typecheck.Stmt(n.Call)
})
}
// rewriteArgument rewrites the argument *argp of the given call expression.
// fn is the static callee function, if known.
// wrapper is the go/defer wrapper function for call, if any.
func (e *escape) rewriteArgument(argp *ir.Node, init *ir.Nodes, call ir.Node, fn *ir.Name, wrapper *ir.Func) {
var pragma ir.PragmaFlag
if fn != nil && fn.Func != nil {
pragma = fn.Func.Pragma
}
// unsafeUintptr rewrites "uintptr(ptr)" arguments to syscall-like
// functions, so that ptr is kept alive and/or escaped as
// appropriate. unsafeUintptr also reports whether it modified arg0.
unsafeUintptr := func(arg0 ir.Node) bool {
if pragma&(ir.UintptrKeepAlive|ir.UintptrEscapes) == 0 {
return false
}
// If the argument is really a pointer being converted to uintptr,
// arrange for the pointer to be kept alive until the call returns,
// by copying it into a temp and marking that temp
// still alive when we pop the temp stack.
if arg0.Op() != ir.OCONVNOP || !arg0.Type().IsUintptr() {
return false
}
arg := arg0.(*ir.ConvExpr)
if !arg.X.Type().IsUnsafePtr() {
return false
}
// Create and declare a new pointer-typed temp variable.
tmp := e.wrapExpr(arg.Pos(), &arg.X, init, call, wrapper)
if pragma&ir.UintptrEscapes != 0 {
e.flow(e.heapHole().note(arg, "//go:uintptrescapes"), e.oldLoc(tmp))
}
if pragma&ir.UintptrKeepAlive != 0 {
call := call.(*ir.CallExpr)
// SSA implements CallExpr.KeepAlive using OpVarLive, which
// doesn't support PAUTOHEAP variables. I tried changing it to
// use OpKeepAlive, but that ran into issues of its own.
// For now, the easy solution is to explicitly copy to (yet
// another) new temporary variable.
keep := tmp
if keep.Class == ir.PAUTOHEAP {
keep = e.copyExpr(arg.Pos(), tmp, call.PtrInit(), wrapper, false)
}
keep.SetAddrtaken(true) // ensure SSA keeps the tmp variable
call.KeepAlive = append(call.KeepAlive, keep)
}
return true
}
visit := func(pos src.XPos, argp *ir.Node) {
// Optimize a few common constant expressions. By leaving these
// untouched in the call expression, we let the wrapper handle
// evaluating them, rather than taking up closure context space.
switch arg := *argp; arg.Op() {
case ir.OLITERAL, ir.ONIL, ir.OMETHEXPR:
return
case ir.ONAME:
if arg.(*ir.Name).Class == ir.PFUNC {
return
}
}
if unsafeUintptr(*argp) {
return
}
if wrapper != nil {
e.wrapExpr(pos, argp, init, call, wrapper)
}
}
// Peel away any slice lits.
if arg := *argp; arg.Op() == ir.OSLICELIT {
list := arg.(*ir.CompLitExpr).List
for i := range list {
visit(arg.Pos(), &list[i])
}
} else {
visit(call.Pos(), argp)
}
}
// wrapExpr replaces *exprp with a temporary variable copy. If wrapper
// is non-nil, the variable will be captured for use within that
// function.
func (e *escape) wrapExpr(pos src.XPos, exprp *ir.Node, init *ir.Nodes, call ir.Node, wrapper *ir.Func) *ir.Name {
tmp := e.copyExpr(pos, *exprp, init, e.curfn, true)
if wrapper != nil {
// Currently for "defer i.M()" if i is nil it panics at the point
// of defer statement, not when deferred function is called. We
// need to do the nil check outside of the wrapper.
if call.Op() == ir.OCALLINTER && exprp == &call.(*ir.CallExpr).X.(*ir.SelectorExpr).X {
check := ir.NewUnaryExpr(pos, ir.OCHECKNIL, ir.NewUnaryExpr(pos, ir.OITAB, tmp))
init.Append(typecheck.Stmt(check))
}
e.oldLoc(tmp).captured = true
tmp = ir.NewClosureVar(pos, wrapper, tmp)
}
*exprp = tmp
return tmp
}
// copyExpr creates and returns a new temporary variable within fn;
// appends statements to init to declare and initialize it to expr;
// and escape analyzes the data flow if analyze is true.
func (e *escape) copyExpr(pos src.XPos, expr ir.Node, init *ir.Nodes, fn *ir.Func, analyze bool) *ir.Name {
if ir.HasUniquePos(expr) {
pos = expr.Pos()
}
tmp := typecheck.TempAt(pos, fn, expr.Type())
stmts := []ir.Node{
ir.NewDecl(pos, ir.ODCL, tmp),
ir.NewAssignStmt(pos, tmp, expr),
}
typecheck.Stmts(stmts)
init.Append(stmts...)
if analyze {
e.newLoc(tmp, false)
e.stmts(stmts)
}
return tmp
}
// tagHole returns a hole for evaluating an argument passed to param.
// 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.
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...)
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -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().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()
}

View File

@@ -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 = &note{
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
}

View File

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

View File

@@ -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)] == '.'
}

View File

@@ -0,0 +1,207 @@
// 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:
// TODO(mdempsky): Treat like a normal call? esc.go used to just ignore it.
}
}
func (e *escape) stmts(l ir.Nodes) {
for _, n := range l {
e.stmt(n)
}
}
// block is like stmts, but preserves loopDepth.
func (e *escape) block(l ir.Nodes) {
old := e.loopDepth
e.stmts(l)
e.loopDepth = old
}
func (e *escape) dcl(n *ir.Name) hole {
if n.Curfn != e.curfn || n.IsClosureVar() {
base.Fatalf("bad declaration of %v", n)
}
loc := e.oldLoc(n)
loc.loopDepth = e.loopDepth
return loc.asHole()
}

View File

@@ -0,0 +1,215 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package escape
import (
"cmd/compile/internal/ir"
"cmd/compile/internal/typecheck"
)
func isSliceSelfAssign(dst, src ir.Node) bool {
// Detect the following special case.
//
// func (b *Buffer) Foo() {
// n, m := ...
// b.buf = b.buf[n:m]
// }
//
// This assignment is a no-op for escape analysis,
// it does not store any new pointers into b that were not already there.
// However, without this special case b will escape, because we assign to OIND/ODOTPTR.
// Here we assume that the statement will not contain calls,
// that is, that order will move any calls to init.
// Otherwise base ONAME value could change between the moments
// when we evaluate it for dst and for src.
// dst is ONAME dereference.
var dstX ir.Node
switch dst.Op() {
default:
return false
case ir.ODEREF:
dst := dst.(*ir.StarExpr)
dstX = dst.X
case ir.ODOTPTR:
dst := dst.(*ir.SelectorExpr)
dstX = dst.X
}
if dstX.Op() != ir.ONAME {
return false
}
// src is a slice operation.
switch src.Op() {
case ir.OSLICE, ir.OSLICE3, ir.OSLICESTR:
// OK.
case ir.OSLICEARR, ir.OSLICE3ARR:
// Since arrays are embedded into containing object,
// slice of non-pointer array will introduce a new pointer into b that was not already there
// (pointer to b itself). After such assignment, if b contents escape,
// b escapes as well. If we ignore such OSLICEARR, we will conclude
// that b does not escape when b contents do.
//
// Pointer to an array is OK since it's not stored inside b directly.
// For slicing an array (not pointer to array), there is an implicit OADDR.
// We check that to determine non-pointer array slicing.
src := src.(*ir.SliceExpr)
if src.X.Op() == ir.OADDR {
return false
}
default:
return false
}
// slice is applied to ONAME dereference.
var baseX ir.Node
switch base := src.(*ir.SliceExpr).X; base.Op() {
default:
return false
case ir.ODEREF:
base := base.(*ir.StarExpr)
baseX = base.X
case ir.ODOTPTR:
base := base.(*ir.SelectorExpr)
baseX = base.X
}
if baseX.Op() != ir.ONAME {
return false
}
// dst and src reference the same base ONAME.
return dstX.(*ir.Name) == baseX.(*ir.Name)
}
// isSelfAssign reports whether assignment from src to dst can
// be ignored by the escape analysis as it's effectively a self-assignment.
func isSelfAssign(dst, src ir.Node) bool {
if isSliceSelfAssign(dst, src) {
return true
}
// Detect trivial assignments that assign back to the same object.
//
// It covers these cases:
// val.x = val.y
// val.x[i] = val.y[j]
// val.x1.x2 = val.x1.y2
// ... etc
//
// These assignments do not change assigned object lifetime.
if dst == nil || src == nil || dst.Op() != src.Op() {
return false
}
// The expression prefix must be both "safe" and identical.
switch dst.Op() {
case ir.ODOT, ir.ODOTPTR:
// Safe trailing accessors that are permitted to differ.
dst := dst.(*ir.SelectorExpr)
src := src.(*ir.SelectorExpr)
return ir.SameSafeExpr(dst.X, src.X)
case ir.OINDEX:
dst := dst.(*ir.IndexExpr)
src := src.(*ir.IndexExpr)
if mayAffectMemory(dst.Index) || mayAffectMemory(src.Index) {
return false
}
return ir.SameSafeExpr(dst.X, src.X)
default:
return false
}
}
// mayAffectMemory reports whether evaluation of n may affect the program's
// memory state. If the expression can't affect memory state, then it can be
// safely ignored by the escape analysis.
func mayAffectMemory(n ir.Node) bool {
// We may want to use a list of "memory safe" ops instead of generally
// "side-effect free", which would include all calls and other ops that can
// allocate or change global state. For now, it's safer to start with the latter.
//
// We're ignoring things like division by zero, index out of range,
// and nil pointer dereference here.
// TODO(rsc): It seems like it should be possible to replace this with
// an ir.Any looking for any op that's not the ones in the case statement.
// But that produces changes in the compiled output detected by buildall.
switch n.Op() {
case ir.ONAME, ir.OLITERAL, ir.ONIL:
return false
case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD:
n := n.(*ir.BinaryExpr)
return mayAffectMemory(n.X) || mayAffectMemory(n.Y)
case ir.OINDEX:
n := n.(*ir.IndexExpr)
return mayAffectMemory(n.X) || mayAffectMemory(n.Index)
case ir.OCONVNOP, ir.OCONV:
n := n.(*ir.ConvExpr)
return mayAffectMemory(n.X)
case ir.OLEN, ir.OCAP, ir.ONOT, ir.OBITNOT, ir.OPLUS, ir.ONEG, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
n := n.(*ir.UnaryExpr)
return mayAffectMemory(n.X)
case ir.ODOT, ir.ODOTPTR:
n := n.(*ir.SelectorExpr)
return mayAffectMemory(n.X)
case ir.ODEREF:
n := n.(*ir.StarExpr)
return mayAffectMemory(n.X)
default:
return true
}
}
// HeapAllocReason returns the reason the given Node must be heap
// allocated, or the empty string if it doesn't.
func HeapAllocReason(n ir.Node) string {
if n == nil || n.Type() == nil {
return ""
}
// Parameters are always passed via the stack.
if n.Op() == ir.ONAME {
n := n.(*ir.Name)
if n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT {
return ""
}
}
if n.Type().Width > ir.MaxStackVarSize {
return "too large for stack"
}
if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Width > ir.MaxImplicitStackVarSize {
return "too large for stack"
}
if n.Op() == ir.OCLOSURE && typecheck.ClosureType(n.(*ir.ClosureExpr)).Size() > ir.MaxImplicitStackVarSize {
return "too large for stack"
}
if n.Op() == ir.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().Width != 0 && ir.Int64Val(r) > ir.MaxImplicitStackVarSize/t.Elem().Width {
return "too large for stack"
}
}
return ""
}

View File

@@ -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 {
@@ -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)
}
}
}
}

View File

@@ -32,6 +32,7 @@ import (
"log"
"os"
"runtime"
"sort"
)
func hidePanic() {
@@ -159,9 +160,6 @@ func Main(archInit func(*ssagen.ArchInfo)) {
dwarf.EnableLogging(base.Debug.DwarfInl != 0)
}
if base.Debug.SoftFloat != 0 {
if buildcfg.Experiment.RegabiArgs {
log.Fatalf("softfloat mode with GOEXPERIMENT=regabiargs not implemented ")
}
ssagen.Arch.SoftFloat = true
}
@@ -181,23 +179,41 @@ 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("<autogenerated>", "<autogenerated>"), 1, 0)
typecheck.InitUniverse()
typecheck.InitRuntime()
// Parse and typecheck input.
noder.LoadPackage(flag.Args())
dwarfgen.RecordPackageName()
// Prepare for backend processing. This must happen before pkginit,
// because it generates itabs for initializing global variables.
ssagen.InitConfig()
// Build init task.
if initTask := pkginit.Task(); initTask != nil {
typecheck.Export(initTask)
}
// Stability quirk: sort top-level declarations, so we're not
// sensitive to the order that functions are added. In particular,
// the order that noder+typecheck add function closures is very
// subtle, and not important to reproduce.
//
// Note: This needs to happen after pkginit.Task, otherwise it risks
// changing the order in which top-level variables are initialized.
if base.Debug.UnifiedQuirks != 0 {
s := typecheck.Target.Decls
sort.SliceStable(s, func(i, j int) bool {
return s[i].Pos().Before(s[j].Pos())
})
}
// Eliminate some obviously dead code.
// Must happen after typechecking.
for _, n := range typecheck.Target.Decls {
@@ -252,6 +268,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 +281,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 +289,10 @@ func Main(archInit func(*ssagen.ArchInfo)) {
fcount := int64(0)
for i := 0; i < len(typecheck.Target.Decls); i++ {
if fn, ok := typecheck.Target.Decls[i].(*ir.Func); ok {
// Don't try compiling dead hidden closure.
if fn.IsDeadcodeClosure() {
continue
}
enqueueFunc(fn)
fcount++
}

View File

@@ -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) {

View File

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

View File

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

View File

@@ -1,4 +1,3 @@
// UNREVIEWED
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -10,7 +9,6 @@ import (
"cmd/compile/internal/types2"
"fmt"
"internal/testenv"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -64,7 +62,7 @@ const maxTime = 30 * time.Second
func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
list, err := ioutil.ReadDir(dirname)
list, err := os.ReadDir(dirname)
if err != nil {
t.Fatalf("testDir(%s): %s", dirname, err)
}
@@ -92,7 +90,7 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
}
func mktmpdir(t *testing.T) string {
tmpdir, err := ioutil.TempDir("", "gcimporter_test")
tmpdir, err := os.MkdirTemp("", "gcimporter_test")
if err != nil {
t.Fatal("mktmpdir:", err)
}
@@ -142,7 +140,7 @@ func TestVersionHandling(t *testing.T) {
}
const dir = "./testdata/versions"
list, err := ioutil.ReadDir(dir)
list, err := os.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
@@ -195,7 +193,7 @@ func TestVersionHandling(t *testing.T) {
// create file with corrupted export data
// 1) read file
data, err := ioutil.ReadFile(filepath.Join(dir, name))
data, err := os.ReadFile(filepath.Join(dir, name))
if err != nil {
t.Fatal(err)
}
@@ -212,7 +210,7 @@ func TestVersionHandling(t *testing.T) {
// 4) write the file
pkgpath += "_corrupted"
filename := filepath.Join(corruptdir, pkgpath) + ".a"
ioutil.WriteFile(filename, data, 0666)
os.WriteFile(filename, data, 0666)
// test that importing the corrupted file results in an error
_, err = Import(make(map[string]*types2.Package), pkgpath, corruptdir, nil)
@@ -261,8 +259,7 @@ var importedObjectTests = []struct {
{"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
{"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"},
{"go/ast.Node", "type Node interface{End() go/token.Pos; Pos() go/token.Pos}"},
// go/types.Type has grown much larger - excluded for now
// {"go/types.Type", "type Type interface{String() string; Underlying() Type}"},
{"go/types.Type", "type Type interface{String() string; Underlying() Type}"},
}
func TestImportedTypes(t *testing.T) {
@@ -457,17 +454,17 @@ func TestIssue13898(t *testing.T) {
t.Fatal("go/types not found")
}
// look for go/types2.Object type
// look for go/types.Object type
obj := lookupObj(t, goTypesPkg.Scope(), "Object")
typ, ok := obj.Type().(*types2.Named)
if !ok {
t.Fatalf("go/types2.Object type is %v; wanted named type", typ)
t.Fatalf("go/types.Object type is %v; wanted named type", typ)
}
// lookup go/types2.Object.Pkg method
// lookup go/types.Object.Pkg method
m, index, indirect := types2.LookupFieldOrMethod(typ, false, nil, "Pkg")
if m == nil {
t.Fatalf("go/types2.Object.Pkg not found (index = %v, indirect = %v)", index, indirect)
t.Fatalf("go/types.Object.Pkg not found (index = %v, indirect = %v)", index, indirect)
}
// the method must belong to go/types

View File

@@ -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
// TODO: before release, change this back to 2.
iexportVersionGenerics = iexportVersionPosCol
iexportVersionCurrent = iexportVersionGenerics
)
type ident struct {
pkg string
name string
}
const predeclReserved = 32
type itag uint64
@@ -57,6 +71,9 @@ const (
signatureType
structType
interfaceType
typeParamType
instType
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,13 +95,17 @@ 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 /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11:
default:
errorf("unknown iexport format version %d", version)
if version > iexportVersionGenerics {
errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
} else {
errorf("unknown iexport format version %d", version)
}
}
sLen := int64(r.uint64())
@@ -96,16 +117,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 +142,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 +183,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 +191,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 +226,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,6 +252,16 @@ func (p *iimporter) pkgAt(off uint64) *types2.Package {
return nil
}
func (p *iimporter) posBaseAt(off uint64) *syntax.PosBase {
if posBase, ok := p.posBaseCache[off]; ok {
return posBase
}
filename := p.stringAt(off)
posBase := syntax.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)) {
return t
@@ -241,7 +275,7 @@ func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type {
// Reader.Reset is not available in Go 1.4.
// Use bytes.NewReader for now.
// r.declReader.Reset(p.declData[off-predeclReserved:])
r.declReader = *bytes.NewReader(p.declData[off-predeclReserved:])
r.declReader = *strings.NewReader(p.declData[off-predeclReserved:])
t := r.doType(base)
if base == nil || !isInterface(t) {
@@ -251,12 +285,12 @@ func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type {
}
type importReader struct {
p *iimporter
declReader bytes.Reader
currPkg *types2.Package
prevFile string
prevLine int64
prevColumn int64
p *iimporter
declReader strings.Reader
currPkg *types2.Package
prevPosBase *syntax.PosBase
prevLine int64
prevColumn int64
}
func (r *importReader) obj(name string) {
@@ -274,16 +308,28 @@ func (r *importReader) obj(name string) {
r.declare(types2.NewConst(pos, r.currPkg, name, typ, val))
case 'F':
case 'F', 'G':
var tparams []*types2.TypeParam
if tag == 'G' {
tparams = r.tparamList()
}
sig := r.signature(nil)
sig.SetTParams(tparams)
r.declare(types2.NewFunc(pos, r.currPkg, name, sig))
case 'T':
case 'T', 'U':
var tparams []*types2.TypeParam
if tag == 'U' {
tparams = r.tparamList()
}
// Types can be recursive. We need to setup a stub
// declaration before recursing.
obj := types2.NewTypeName(pos, r.currPkg, name, nil)
named := types2.NewNamed(obj, nil, nil)
if tag == 'U' {
named.SetTParams(tparams)
}
r.declare(obj)
underlying := r.p.typAt(r.uint64(), named).Underlying()
@@ -296,10 +342,43 @@ func (r *importReader) obj(name string) {
recv := r.param()
msig := r.signature(recv)
// If the receiver has any targs, set those as the
// rparams of the method (since those are the
// typeparams being used in the method sig/body).
targs := baseType(msig.Recv().Type()).TArgs()
if targs.Len() > 0 {
rparams := make([]*types2.TypeParam, targs.Len())
for i := range rparams {
rparams[i] = types2.AsTypeParam(targs.At(i))
}
msig.SetRParams(rparams)
}
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")
}
name0, sub := parseSubscript(name)
tn := types2.NewTypeName(pos, r.currPkg, name0, nil)
t := (*types2.Checker)(nil).NewTypeParam(tn, nil)
if sub == 0 {
errorf("missing subscript")
}
t.SetId(sub)
// To handle recursive references to the typeparam within its
// bound, save the partial type in tparamIndex before reading the bounds.
id := ident{r.currPkg.Name(), name}
r.p.tparamIndex[id] = t
t.SetConstraint(r.typ())
case 'V':
typ := r.typ()
@@ -439,12 +518,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 +532,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 +544,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 +558,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 {
@@ -554,6 +633,49 @@ func (r *importReader) doType(base *types2.Named) types2.Type {
typ := types2.NewInterfaceType(methods, embeddeds)
r.p.interfaceList = append(r.p.interfaceList, typ)
return typ
case typeParamType:
if r.p.exportVersion < iexportVersionGenerics {
errorf("unexpected type param type")
}
pkg, name := r.qualifiedIdent()
id := ident{pkg.Name(), name}
if t, ok := r.p.tparamIndex[id]; ok {
// We're already in the process of importing this typeparam.
return t
}
// Otherwise, import the definition of the typeparam now.
r.p.doDecl(pkg, name)
return r.p.tparamIndex[id]
case instType:
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 *Checker
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)
}
}
@@ -568,6 +690,19 @@ func (r *importReader) signature(recv *types2.Var) *types2.Signature {
return types2.NewSignature(recv, 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 {
typ := r.typ()
xs[i] = types2.AsTypeParam(typ)
}
return xs
}
func (r *importReader) paramList() *types2.Tuple {
xs := make([]*types2.Var, r.uint64())
for i := range xs {
@@ -610,3 +745,33 @@ 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
}
func parseSubscript(name string) (string, uint64) {
// Extract the subscript value from the type param name. We export
// and import the subscript value, so that all type params have
// unique names.
sub := uint64(0)
startsub := -1
for i, r := range name {
if '₀' <= r && r < '₀'+10 {
if startsub == -1 {
startsub = i
}
sub = sub*10 + uint64(r-'₀')
}
}
if startsub >= 0 {
name = name[:startsub]
}
return name, sub
}

View File

@@ -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.
@@ -120,6 +119,9 @@ var predeclared = []types2.Type{
// used internally by gc; never used by this package or in .a files
anyType{},
// comparable
types2.Universe.Lookup("comparable").Type(),
}
type anyType struct{}

View File

@@ -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
}
// 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.
if fn.ExportInline() {
return
}
fn.SetExportInline(true)
typecheck.ImportedBody(fn)
var doFlood func(n ir.Node)
doFlood = func(n ir.Node) {
switch n.Op() {
case ir.OMETHEXPR, ir.ODOTMETH:
Inline_Flood(ir.MethodExprName(n), exportsym)
case ir.ONAME:
n := n.(*ir.Name)
switch n.Class {
case ir.PFUNC:
Inline_Flood(n, exportsym)
exportsym(n)
case ir.PEXTERN:
exportsym(n)
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,6 +273,19 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
}
}
}
if n.X.Op() == ir.OMETHEXPR {
if meth := ir.MethodExprName(n.X); meth != nil {
fn := meth.Func
if fn != nil && types.IsRuntimePkg(fn.Sym().Pkg) && fn.Sym().Name == "heapBits.nextArena" {
// Special case: explicitly allow
// mid-stack inlining of
// runtime.heapBits.next even though
// it calls slow-path
// runtime.heapBits.nextArena.
break
}
}
}
if ir.IsIntrinsicCall(n) {
// Treat like any other node.
@@ -309,28 +300,8 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
// Call cost for non-leaf inlining.
v.budget -= v.extraCallCost
// Call is okay if inlinable and we have the budget for the body.
case ir.OCALLMETH:
n := n.(*ir.CallExpr)
t := n.X.Type()
if t == nil {
base.Fatalf("no function type for [%p] %+v\n", n.X, n.X)
}
fn := ir.MethodExprName(n.X).Func
if types.IsRuntimePkg(fn.Sym().Pkg) && fn.Sym().Name == "heapBits.nextArena" {
// Special case: explicitly allow
// mid-stack inlining of
// runtime.heapBits.next even though
// it calls slow-path
// runtime.heapBits.nextArena.
break
}
if fn.Inl != nil {
v.budget -= fn.Inl.Cost
break
}
// Call cost for non-leaf inlining.
v.budget -= v.extraCallCost
base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
// Things that are too hairy, irrespective of the budget
case ir.OCALL, ir.OCALLINTER:
@@ -445,7 +416,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
// and don't charge for the OBLOCK itself. The ++ undoes the -- below.
v.budget++
case ir.OCALLPART, ir.OSLICELIT:
case ir.OMETHVALUE, ir.OSLICELIT:
v.budget-- // Hack for toolstash -cmp.
case ir.OMETHEXPR:
@@ -499,9 +470,6 @@ func inlcopy(n ir.Node) ir.Node {
// x.Func.Body for iexport and local inlining.
oldfn := x.Func
newfn := ir.NewFunc(oldfn.Pos())
if oldfn.ClosureCalled() {
newfn.SetClosureCalled(true)
}
m.(*ir.ClosureExpr).Func = newfn
newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), oldfn.Nname.Sym())
// XXX OK to share fn.Type() ??
@@ -544,37 +512,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,7 +534,9 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
case ir.ODEFER, ir.OGO:
n := n.(*ir.GoDeferStmt)
switch call := n.Call; call.Op() {
case ir.OCALLFUNC, ir.OCALLMETH:
case ir.OCALLMETH:
base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
case ir.OCALLFUNC:
call := call.(*ir.CallExpr)
call.NoInline = true
}
@@ -607,11 +546,18 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
case ir.OCLOSURE:
return n
case ir.OCALLMETH:
// Prevent inlining some reflect.Value methods when using checkptr,
// even when package reflect was compiled without it (#35073).
base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
case ir.OCALLFUNC:
n := n.(*ir.CallExpr)
if s := ir.MethodExprName(n.X).Sym(); base.Debug.Checkptr != 0 && types.IsReflectPkg(s.Pkg) && (s.Name == "Value.UnsafeAddr" || s.Name == "Value.Pointer") {
return n
if n.X.Op() == ir.OMETHEXPR {
// Prevent inlining some reflect.Value methods when using checkptr,
// even when package reflect was compiled without it (#35073).
if meth := ir.MethodExprName(n.X); meth != nil {
s := meth.Sym()
if base.Debug.Checkptr != 0 && types.IsReflectPkg(s.Pkg) && (s.Name == "Value.UnsafeAddr" || s.Name == "Value.Pointer") {
return n
}
}
}
}
@@ -619,31 +565,18 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
ir.EditChildren(n, edit)
if as := n; as.Op() == ir.OAS2FUNC {
as := as.(*ir.AssignListStmt)
if as.Rhs[0].Op() == ir.OINLCALL {
as.Rhs = inlconv2list(as.Rhs[0].(*ir.InlinedCallExpr))
as.SetOp(ir.OAS2)
as.SetTypecheck(0)
n = typecheck.Stmt(as)
}
}
// with all the branches out of the way, it is now time to
// transmogrify this node itself unless inhibited by the
// switch at the top of this function.
switch n.Op() {
case ir.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)
}
@@ -653,38 +586,10 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
if fn := inlCallee(call.X); fn != nil && fn.Inl != nil {
n = mkinlcall(call, fn, maxCost, inlMap, edit)
}
case ir.OCALLMETH:
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 +645,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)
@@ -793,38 +703,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)
}
res := NewInline(n, fn, inlIndex)
if res == nil {
res = oldInline(n, fn, inlIndex)
}
// transitive inlining
// might be nice to do this before exporting the body,
// but can't emit the body with inlining expanded.
// instead we emit the things that the body needs
// and each use must redo the inlining.
// luckily these are small.
ir.EditChildren(res, edit)
if base.Flag.LowerM > 2 {
fmt.Printf("%v: After inlining %+v\n\n", ir.Line(res), res)
}
return res
}
// CalleeEffects appends any side effects from evaluating callee to init.
func CalleeEffects(init *ir.Nodes, callee ir.Node) {
for {
switch callee.Op() {
case ir.ONAME, ir.OCLOSURE, ir.OMETHEXPR:
return // done
case ir.OCONVNOP:
conv := callee.(*ir.ConvExpr)
init.Append(ir.TakeInit(conv)...)
callee = conv.X
case ir.OINLCALL:
ic := callee.(*ir.InlinedCallExpr)
init.Append(ir.TakeInit(ic)...)
init.Append(ic.Body.Take()...)
callee = ic.SingleResult()
default:
base.FatalfAt(callee.Pos(), "unexpected callee expression: %v", callee)
}
}
}
// oldInline creates an InlinedCallExpr to replace the given call
// expression. fn is the callee function to be inlined. inlIndex is
// the inlining tree position index, for use with src.NewInliningBase
// when rewriting positions.
func oldInline(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
if base.Debug.TypecheckInl == 0 {
typecheck.ImportedBody(fn)
}
SSADumpInline(fn)
ninit := n.Init()
ninit := call.Init()
// For normal function calls, the function callee expression
// may contain side effects (e.g., added by addinit during
// inlconv2expr or inlconv2list). Make sure to preserve these,
// may contain side effects. Make sure to preserve these,
// if necessary (#42703).
if n.Op() == ir.OCALLFUNC {
callee := n.X
for callee.Op() == ir.OCONVNOP {
conv := callee.(*ir.ConvExpr)
ninit.Append(ir.TakeInit(conv)...)
callee = conv.X
}
if callee.Op() != ir.ONAME && callee.Op() != ir.OCLOSURE && callee.Op() != ir.OMETHEXPR {
base.Fatalf("unexpected callee expression: %v", callee)
}
if call.Op() == ir.OCALLFUNC {
CalleeEffects(&ninit, call.X)
}
// Make temp names to use instead of the originals.
@@ -854,25 +816,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 +825,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 +847,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 +876,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 +911,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 +928,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 +943,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 +960,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 +1014,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) {
@@ -1222,8 +1083,6 @@ func (subst *inlsubst) clovar(n *ir.Name) *ir.Name {
// closure does the necessary substitions for a ClosureExpr n and returns the new
// closure node.
func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node {
m := ir.Copy(n)
// Prior to the subst edit, set a flag in the inlsubst to
// indicated that we don't want to update the source positions in
// the new closure. If we do this, it will appear that the closure
@@ -1231,29 +1090,16 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node {
// issue #46234 for more details.
defer func(prev bool) { subst.noPosUpdate = prev }(subst.noPosUpdate)
subst.noPosUpdate = true
ir.EditChildren(m, subst.edit)
//fmt.Printf("Inlining func %v with closure into %v\n", subst.fn, ir.FuncName(ir.CurFunc))
// The following is similar to funcLit
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 +1149,9 @@ 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.SetInit(subst.list(n.Init()))
return typecheck.Expr(newclo)
}
// node recursively copies a node from the saved pristine body of the
@@ -1391,7 +1233,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

View File

@@ -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())

View File

@@ -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,
@@ -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
@@ -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.
@@ -1114,16 +1134,21 @@ func dumpNodeHeader(w io.Writer, n Node) {
}
if n.Pos().IsKnown() {
pfx := ""
fmt.Fprint(w, " # ")
switch n.Pos().IsStmt() {
case src.PosNotStmt:
pfx = "_" // "-" would be confusing
fmt.Fprint(w, "_") // "-" would be confusing
case src.PosIsStmt:
pfx = "+"
fmt.Fprint(w, "+")
}
for i, pos := range base.Ctxt.AllPos(n.Pos(), nil) {
if i > 0 {
fmt.Fprint(w, ",")
}
// TODO(mdempsky): Print line pragma details too.
file := filepath.Base(pos.Filename())
fmt.Fprintf(w, "%s:%d:%d", file, pos.Line(), pos.Col())
}
pos := base.Ctxt.PosTable.Pos(n.Pos())
file := filepath.Base(pos.Filename())
fmt.Fprintf(w, " # %s%s:%d", pfx, file, pos.Line())
}
}

View File

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

View File

@@ -358,39 +358,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.Op() != ONAME || n.Curfn == nil {
return n // okay to use directly
}
if n.IsClosureVar() {
base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n)
}
if n.Op() != ONAME || n.Curfn == nil || n.Curfn == fn {
return n // okay to use directly
c := n.Innermost
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)
}
c := n.Innermost
if c != nil && c.Curfn == fn {
return c
}
// 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
}

View File

@@ -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,9 +320,16 @@ 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
)
@@ -436,18 +446,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 +574,7 @@ func OuterValue(n Node) Node {
for {
switch nn := n; nn.Op() {
case OXDOT:
base.Fatalf("OXDOT in walk")
base.FatalfAt(n.Pos(), "OXDOT in walk: %v", n)
case ODOT:
nn := nn.(*SelectorExpr)
n = nn.X

View File

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

View File

@@ -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) {

View File

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

View File

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

View File

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

View File

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

View File

@@ -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())
}
}

View File

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

View File

@@ -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)"}]}`)
})
}

View File

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

View File

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

View File

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

View File

@@ -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)
@@ -90,27 +95,54 @@ 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.Name.Value == "init" && decl.Recv == nil {
g.target.Inits = append(g.target.Inits, fn)
}
g.funcBody(fn, decl.Recv, decl.Type, decl.Body)
g.later(func() {
if fn.Type().HasTParam() {
g.topFuncIsGeneric = true
}
g.funcBody(fn, decl.Recv, decl.Type, decl.Body)
g.topFuncIsGeneric = false
if fn.Type().HasTParam() && fn.Body != nil {
// Set pointers to the dcls/body of a generic function/method in
// the Inl struct, so it is marked for export, is available for
// stenciling, and works with Inline_Flood().
fn.Inl = &ir.Inline{
Cost: 1,
Dcl: fn.Dcl,
Body: fn.Body,
}
}
out.Append(fn)
out.Append(fn)
})
}
func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
if decl.Alias {
name, _ := g.def(decl.Name)
g.pragmaFlags(decl.Pragma, 0)
// TODO(mdempsky): This matches how typecheckdef marks aliases for
// export, but this won't generalize to exporting function-scoped
// type aliases. We should maybe just use n.Alias() instead.
if ir.CurFunc == nil {
name.Sym().Def = ir.TypeNode(name.Type())
}
assert(name.Alias()) // should be set by irgen.obj
out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name))
return
@@ -154,11 +186,15 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
// [mdempsky: Subtleties like these are why I always vehemently
// object to new type pragmas.]
ntyp.SetUnderlying(g.typeExpr(decl.Type))
if len(decl.TParamList) > 0 {
// Set HasTParam if there are any tparams, even if no tparams are
// used in the type itself (e.g., if it is an empty struct, or no
// fields in the struct use the tparam).
ntyp.SetHasTParam(true)
tparams := otyp.(*types2.Named).TParams()
if 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()
@@ -182,7 +218,6 @@ func (g *irgen) varDecl(out *ir.Nodes, decl *syntax.VarDecl) {
for i, name := range decl.NameList {
names[i], _ = g.def(name)
}
values := g.exprList(decl.Values)
if decl.Pragma != nil {
pragma := decl.Pragma.(*pragmas)
@@ -191,44 +226,57 @@ func (g *irgen) varDecl(out *ir.Nodes, decl *syntax.VarDecl) {
g.reportUnused(pragma)
}
var as2 *ir.AssignListStmt
if len(values) != 0 && len(names) != len(values) {
as2 = ir.NewAssignListStmt(pos, ir.OAS2, make([]ir.Node, len(names)), values)
}
do := func() {
values := g.exprList(decl.Values)
for i, name := range names {
if ir.CurFunc != nil {
out.Append(ir.NewDecl(pos, ir.ODCL, name))
var as2 *ir.AssignListStmt
if len(values) != 0 && len(names) != len(values) {
as2 = ir.NewAssignListStmt(pos, ir.OAS2, make([]ir.Node, len(names)), values)
}
for i, name := range names {
if ir.CurFunc != nil {
out.Append(ir.NewDecl(pos, ir.ODCL, name))
}
if as2 != nil {
as2.Lhs[i] = name
name.Defn = as2
} else {
as := ir.NewAssignStmt(pos, name, nil)
if len(values) != 0 {
as.Y = values[i]
name.Defn = as
} else if ir.CurFunc == nil {
name.Defn = as
}
lhs := []ir.Node{as.X}
rhs := []ir.Node{}
if as.Y != nil {
rhs = []ir.Node{as.Y}
}
transformAssign(as, lhs, rhs)
as.X = lhs[0]
if as.Y != nil {
as.Y = rhs[0]
}
as.SetTypecheck(1)
out.Append(as)
}
}
if as2 != nil {
as2.Lhs[i] = name
name.Defn = as2
} else {
as := ir.NewAssignStmt(pos, name, nil)
if len(values) != 0 {
as.Y = values[i]
name.Defn = as
} else if ir.CurFunc == nil {
name.Defn = as
}
lhs := []ir.Node{as.X}
rhs := []ir.Node{}
if as.Y != nil {
rhs = []ir.Node{as.Y}
}
transformAssign(as, lhs, rhs)
as.X = lhs[0]
if as.Y != nil {
as.Y = rhs[0]
}
as.SetTypecheck(1)
out.Append(as)
transformAssign(as2, as2.Lhs, as2.Rhs)
as2.SetTypecheck(1)
out.Append(as2)
}
}
if as2 != nil {
transformAssign(as2, as2.Lhs, as2.Rhs)
as2.SetTypecheck(1)
out.Append(as2)
// If we're within a function, we need to process the assignment
// part of the variable declaration right away. Otherwise, we leave
// it to be handled after all top-level declarations are processed.
if ir.CurFunc != nil {
do()
} else {
g.later(do)
}
}

View File

@@ -0,0 +1,301 @@
// 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) rawValue() constant.Value {
isComplex := r.bool()
val := r.scalar()
if isComplex {
val = constant.BinaryOp(val, token.ADD, constant.MakeImag(r.scalar()))
}
return val
}
func (r *decoder) scalar() constant.Value {
switch tag := codeVal(r.code(syncVal)); tag {
default:
panic(fmt.Sprintf("unexpected scalar tag: %v", tag))
case valBool:
return constant.MakeBool(r.bool())
case valString:
return constant.MakeString(r.string())
case valInt64:
return constant.MakeInt64(r.int64())
case valBigInt:
return constant.Make(r.bigInt())
case valBigRat:
num := r.bigInt()
denom := r.bigInt()
return constant.Make(new(big.Rat).SetFrac(num, denom))
case valBigFloat:
return constant.Make(r.bigFloat())
}
}
func (r *decoder) bigInt() *big.Int {
v := new(big.Int).SetBytes([]byte(r.string()))
if r.bool() {
v.Neg(v)
}
return v
}
func (r *decoder) bigFloat() *big.Float {
v := new(big.Float).SetPrec(512)
assert(v.UnmarshalText([]byte(r.string())) == nil)
return v
}

View File

@@ -0,0 +1,284 @@
// 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) rawValue(val constant.Value) {
if w.bool(val.Kind() == constant.Complex) {
w.scalar(constant.Real(val))
w.scalar(constant.Imag(val))
} else {
w.scalar(val)
}
}
func (w *encoder) scalar(val constant.Value) {
switch v := constant.Val(val).(type) {
default:
panic(fmt.Sprintf("unhandled %v (%v)", val, val.Kind()))
case bool:
w.code(valBool)
w.bool(v)
case string:
w.code(valString)
w.string(v)
case int64:
w.code(valInt64)
w.int64(v)
case *big.Int:
w.code(valBigInt)
w.bigInt(v)
case *big.Rat:
w.code(valBigRat)
w.bigInt(v.Num())
w.bigInt(v.Denom())
case *big.Float:
w.code(valBigFloat)
w.bigFloat(v)
}
}
func (w *encoder) bigInt(v *big.Int) {
b := v.Bytes()
w.string(string(b)) // TODO: More efficient encoding.
w.bool(v.Sign() < 0)
}
func (w *encoder) bigFloat(v *big.Float) {
b := v.Append(nil, 'p', -1)
w.string(string(b)) // TODO: More efficient encoding.
}

View File

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

View File

@@ -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:
@@ -105,23 +118,30 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
// The key for the Inferred map is the CallExpr (if inferring
// types required the function arguments) or the IndexExpr below
// (if types could be inferred without the function arguments).
if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.Targs) > 0 {
if inferred, ok := g.info.Inferred[expr]; ok && inferred.TArgs.Len() > 0 {
// This is the case where inferring types required the
// types of the function arguments.
targs := make([]ir.Node, len(inferred.Targs))
for i, targ := range inferred.Targs {
targs[i] = ir.TypeNode(g.typ(targ))
targs := make([]ir.Node, inferred.TArgs.Len())
for i := range targs {
targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i)))
}
if fun.Op() == ir.OFUNCINST {
// Replace explicit type args with the full list that
// includes the additional inferred type args
// includes the additional inferred type args.
// Substitute the type args for the type params in
// the generic function's type.
fun.(*ir.InstExpr).Targs = targs
newt := g.substType(fun.Type(), fun.Type().TParams(), targs)
typed(newt, fun)
} else {
// Create a function instantiation here, given
// there are only inferred type args (e.g.
// min(5,6), where min is a generic function)
// Create a function instantiation here, given there
// are only inferred type args (e.g. min(5,6), where
// min is a generic function). Substitute the type
// args for the type params in the generic function's
// type.
inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs)
typed(fun.Type(), inst)
newt := g.substType(fun.Type(), fun.Type().TParams(), targs)
typed(newt, inst)
fun = inst
}
@@ -131,13 +151,13 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
case *syntax.IndexExpr:
var targs []ir.Node
if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.Targs) > 0 {
if inferred, ok := g.info.Inferred[expr]; ok && inferred.TArgs.Len() > 0 {
// This is the partial type inference case where the types
// can be inferred from other type arguments without using
// the types of the function arguments.
targs = make([]ir.Node, len(inferred.Targs))
for i, targ := range inferred.Targs {
targs[i] = ir.TypeNode(g.typ(targ))
targs = make([]ir.Node, inferred.TArgs.Len())
for i := range targs {
targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i)))
}
} else if _, ok := expr.Index.(*syntax.ListExpr); ok {
targs = g.exprList(expr.Index)
@@ -158,12 +178,16 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
panic("Incorrect argument for generic func instantiation")
}
n := ir.NewInstExpr(pos, ir.OFUNCINST, x, targs)
typed(g.typ(typ), n)
newt := g.typ(typ)
// Substitute the type args for the type params in the uninstantiated
// function's type. If there aren't enough type args, then the rest
// will be inferred at the call node, so don't try the substitution yet.
if x.Type().TParams().NumFields() == len(targs) {
newt = g.substType(g.typ(typ), x.Type().TParams(), targs)
}
typed(newt, n)
return n
case *syntax.ParenExpr:
return g.expr(expr.X) // skip parens; unneeded after parse+typecheck
case *syntax.SelectorExpr:
// Qualified identifier.
if name, ok := expr.X.(*syntax.Name); ok {
@@ -193,7 +217,29 @@ 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)
g.instTypeList = append(g.instTypeList, ts.InstTypeList...)
return newt
}
// selectorExpr resolves the choice of ODOT, ODOTPTR, OMETHVALUE (eventually
// ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather
// than in typecheck.go.
func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.SelectorExpr) ir.Node {
@@ -203,6 +249,44 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
// only be fully transformed once it has an instantiated type.
n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value))
typed(g.typ(typ), n)
// Fill in n.Selection for a generic method reference or a bound
// interface method, even though we won't use it directly, since it
// is useful for analysis. Specifically do not fill in for fields or
// other interfaces methods (method call on an interface value), so
// n.Selection being non-nil means a method reference for a generic
// type or a method reference due to a bound.
obj2 := g.info.Selections[expr].Obj()
sig := types2.AsSignature(obj2.Type())
if sig == nil || sig.Recv() == nil {
return n
}
index := g.info.Selections[expr].Index()
last := index[len(index)-1]
// recvType is the receiver of the method being called. Because of the
// way methods are imported, g.obj(obj2) doesn't work across
// packages, so we have to lookup the method via the receiver type.
recvType := deref2(sig.Recv().Type())
if types2.AsInterface(recvType.Underlying()) != nil {
fieldType := n.X.Type()
for _, ix := range index[:len(index)-1] {
fieldType = fieldType.Field(ix).Type
}
if fieldType.Kind() == types.TTYPEPARAM {
n.Selection = fieldType.Bound().AllMethods().Index(last)
//fmt.Printf(">>>>> %v: Bound call %v\n", base.FmtPos(pos), n.Sel)
} else {
assert(fieldType.Kind() == types.TINTER)
//fmt.Printf(">>>>> %v: Interface call %v\n", base.FmtPos(pos), n.Sel)
}
return n
}
recvObj := types2.AsNamed(recvType).Obj()
recv := g.pkg(recvObj.Pkg()).Lookup(recvObj.Name()).Def
n.Selection = recv.Type().Methods().Index(last)
//fmt.Printf(">>>>> %v: Method call %v\n", base.FmtPos(pos), n.Sel)
return n
}
@@ -259,14 +343,18 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
if wantPtr {
recvType2Base = types2.AsPointer(recvType2).Elem()
}
if len(types2.AsNamed(recvType2Base).TParams()) > 0 {
if types2.AsNamed(recvType2Base).TParams().Len() > 0 {
// recvType2 is the original generic type that is
// instantiated for this method call.
// selinfo.Recv() is the instantiated type
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)
@@ -274,9 +362,9 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
// selinfo.Targs() are the types used to
// instantiate the type of receiver
targs2 := getTargs(selinfo)
targs := make([]ir.Node, len(targs2))
for i, targ2 := range targs2 {
targs[i] = ir.TypeNode(g.typ(targ2))
targs := make([]ir.Node, targs2.Len())
for i := range targs {
targs[i] = ir.TypeNode(g.typ(targs2.At(i)))
}
// Create function instantiation with the type
@@ -300,11 +388,8 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
}
// getTargs gets the targs associated with the receiver of a selected method
func getTargs(selinfo *types2.Selection) []types2.Type {
r := selinfo.Recv()
if p := types2.AsPointer(r); p != nil {
r = p.Elem()
}
func getTargs(selinfo *types2.Selection) *types2.TypeList {
r := deref2(selinfo.Recv())
n := types2.AsNamed(r)
if n == nil {
base.Fatalf("Incorrect type for selinfo %v", selinfo)
@@ -313,13 +398,17 @@ func getTargs(selinfo *types2.Selection) []types2.Type {
}
func (g *irgen) exprList(expr syntax.Expr) []ir.Node {
return g.exprs(unpackListExpr(expr))
}
func unpackListExpr(expr syntax.Expr) []syntax.Expr {
switch expr := expr.(type) {
case nil:
return nil
case *syntax.ListExpr:
return g.exprs(expr.ElemList)
return expr.ElemList
default:
return []ir.Node{g.expr(expr)}
return []syntax.Expr{expr}
}
}
@@ -344,11 +433,13 @@ func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
for i, elem := range lit.ElemList {
switch elem := elem.(type) {
case *syntax.KeyValueExpr:
var key ir.Node
if isStruct {
exprs[i] = ir.NewStructKeyExpr(g.pos(elem), g.name(elem.Key.(*syntax.Name)), g.expr(elem.Value))
key = ir.NewIdent(g.pos(elem.Key), g.name(elem.Key.(*syntax.Name)))
} else {
exprs[i] = ir.NewKeyExpr(g.pos(elem), g.expr(elem.Key), g.expr(elem.Value))
key = g.expr(elem.Key)
}
exprs[i] = ir.NewKeyExpr(g.pos(elem), key, g.expr(elem.Value))
default:
exprs[i] = g.expr(elem)
}
@@ -360,19 +451,13 @@ func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
}
func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node {
fn := ir.NewFunc(g.pos(expr))
fn.SetIsHiddenClosure(ir.CurFunc != nil)
fn := ir.NewClosureFunc(g.pos(expr), ir.CurFunc != 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 +471,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 +488,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
}
}

View File

@@ -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())
}
}

Some files were not shown because too many files have changed in this diff Show More