[dev.fuzz] all: merge master (65f0d24) into dev.fuzz

Conflicts:

- api/next.txt
- src/cmd/go/alldocs.go
- src/cmd/go/internal/test/test.go

Merge List:

+ 2021-09-08 65f0d24f73 cmd/go: print offending -mod value in workspace mode
+ 2021-09-08 37c9552e06 cmd/go: improve the creation and editing of go.work files
+ 2021-09-08 c8d4fe2adc go/types: temporarily pin the Checker to Interface during checking
+ 2021-09-08 d419f9c612 go/types: spell out 'Type' in type parameter APIs
+ 2021-09-08 12eb7331b9 go/ast: rename TParams fields to TypeParams
+ 2021-09-08 38c2e08cbd go/types: move NewTypeParam off of Checker
+ 2021-09-08 cb9ccd494b go/types: move typeHash to environment.go
+ 2021-09-08 a1a6540bf1 go/types: implement deduplication of instances using the Environment
+ 2021-09-08 409434d623 cmd/go/internal/modload: scan dependencies of root paths when raising version limits in editRequirements
+ 2021-09-08 054710ce46 cmd/compile/internal/types2: reduce number of delayed functions (optimization)
+ 2021-09-08 73a062c3e7 cmd/compile/internal/types2: handle recursive type parameter constraints
+ 2021-09-08 9581d891ab cmd/pprof: update vendored github.com/google/pprof
+ 2021-09-08 8214257347 test/codegen: fix package name for test case
+ 2021-09-08 1da64686f8 test/codegen: fix compilation of bitfield tests
+ 2021-09-08 fdc2072420 test/codegen: remove broken riscv64 test
+ 2021-09-08 64bdad2011 all: update vendored golang.org/x/tools
+ 2021-09-08 9295723079 cmd/link: rework .TOC. handling for ppc64le
+ 2021-09-08 50c69cc3a9 cmd/link/internal/riscv64,cmd/internal/obj/riscv: make error messages consistent
+ 2021-09-08 c50d811c7a cmd/interna/obj/riscv: use obj.REG_NONE rather than 0
+ 2021-09-08 f030043e37 cmd/internal/obj/riscv: simplify machine code output
+ 2021-09-08 da790cccc5 cmd/internal/obj/riscv: absorb rewriteMOV into instruction generation
+ 2021-09-08 f5bdbf311c cmd/internal/obj/riscv: simplify rewriteMOV
+ 2021-09-08 bab79dd362 reflect: add back signaling NaN test
+ 2021-09-08 963218cc9c reflect: correct typoo in comment
+ 2021-09-07 3fff213ac2 cmd/compile: add CONVIFACE nodes needed in generic code due to assignments
+ 2021-09-07 b606739be6 reflect: add test for passing float32 signaling NaNs
+ 2021-09-07 b5e33a50fe reflect: rename MapIter method receiver variable from it to iter
+ 2021-09-07 07f623063d reflect: add MapIter.Reset
+ 2021-09-07 a9a01a3fbd cmd/compile: remove now-unneeded SetHasTParam() for cached ptr element
+ 2021-09-07 dcf3545774 encoding/gob: optimize decoding of slice
+ 2021-09-07 80783558b0 cmd/compile: make sure imported instantiated types have their methods created
+ 2021-09-07 23f4f0db68 cmd/compile: add prefetch intrinsic support
+ 2021-09-07 d92101f452 cmd/compile: resolve TODO in inl.go
+ 2021-09-07 903958d2f5 encoding/gob: marshal maps using reflect.Value.MapRange
+ 2021-09-07 6640171914 cmd/compile: fix type substituter to copy Funarg value for structs
+ 2021-09-07 e581ec07ee cmd/compile: fix lazy loading in reader2
+ 2021-09-07 81188661f1 go/types: do not format TParams when hashing
+ 2021-09-07 2a4845257f cmd/compile: fix deadlock in (*Named).load
+ 2021-09-07 bca8c6ffa2 cmd/link: resolve magic value in gdbscript section generation
+ 2021-09-07 21de6bc463 cmd/compile: simplify less with non-negative number and constant 0 or 1
+ 2021-09-07 6226020c2f cmd/compile: make sure that the names created for instantiated type are the same
+ 2021-09-06 a1938435d6 syscall: use dup3 in forkAndExecInChild1 on all Linux platforms
+ 2021-09-06 20a71c9a1d cmd/internal/sys: fix placement of loong64 definition
+ 2021-09-06 ecfff58fb8 cmd/compile: fix delay transformation in *subster.node()
+ 2021-09-06 c7f09eeb13 cmd/internal/sys: declare loong64 arch
+ 2021-09-06 7b69ddc171 cmd/compile: merge sign extension and shift into SBFIZ
+ 2021-09-06 43b05173a2 cmd/compile: merge zero/sign extensions with UBFX/SBFX on arm64
+ 2021-09-05 7619a4528d reflect: improve panic when MapIter has no associated map Value
+ 2021-09-05 1b2d794ca3 reflect: allocate hiter as part of MapIter
+ 2021-09-04 9133245be7 cmd/compile/internal/types2: detect constraint type inference cycles
+ 2021-09-04 28dae3defb cmd/internal/obj/riscv: improve code generation for loading of constants
+ 2021-09-04 37e9c1d6fe cmd/internal/obj/riscv: avoid obj.Prog rewriting for address to register loads
+ 2021-09-04 2d90df91a8 cmd/internal/obj/riscv: avoid obj.Prog rewriting for immediate splitting
+ 2021-09-04 5c224ec921 database/sql: improve the documentation of Conn.Raw
+ 2021-09-04 ba66d62b68 cmd/internal/obj/riscv: avoid obj.Prog rewriting for memory stores
+ 2021-09-04 5ec298d7b0 cmd/internal/obj/riscv: avoid obj.Prog rewriting for memory loads
+ 2021-09-04 0b66310924 cmd/internal/obj/riscv: avoid obj.Prog rewriting for store instructions
+ 2021-09-04 8a01010c26 cmd/internal/obj/riscv: avoid obj.Prog rewriting for load instructions
+ 2021-09-04 9cb5716f00 cmd/internal/obj/riscv: avoid obj.Prog rewriting for constant loads
+ 2021-09-03 4957976b1a cmd/link: make npkgsyms meaningful
+ 2021-09-03 d9244f8b64 Revert "go/ast: clarify when Ident.Obj is nil"
+ 2021-09-03 04d8d24960 misc/wasm: enable ECMAScript strict mode
+ 2021-09-03 52aef05498 go/ast: clarify when Ident.Obj is nil
+ 2021-09-03 ab7c904bf2 cmd/internal/obj/riscv: factor out instructions for MOV pseudo-instructions
+ 2021-09-03 17910ed4ff refect: rename Ptr Kind to Pointer (but keep Ptr)
+ 2021-09-03 9f69a44308 image/draw: add RGBA64Image fast path
+ 2021-09-02 065f380815 debug/dwarf: check for DWARFv4 AttrDataBitOffset value
+ 2021-09-02 a8aa6cfa6d cmd/compile: correct a comment in uint64Tofloat
+ 2021-09-02 58244eee01 test: only test -G=3 by default
+ 2021-09-02 9633195ae1 src: do not emit warning when GOROOT_BOOTSTRAP is unset
+ 2021-09-02 7609b50701 go/types: systematic detection of missing instantiation
+ 2021-09-02 acc2957bc9 net/http: fix hang in probing for a zero-length request body
+ 2021-09-02 2a463a22ce net/http: close request body after recovering from a handler panic
+ 2021-09-02 ead3fe0dba all: update vendored dependencies for Go 1.18
+ 2021-09-02 08588e6036 go/internal/gcimporter: always call SetTParams, even if empty
+ 2021-09-02 d01388b04f all: update vendored golang.org/x/crypto
+ 2021-09-02 782aa42255 cmd/link: mark stacks as non-executable on freebsd
+ 2021-09-02 d8b156773c all: update vendored golang.org/x/sys
+ 2021-09-02 014a9720f9 cmd/link: avoid crash on undefined func sym with external linking
+ 2021-09-02 37d4532867 cmd/internal/obj/riscv: simplify addition with constant
+ 2021-09-02 4fb79569d2 go/internal/gcimporter: add import tests for type parameters
+ 2021-09-02 b8420baf46 go/internal/gcimporter: add support for importing parameterized types
+ 2021-09-02 4591f49938 runtime: do not alloc never used tail bytes in fixalloc
+ 2021-09-02 a35c5c98c0 runtime: constify a test variable
+ 2021-09-02 90ed541149 runtime: ensure the fixalloc object size is valid
+ 2021-09-02 69107e73ce runtime: change 0 to pollNoError in netpollblock
+ 2021-09-02 08e2519ded cmd/compile: workaround inlining of closures with range statements
+ 2021-09-02 6705191e02 syscall: drop fallback to accept in Accept on Linux
+ 2021-09-02 17e9d148d3 syscall: drop fallback to utimes in UtimesNano on Linux
+ 2021-09-02 d13d62c49a os, syscall: remove fallback to pipe syscall on Linux
+ 2021-09-02 840b4292c9 src: emit warning when make.bash run with invalid GOROOT_BOOTSTRAP
+ 2021-09-02 1ae7ddc235 test: always run test in unified IR mode regardless of explicit -G flag
+ 2021-09-02 3db4888a05 cmd/compile: use types2.Unsafe to represent package unsafe in gcimports
+ 2021-09-02 9afbf82667 cmd/compile: allow objStub from unsafe package
+ 2021-09-02 1bd35fab05 runtime: use vDSO clock_gettime on linux/riscv64
+ 2021-09-02 df4c625d88 cmd/compile: disable type list syntax for the compiler
+ 2021-09-01 2872496ba5 cmd/compile/internal/types2: systematic detection of missing instantiation
+ 2021-09-01 0bfd6fcea6 all: update golang.org/x/net to pull in CL 346890
+ 2021-09-01 88859f3cd8 cmd/compile: optimize unified IR handling of imported functions
+ 2021-09-01 50f38d0405 cmd/compile: emit unified IR wrappers after inlining
+ 2021-09-01 5e0f8edbdc cmd/compile: remove useless fcount
+ 2021-09-01 ea51e223c2 cmd/{asm,compile}: add fused multiply-add support on riscv64
+ 2021-09-01 711e1c8224 cmd/compile: fix irgen mis-handling invalid function declaration
+ 2021-09-01 592ee433f5 spec: adjust example for consistency
+ 2021-09-01 6c5f028242 cmd/compile/internal/pkginit: separate "init" and "inittask" logic
+ 2021-09-01 8f397bc118 cmd/internal/obj/ppc64: improve long conditional branch fixup
+ 2021-09-01 5670ff4ae5 cmd/compile: fix conversions from TypeParam to interface
+ 2021-09-01 717f337d1d cmd/asm: adjust riscv64 test data to avoid churn
+ 2021-09-01 5a687eeaf1 cmd/asm,cmd/internal/obj/riscv: add more error tests for riscv64 assembly
+ 2021-09-01 faf9c7d8fe cmd/compile: assign results of transformAssign back to source location
+ 2021-09-01 2dd7b770de cmd/compile: fix missing case for shape double-check function
+ 2021-09-01 62ba72b353 cmd/compile: fix method expression lookup during import
+ 2021-09-01 f4e24599dd go/types: disallow aliases for generic types
+ 2021-09-01 36ac2214fa go/types: remove superfluous ordinaryType calls
+ 2021-09-01 1a9807906d go/types: more systematic error handling in typeWriter
+ 2021-09-01 5cd1b847dc go/types: eliminate typeHashing global variable
+ 2021-09-01 0df6df17e1 go/types: generalize instanceHash to accept any type, rename to typeHash
+ 2021-08-31 3c8c9e1e44 go/types: don't print instance markers for type hashes
+ 2021-08-31 2d98a4b4bc go/types: use a typeWriter to write types (cleanup)
+ 2021-08-31 b2f09cd717 go/types: do not declare new methods on instantiated types
+ 2021-08-31 5e9ba0b1bd go/types: implement TypeList.String (debugging support)
+ 2021-08-31 580987cd58 go/types: remove need for the instance struct
+ 2021-08-31 d15a75e070 go/types: address some TODOs (cleanup)
+ 2021-08-31 1f83a8c16c cmd/compile: use the zero value for results of impossible indexing
+ 2021-08-31 bb0b511738 cmd/compile: use right line number for conversion expression
+ 2021-08-31 7637345b6e go/internal/typeparams: remove typeparams.{Get,Set} (cleanup)
+ 2021-08-31 78d0f8c870 go/types: fix type set printing and add a test
+ 2021-08-31 ae2b2dc01a go/types: rename IsMethodSet to IsConstraint (cleanup)
+ 2021-08-31 b93581e47d go/types: add error reporting for 1.18 syntax if GoVersion is below 1.18
+ 2021-08-31 aed59d172a go/types: allow composite literals of type parameter type
+ 2021-08-31 891470fbf7 cmd/compile: fix handling of Defn field during stenciling
+ 2021-08-31 46121306d3 cmd/compile: remove folding of 32 bit pointer offsets on amd64
+ 2021-08-31 144e0b1f6e cmd/compile: add MOVOstoreconst with offset folding on amd64
+ 2021-08-31 f27d6a23b0 cmd/compile: builtins may be in the unsafe package
+ 2021-08-31 68152359fd cmd/compile/internal/types2: disallow aliases for generic types
+ 2021-08-31 605d1aaea2 go/types, types2: union terms must be instantiated
+ 2021-08-31 ded10d75a9 cmd/compile/internal/types2: remove superfluous ordinaryType calls
+ 2021-08-31 3920d6f208 runtime: eliminate the redundant for loop in runqget()
+ 2021-08-31 f118d145a5 cmd/compile: make unified IR more selective about method wrappers
+ 2021-08-31 d384ebde60 net: enable multicast listener tests on solaris/illumos
+ 2021-08-30 7622e41c84 go/types, types2: add a test for invalid import of "init"
+ 2021-08-30 3342aa5f51 cmd/compile/internal/types2: more systematic error handling in typeWriter
+ 2021-08-30 b06cfe9b25 cmd/compile/internal/types2: eliminate typeHashing global variable
+ 2021-08-30 437362ccec cmd/compile/internal/types2: generalize instanceHash to accept any type, rename to typeHash
+ 2021-08-30 86fa510d24 go/types, types2: types in method expressions must be instantiated
+ 2021-08-30 8f4c020660 cmd/compile: fix bug with Inferred targs
+ 2021-08-30 8250141c9a cmd/compile/internal/types2: don't print instance markers for type hashes
+ 2021-08-30 5f0d821add cmd/compile/internal/types2: use a typeWriter to write types (cleanup)
+ 2021-08-30 61120c634c cmd/go/internal/modload: use "pruned" instead of "lazy" to describe pruned module graphs
+ 2021-08-30 af9009a989 cmd/go/internal/modload: remove go117LazyTODO
+ 2021-08-30 9da7ccab58 cmd/go/internal/modload: remove go117EnableLazyLoading
+ 2021-08-30 bdc1bef8a0 cmd/go: ensure 'go get -u' can upgrade pruned (1.17+) modules
+ 2021-08-30 b602daea1b cmd/compile: fix error when revcType is ptr in selectorExpr
+ 2021-08-30 7b38dd8e25 runtime: remove unnecesarry newline on freeStackSpans
+ 2021-08-30 56c3856d52 cmd/compile/internal/types: unexport Type.widthCalculated
+ 2021-08-30 21d0b306af cmd/compile/internal/types: remove unused Tie method
+ 2021-08-30 a29d9aad7a test/typeparam/sliceimp.dir: fix typo in a.go
+ 2021-08-29 f29abccd8a test: add test cases for issue47892.
+ 2021-08-28 f4cd001b57 os/user: simplify skipping listGroups test
+ 2021-08-28 6df3aac4ae cmd/compile: fix offset-generator for storeOneLoad
+ 2021-08-28 5afa555428 cmd/compile: fix wrong check for b.Controls in isBlockMultiValueExit
+ 2021-08-28 d7a43e8912 cmd/compile: support type C comparable
+ 2021-08-28 044550ab0e runtime: add test case for checkptr alignment with nested expression
+ 2021-08-28 010817714e cmd/compile: ignore SliceExpr.CheckPtrCall for mknode
+ 2021-08-28 f371b30f32 unicode/utf8: add AppendRune
+ 2021-08-28 ef4cb2f776 cmd/compile/internal/types: change NewNamed to use TypeObject
+ 2021-08-28 5fb177163b go/types, types2: types in type switch cases must be instantiated
+ 2021-08-28 c81fa001a7 cmd/compile/internal/types: simplify and optimize PtrDataSize
+ 2021-08-27 a9377183d0 cmd/compile/internal/types: unexport New and NewBasic
+ 2021-08-27 82efc05403 cmd/compile: use Type.OrigSym getter/setters [generated]
+ 2021-08-27 68ecdc2c70 cmd/compile/internal/types: add Type.OrigSym getter/setters
+ 2021-08-27 72c003ef82 cmd/compile: unexport Type.Width and Type.Align [generated]
+ 2021-08-27 94f2a03951 cmd: update requirement on golang.org/x/mod
+ 2021-08-27 6a35e07512 cmd/compile: fix stenciling of conversions between interfaces
+ 2021-08-27 4f0dedca71 cmd/compile: fix parameterized interfaces
+ 2021-08-27 39eb1cc3f4 crypto/x509: drop compatibility hack for expired COMODO intermediates
+ 2021-08-27 acdea4f9f7 all: REVERSE MERGE dev.cmdgo (220bc44) into master
+ 2021-08-27 220bc44a4c [dev.cmdgo] all: merge master (67f7e16) into dev.cmdgo
+ 2021-08-27 67f7e16bcc encoding/gob: optimize decoding of []byte
+ 2021-08-27 2c60a99f72 cmd/compile/internal/syntax: make valid type parameter list in presence of errors
+ 2021-08-27 d350a66532 cmd/compile: eagerly CalcStructSize for synthetic ABI types
+ 2021-08-27 d7e2e2ec2b cmd/compile: delay fillinMethods to deal with mutually-recursive types
+ 2021-08-27 c927599783 cmd/compile: eliminate repetitive code
+ 2021-08-27 62f88b6dc8 cmd/compile: add types.RecalcSize
+ 2021-08-27 e7eee5e265 cmd/compile: remove ssagen/pgen_test.go
+ 2021-08-27 f153b6739b cmd/compile: use typecheck.InitUniverse in unit tests
+ 2021-08-26 967a8017f7 cmd/compile: move types init code into package types
+ 2021-08-26 af80af22b5 cmd/compile/internal/types2: do not declare new methods on instantiated types
+ 2021-08-26 03db2c2413 cmd/compile/internal/types2: implement TypeList.String (debugging support)
+ 2021-08-26 c9e05fdcf7 cmd/compile: fix reference to generic type needed by crawler
+ 2021-08-26 eb6a07fcf9 cmd/compile: unexport Type.Vargen
+ 2021-08-26 3836983779 cmd/compile/internal/types: unexport Type.Extra
+ 2021-08-26 1f8d4562de cmd/compile: change typecheck.iscmp into ir.Op.IsCmp
+ 2021-08-26 de83ef67ac [dev.cmdgo] all: merge master (5e6a7e9) into dev.cmdgo
+ 2021-08-26 5e6a7e9b86 embed: remove reference to global variables in docs
+ 2021-08-26 166b691b65 cmd/compile/internal/types2: remove need for instance (struct)
+ 2021-08-26 d6bdae33e9 cmd/compile/internal/types2: address some TODOs (cleanup)
+ 2021-08-26 770df2e18d crypto/tls: fix typo in PreferServerCipherSuites comment
+ 2021-08-26 a6ff433d6a cmd/go: pass -gcflags after other flags generated by the go command
+ 2021-08-25 4f2620285d cmd/compile/internal/types2: fix type set printing and add test
+ 2021-08-25 0ac64f6d70 cmd/compile/internal/types2: rename IsMethodSet to IsConstraint (cleanup)
+ 2021-08-25 4068fb6c21 cmd/compile: always accept 1.18 syntax but complain if not 1.18
+ 2021-08-25 bf0bc4122f go/types, types2: don't re-evaluate context string for each function argument (optimization)
+ 2021-08-25 4158e88f64 cmd/compile/internal/syntax: fix position of type parameter field
+ 2021-08-25 647bef6c59 go/types: implement NewTypeList and use it instead of composite literals
+ 2021-08-25 6cf1d5d0fa cmd/compile: generic SSA rules for simplifying 2 and 3 operand integer arithmetic expressions
+ 2021-08-25 5baf60d472 bytes, strings: optimize Trim for single byte cutsets
+ 2021-08-25 3d667671ad cmd/compile: fix function contains no TParam in generic function
+ 2021-08-25 4f2ebfe34b cmd/compile: allow embed into any byte slice type
+ 2021-08-25 d2f002cb39 time/format: avoid growslice in time.String()/time.GoString()
+ 2021-08-25 de23549a39 [dev.cmdgo] cmd/go: fix calls to modFileGoVersion to pass in modFile
+ 2021-08-25 3b523caf41 [dev.cmdgo] cmd/go: clean up TODOWorkspaces instances
+ 2021-08-25 08d4cc20ca cmd/compile: fix stencil call expression.
+ 2021-08-25 109c13b64f [dev.cmdgo] all: merge master (c2f96e6) into dev.cmdgo
+ 2021-08-25 099b819085 cmd/compile: fix CheckSize() calculation for -G=3 and stencils
+ 2021-08-25 e1fcf8857e test: add test that caused gofrontend compiler crash
+ 2021-08-25 d37b8dedf7 test: add test case that gofrontend miscompiled
+ 2021-08-25 41b99dab0f os/user: don't skip TestLookupGroup if supported
+ 2021-08-25 de1c934b97 cmd/compile: fix checkptr false positive for (*[Big]T)(ptr)[:n:n] pattern
+ 2021-08-24 54cdef1f10 reflect: add MapIter.SetKey and MapIter.SetValue
+ 2021-08-24 5d863f89fe cmd/compile: simplify bad conversion check
+ 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 e2e1987b31 [dev.cmdgo] cmd/link: fix TestBuildForTvOS
+ 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 d397fc1169 [dev.cmdgo] don't give command-line-arguments a module
+ 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 aaf914d0e6 [dev.cmdgo] cmd/go: remove modload.ModRoot function
+ 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 337cebd2c151
+ 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 3025ce2fa8 [dev.cmdgo] cmd/go: address code review comments in test cgo_path_space_quote
+ 2021-08-06 8eaf4d16bc make.bash: do not overwrite GO_LDSO if already set
+ 2021-08-06 fc8e0cbbba [dev.cmdgo] cmd: update x/tools and remove copy of txtar
+ 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-31 3799012990 [dev.cmdgo] cmd/go: add go mod editwork command
+ 2021-07-30 b3b53e1dad [dev.cmdgo] cmd/go: thread through modroots providing replacements
+ 2021-07-30 47694b59eb [dev.cmdgo] cmd/go: provide a more helpful missing required module error in workspaces
+ 2021-07-30 90830699ae [dev.cmdgo] cmd/go: allow expliticly setting -mod=readonly in workspace mode
+ 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 8e2ab05dd3 Merge "[dev.cmdgo] all: merge master (9eee0ed) into dev.cmdgo" into dev.cmdgo
+ 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 52e970b1c8 [dev.cmdgo] cmd: support space and quotes in CC and CXX
+ 2021-07-30 3a69cef65a [dev.cmdgo] cmd/internal/str: add utilities for quoting and splitting args
+ 2021-07-30 137089ffb9 [dev.cmdgo] cmd/internal/str: move package from cmd/go/internal/str
+ 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 47cdfa95ae [dev.cmdgo] all: merge master (9eee0ed) into dev.cmdgo
+ 2021-07-28 9eee0ed439 cmd/go: fix go.mod file name printed in error messages for replacements
+ 2021-07-28 473e493d18 [dev.typeparams] cmd/compile/internal/types2: merge instance and Named to eliminate sanitization
+ 2021-07-28 176baafd5b [dev.cmdgo] cmd/go: sort roots when joining multiple main module roots
+ 2021-07-28 288a83dcff [dev.cmdgo] cmd/go: maintain a go.work.sum file
+ 2021-07-28 b39e0f461c runtime: don't crash on nil pointers in checkptrAlignment
+ 2021-07-28 e00a6ec084 [dev.typeparams] cmd/compile: mark methods of instantiated interface types as used
+ 2021-07-27 2c8acf63c2 [dev.cmdgo] cmd/go: make fewer 'go mod' commands update go.mod
+ 2021-07-27 72233d27c4 [dev.cmdgo] cmd/go: add -testsum flag to update go.sum in script tests
+ 2021-07-27 7cd10c1149 cmd/go: use .mod instead of .zip to determine if version has go.mod file
+ 2021-07-27 b2205eab0e [dev.cmdgo] cmd/go: add go mod initwork command
+ 2021-07-27 f05f5ceffa [dev.cmdgo] cmd/go: fold index and modFile into MainModules
+ 2021-07-27 c751e2e6ba [dev.typeparams] cmd/compile/internal/types2: use comparable bit rather than ==() method
+ 2021-07-27 c8cf0f74e4 cmd/go: add missing flag in UsageLine
+ 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-27 7ba8e796c9 testing: clarify T.Name returns a distinct name of the running test
+ 2021-07-27 33ff155970 go/types: preserve untyped constants on the RHS of a shift expression
+ 2021-07-26 840e583ff3 runtime: correct variable name in comment
+ 2021-07-26 bfbb288574 runtime: remove adjustTimers counter
+ 2021-07-26 9c81fd53b3 cmd/vet: add missing copyright header
+ 2021-07-26 7ce257147f [dev.cmdgo] cmd/go: add the workspace mode
+ 2021-07-26 3cd15e02ed [dev.cmdgo] cmd: pull in x/mod on the dev.cmdgo branch
+ 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-26 ecaa6816bf doc: clarify non-nil zero length slice to array pointer conversion
+ 2021-07-26 1868f8296e crypto/x509: update iOS bundled roots to version 55188.120.1.0.1
+ 2021-07-25 849b791129 spec: use consistent capitalization for rune literal hex constants
+ 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 0914646ab9 doc/1.17: fix two dead rfc links
+ 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 052da5717e cmd/compile: do not change field offset in ABI analysis
+ 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 798ec73519 runtime: don't clear timerModifiedEarliest if adjustTimers is 0
+ 2021-07-22 a627fcd3c4 [dev.cmdgo] cmd/go: replace Target with MainModules, allowing for multiple targets
+ 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 fdb45acd1f runtime: move mem profile sampling into m-acquired section
+ 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 3e48c0381f reflect: add missing copyright header
+ 2021-07-21 48c88f1b1b reflect: add Value.CanConvert
+ 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-20 9e26569293 cmd/go: don't add C compiler ID to hash for standard library
+ 2021-07-20 d568e6e075 runtime/debug: skip TestPanicOnFault on netbsd/arm
+ 2021-07-20 ab361499ef [dev.cmdgo] cmd/go/testdata/script: fix a small typo in modfile_flag
+ 2021-07-19 c8f4e6152d spec: correct example comment in Conversions from slice to array
+ 2021-07-19 1d91551b73 time: correct typo in documentation for UnixMicro
+ 2021-07-19 404127c30f cmd/compile: fix off-by-one error in traceback argument counting
+ 2021-07-19 c6d3d0b0ad [dev.typeparams] go/types: fix the type parameter index in applyTypeFunc
+ 2021-07-19 6298cfe672 cmd/compile: fix typo in fatal message of builtinCall
+ 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 49402bee36 cmd/{compile,link}: fix bug in map.zero handling
+ 2021-07-19 9b85985d36 [dev.typeparams] Separate out gcshape types that are instantiated types
+ 2021-07-18 a66190ecee test/bench/go1: fix size for RegexpMatchMedium_32
+ 2021-07-18 650fc2117a text/scanner: use Go convention in Position doc comment
+ 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 aa4e0f528e net/http:  correct capitalization in cancelTimeBody comment
+ 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-15 0941dbca6a testing: clarify in docs that TestMain is advanced
+ 2021-07-15 69728ead87 cmd/go: update error messages in tests to match CL 332573
+ 2021-07-15 c1cc9f9c3d cmd/compile: fix lookup package of redeclared dot import symbol
+ 2021-07-15 21a04e3335 doc/go1.17: mention GOARCH=loong64
+ 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 2b00a54baf go/build, runtime/internal/sys: reserve GOARCH=loong64
+ 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 60ddf42b46 cmd/go: change link in error message from /wiki to /doc.
+ 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 d8f348a589 cmd/go: remove a duplicated word from 'go help mod graph'
+ 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 a98589711d crypto/tls: test key type when casting
+ 2021-07-12 cfbd73ba33 doc/go1.17: editing pass over the "Compiler" section
+ 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 ab4085ce84 runtime/pprof: call runtime.GC twice in memory profile test
+ 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-08 296ddf2a93 net: filter bad names from Lookup functions instead of hard failing
+ 2021-07-08 ce76298ee7 Update oudated comment
+ 2021-07-08 2ca44fe221 doc/go1.17: linkify time.UnixMilli and time.UnixMicro
+ 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 5c59e11f5e cmd/compile: remove special-casing of blank in types.sconv{,2}
+ 2021-07-07 b003a8b1ae cmd/compile: optimize types.sconv
+ 2021-07-07 11f5df2d67 cmd/compile: extract pkgqual from symfmt
+ 2021-07-07 991fd381d5 cmd/go: don't lock .mod and .sum files for read in overlay
+ 2021-07-07 186a3bb4b0 cmd/go/internal/modfetch/codehost: skip hg tests if no hg binary is present
+ 2021-07-07 00c00558e1 cmd/go/internal/modload: remove unused functions
+ 2021-07-07 f264879f74 cmd/go/internal/modload: fix an apparent typo in the AutoRoot comment
+ 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 c96833e5ba doc: remove stale comment about arm64 port
+ 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-06 aa4da4f189 [dev.cmdgo] all: merge master (912f075) into dev.cmdgo
+ 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 912f075047 net/http: mention socks5 support in proxy
+ 2021-07-02 287c5e8066 cmd/compile: fix stack growing algorithm
+ 2021-07-02 743f03eeb0 spec, unsafe: clarify unsafe.Slice docs
+ 2021-07-02 6dec18cc75 [dev.typeparams] cmd/compile: start using sub-dictionary entries where needed
+ 2021-07-02 6125d0c426 cmd/dist: correct comment: SysProcAttri -> SysProcAttr
+ 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 03761ede02 net: don't reject null mx records
+ 2021-07-01 877688c838 testing: add TB.Setenv
+ 2021-07-01 ef8ae82b37 cmd/compile: fix bug in dwarf-gen var location generation
+ 2021-07-01 9ba294e15b [dev.typeparams] cmd/compile: fix getDictionarySym for methods references, write out sub-dictionaries
+ 2021-07-01 770899f7e1 cmd/go: add a regression test for 'go mod vendor' path traversal
+ 2021-07-01 835d86a17e cmd/go: use path.Dir instead of filepath.Dir for package paths in 'go mod vendor'
+ 2021-07-01 eb437ba92c cmd/compile: make stack value size threshold comparisons consistent
+ 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-07-01 9d65578b83 cmd/compile: fix typos in document
+ 2021-06-30 ad7e5b219e [dev.typeparams] all: merge master (4711bf3) into dev.typeparams
+ 2021-06-30 4711bf30e5 doc/go1.17: linkify "language changes" in the runtime section
+ 2021-06-30 8767b87ab5 [dev.typeparams] cmd/compile: functions to create GC shape types/names for a concrete type
+ 2021-06-30 ed56ea73e8 path/filepath: deflake TestEvalSymlinksAboveRoot on darwin
+ 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 c080d0323b cmd/dist: pass -Wno-unknown-warning-option in swig_callback_lto
+ 2021-06-30 7d0e9e6e74 image/gif: fix typo in the comment (io.ReadByte -> io.ByteReader)
+ 2021-06-30 0fa3265fe1 os: change example to avoid deprecated function
+ 2021-06-30 f503740ccf [dev.typeparams] cmd/compile: add derived-type dictionaries to unified IR
+ 2021-06-30 d19a53338f image: add Uniform.RGBA64At and Rectangle.RGBA64At
+ 2021-06-30 c45e800e0c crypto/x509: don't fail on optional auth key id fields
+ 2021-06-29 f9d50953b9 net: fix failure of TestCVE202133195
+ 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 e294b8a49e doc/go1.17: fix typo "MacOS" -> "macOS"
+ 2021-06-29 3463852b76 math/big: fix typo of comment (`BytesScanner` to `ByteScanner`)
+ 2021-06-29 fd4b587da3 cmd/compile: suppress details error for invalid variadic argument type
+ 2021-06-29 e2e05af6e1 cmd/internal/obj/arm64: fix an encoding error of CMPW instruction
+ 2021-06-29 dfa8fd861c [dev.typeparams] cmd/compile: add a field (method) name for function in TestABIUtilsInterfaces
+ 2021-06-28 4bb0847b08 cmd/compile,runtime: change unsafe.Slice((*T)(nil), 0) to return []T(nil)
+ 2021-06-28 1519271a93 spec: change unsafe.Slice((*T)(nil), 0) to return []T(nil)
+ 2021-06-28 5385e2386b runtime/internal/atomic: drop Cas64 pointer indirection in comments
+ 2021-06-28 64e6c75924 [dev.typeparams] cmd/compile: port fix for issue46725 to transform.go
+ 2021-06-28 956c81bfe6 cmd/go: add GOEXPERIMENT to `go env` output
+ 2021-06-28 a1d27269d6 cmd/go: prep for 'go env' refactoring
+ 2021-06-28 901510ed4e cmd/link/internal/ld: skip the windows ASLR test when CGO_ENABLED=0
+ 2021-06-28 361159c055 cmd/cgo: fix 'see gmp.go' to 'see doc.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
+ 2020-12-22 6dc2c16f95 [dev.cmdgo] codereview.cfg: add config for dev.cmdgo

Change-Id: I252f9f64197b9fd0d5b230aa83941c3cfcbda6cf
This commit is contained in:
Jay Conrod 2021-09-08 12:46:16 -07:00
commit 5abfd2379b
1638 changed files with 62407 additions and 31665 deletions

View File

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

View File

@ -47,7 +47,9 @@ pkg image, method (*Paletted) RGBA64At(int, int) color.RGBA64
pkg image, method (*Paletted) SetRGBA64(int, int, color.RGBA64) pkg image, method (*Paletted) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*RGBA) RGBA64At(int, int) color.RGBA64 pkg image, method (*RGBA) RGBA64At(int, int) color.RGBA64
pkg image, method (*RGBA) SetRGBA64(int, int, color.RGBA64) pkg image, method (*RGBA) SetRGBA64(int, int, color.RGBA64)
pkg image, method (*Uniform) RGBA64At(int, int) color.RGBA64
pkg image, method (*YCbCr) RGBA64At(int, int) color.RGBA64 pkg image, method (*YCbCr) RGBA64At(int, int) color.RGBA64
pkg image, method (Rectangle) RGBA64At(int, int) color.RGBA64
pkg image, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At } pkg image, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At }
pkg image, type RGBA64Image interface, At(int, int) color.Color pkg image, type RGBA64Image interface, At(int, int) color.Color
pkg image, type RGBA64Image interface, Bounds() Rectangle pkg image, type RGBA64Image interface, Bounds() Rectangle
@ -78,6 +80,7 @@ pkg net/url, method (Values) Has(string) bool
pkg reflect, func VisibleFields(Type) []StructField pkg reflect, func VisibleFields(Type) []StructField
pkg reflect, method (Method) IsExported() bool pkg reflect, method (Method) IsExported() bool
pkg reflect, method (StructField) IsExported() bool pkg reflect, method (StructField) IsExported() bool
pkg reflect, method (Value) CanConvert(Type) bool
pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete() pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete()
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{} pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{}
@ -179,6 +182,7 @@ pkg syscall (windows-amd64), type SysProcAttr struct, AdditionalInheritedHandles
pkg syscall (windows-amd64), type SysProcAttr struct, ParentProcess Handle pkg syscall (windows-amd64), type SysProcAttr struct, ParentProcess Handle
pkg testing, method (*B) Setenv(string, string) pkg testing, method (*B) Setenv(string, string)
pkg testing, method (*T) Setenv(string, string) pkg testing, method (*T) Setenv(string, string)
pkg testing, type TB interface, Setenv(string, string)
pkg text/template/parse, const SkipFuncCheck = 2 pkg text/template/parse, const SkipFuncCheck = 2
pkg text/template/parse, const SkipFuncCheck Mode pkg text/template/parse, const SkipFuncCheck Mode
pkg time, const Layout = "01/02 03:04:05PM '06 -0700" pkg time, const Layout = "01/02 03:04:05PM '06 -0700"

View File

@ -1,93 +1,111 @@
pkg compress/lzw, method (*Reader) Close() error pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg compress/lzw, method (*Reader) Read([]uint8) (int, error) pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg compress/lzw, method (*Reader) Reset(io.Reader, Order, int) pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg compress/lzw, method (*Writer) Close() error pkg syscall (darwin-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg compress/lzw, method (*Writer) Reset(io.Writer, Order, int) pkg syscall (darwin-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg compress/lzw, method (*Writer) Write([]uint8) (int, error) pkg syscall (darwin-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg compress/lzw, type Reader struct pkg syscall (darwin-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg compress/lzw, type Writer struct pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg crypto/tls, method (*CertificateRequestInfo) Context() context.Context pkg syscall (freebsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg crypto/tls, method (*ClientHelloInfo) Context() context.Context pkg syscall (freebsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg crypto/tls, method (*Conn) HandshakeContext(context.Context) error pkg syscall (freebsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg debug/elf, const SHT_MIPS_ABIFLAGS = 1879048234 pkg syscall (freebsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg debug/elf, const SHT_MIPS_ABIFLAGS SectionType pkg syscall (freebsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg encoding/csv, method (*Reader) FieldPos(int) (int, int) pkg syscall (freebsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg go/ast, method (*FuncDecl) IsMethod() bool pkg syscall (freebsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg go/build, type Context struct, ToolTags []string pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg go/parser, const SkipObjectResolution = 64 pkg syscall (freebsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg go/parser, const SkipObjectResolution Mode pkg syscall (freebsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg go/types, type Config struct, GoVersion string pkg syscall (freebsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg io/fs, func FileInfoToDirEntry(FileInfo) DirEntry pkg syscall (freebsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg net, method (*ParseError) Temporary() bool pkg syscall (freebsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg net, method (*ParseError) Timeout() bool pkg syscall (freebsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg net, method (IP) IsPrivate() bool pkg syscall (freebsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg reflect, func VisibleFields(Type) []StructField pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg reflect, method (Method) IsExported() bool pkg syscall (freebsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg reflect, method (StructField) IsExported() bool pkg syscall (freebsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle pkg syscall (freebsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete() pkg syscall (freebsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{} pkg syscall (freebsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (darwin-amd64-cgo), type Handle uintptr pkg syscall (freebsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (freebsd-386-cgo), func NewHandle(interface{}) Handle pkg syscall (freebsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (freebsd-386-cgo), method (Handle) Delete() pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (freebsd-386-cgo), method (Handle) Value() interface{} pkg syscall (linux-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (freebsd-386-cgo), type Handle uintptr pkg syscall (linux-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (freebsd-amd64-cgo), func NewHandle(interface{}) Handle pkg syscall (linux-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (freebsd-amd64-cgo), method (Handle) Delete() pkg syscall (linux-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (freebsd-amd64-cgo), method (Handle) Value() interface{} pkg syscall (linux-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (freebsd-amd64-cgo), type Handle uintptr pkg syscall (linux-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (freebsd-arm-cgo), func NewHandle(interface{}) Handle pkg syscall (linux-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (freebsd-arm-cgo), method (Handle) Delete() pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (freebsd-arm-cgo), method (Handle) Value() interface{} pkg syscall (linux-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (freebsd-arm-cgo), type Handle uintptr pkg syscall (linux-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (linux-386-cgo), func NewHandle(interface{}) Handle pkg syscall (linux-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (linux-386-cgo), method (Handle) Delete() pkg syscall (linux-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (linux-386-cgo), method (Handle) Value() interface{} pkg syscall (linux-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (linux-386-cgo), type Handle uintptr pkg syscall (linux-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (linux-amd64-cgo), func NewHandle(interface{}) Handle pkg syscall (linux-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (linux-amd64-cgo), method (Handle) Delete() pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (linux-amd64-cgo), method (Handle) Value() interface{} pkg syscall (linux-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (linux-amd64-cgo), type Handle uintptr pkg syscall (linux-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (linux-arm-cgo), func NewHandle(interface{}) Handle pkg syscall (linux-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (linux-arm-cgo), method (Handle) Delete() pkg syscall (linux-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (linux-arm-cgo), method (Handle) Value() interface{} pkg syscall (linux-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (linux-arm-cgo), type Handle uintptr pkg syscall (linux-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (netbsd-386-cgo), func NewHandle(interface{}) Handle pkg syscall (linux-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (netbsd-386-cgo), method (Handle) Delete() pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (netbsd-386-cgo), method (Handle) Value() interface{} pkg syscall (netbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (netbsd-386-cgo), type Handle uintptr pkg syscall (netbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (netbsd-amd64-cgo), func NewHandle(interface{}) Handle pkg syscall (netbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (netbsd-amd64-cgo), method (Handle) Delete() pkg syscall (netbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (netbsd-amd64-cgo), method (Handle) Value() interface{} pkg syscall (netbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (netbsd-amd64-cgo), type Handle uintptr pkg syscall (netbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (netbsd-arm-cgo), func NewHandle(interface{}) Handle pkg syscall (netbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (netbsd-arm-cgo), method (Handle) Delete() pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (netbsd-arm-cgo), method (Handle) Value() interface{} pkg syscall (netbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (netbsd-arm-cgo), type Handle uintptr pkg syscall (netbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (netbsd-arm64-cgo), func NewHandle(interface{}) Handle pkg syscall (netbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (netbsd-arm64-cgo), method (Handle) Delete() pkg syscall (netbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (netbsd-arm64-cgo), method (Handle) Value() interface{} pkg syscall (netbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (netbsd-arm64-cgo), type Handle uintptr pkg syscall (netbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (openbsd-386-cgo), func NewHandle(interface{}) Handle pkg syscall (netbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (openbsd-386-cgo), method (Handle) Delete() pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (openbsd-386-cgo), method (Handle) Value() interface{} pkg syscall (netbsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (openbsd-386-cgo), type Handle uintptr pkg syscall (netbsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg runtime/cgo (openbsd-amd64-cgo), func NewHandle(interface{}) Handle pkg syscall (netbsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg runtime/cgo (openbsd-amd64-cgo), method (Handle) Delete() pkg syscall (netbsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg runtime/cgo (openbsd-amd64-cgo), method (Handle) Value() interface{} pkg syscall (netbsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg runtime/cgo (openbsd-amd64-cgo), type Handle uintptr pkg syscall (netbsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-386), const MSG_CMSG_CLOEXEC = 2048 pkg syscall (netbsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-386), const MSG_CMSG_CLOEXEC ideal-int pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (openbsd-386-cgo), const MSG_CMSG_CLOEXEC = 2048 pkg syscall (netbsd-arm64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (openbsd-386-cgo), const MSG_CMSG_CLOEXEC ideal-int pkg syscall (netbsd-arm64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-amd64), const MSG_CMSG_CLOEXEC = 2048 pkg syscall (netbsd-arm64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-amd64), const MSG_CMSG_CLOEXEC ideal-int pkg syscall (netbsd-arm64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (openbsd-amd64-cgo), const MSG_CMSG_CLOEXEC = 2048 pkg syscall (netbsd-arm64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (openbsd-amd64-cgo), const MSG_CMSG_CLOEXEC ideal-int pkg syscall (netbsd-arm64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (windows-386), type SysProcAttr struct, AdditionalInheritedHandles []Handle pkg syscall (netbsd-arm64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (windows-386), type SysProcAttr struct, ParentProcess Handle pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (windows-amd64), type SysProcAttr struct, AdditionalInheritedHandles []Handle pkg syscall (openbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (windows-amd64), type SysProcAttr struct, ParentProcess Handle pkg syscall (openbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (openbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (openbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (openbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (openbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (openbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
pkg syscall (openbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
pkg syscall (windows-386), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error
pkg syscall (windows-386), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error
pkg syscall (windows-amd64), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error
pkg syscall (windows-amd64), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error
pkg testing, func Fuzz(func(*F)) FuzzResult pkg testing, func Fuzz(func(*F)) FuzzResult
pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalFuzzTarget, []InternalExample) *M pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalFuzzTarget, []InternalExample) *M
pkg testing, func RunFuzzTargets(func(string, string) (bool, error), []InternalFuzzTarget) bool pkg testing, func RunFuzzTargets(func(string, string) (bool, error), []InternalFuzzTarget) bool
@ -124,10 +142,3 @@ pkg testing, type FuzzResult struct, T time.Duration
pkg testing, type InternalFuzzTarget struct pkg testing, type InternalFuzzTarget struct
pkg testing, type InternalFuzzTarget struct, Fn func(*F) pkg testing, type InternalFuzzTarget struct, Fn func(*F)
pkg testing, type InternalFuzzTarget struct, Name string pkg testing, type InternalFuzzTarget struct, Name string
pkg text/template/parse, const SkipFuncCheck = 2
pkg text/template/parse, const SkipFuncCheck Mode
pkg time, func UnixMicro(int64) Time
pkg time, func UnixMilli(int64) Time
pkg time, method (*Time) IsDST() bool
pkg time, method (Time) UnixMicro() int64
pkg time, method (Time) UnixMilli() int64

View File

@ -166,7 +166,7 @@ jumps and branches.
</li> </li>
<li> <li>
<code>SP</code>: Stack pointer: top of stack. <code>SP</code>: Stack pointer: the highest address within the local stack frame.
</li> </li>
</ul> </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 The <code>SP</code> pseudo-register is a virtual stack pointer
used to refer to frame-local variables and the arguments being used to refer to frame-local variables and the arguments being
prepared for function calls. 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): in the range [framesize, 0):
<code>x-8(SP)</code>, <code>y-4(SP)</code>, and so on. <code>x-8(SP)</code>, <code>y-4(SP)</code>, and so on.
</p> </p>
@ -409,7 +409,7 @@ The linker will choose one of the duplicates to use.
(For <code>TEXT</code> items.) (For <code>TEXT</code> items.)
Don't insert the preamble to check if the stack must be split. 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 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. Used to protect routines such as the stack splitting code itself.
</li> </li>
<li> <li>
@ -460,7 +460,7 @@ Only valid on functions that declare a frame size of 0.
<code>TOPFRAME</code> = 2048 <code>TOPFRAME</code> = 2048
<br> <br>
(For <code>TEXT</code> items.) (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> </li>
</ul> </ul>
@ -827,10 +827,6 @@ The other codes are <code>-&gt;</code> (arithmetic right shift),
<h3 id="arm64">ARM64</h3> <h3 id="arm64">ARM64</h3>
<p>
The ARM64 port is in an experimental state.
</p>
<p> <p>
<code>R18</code> is the "platform register", reserved on the Apple platform. <code>R18</code> is the "platform register", reserved on the Apple platform.
To prevent accidental misuse, the register is named <code>R18_PLATFORM</code>. To prevent accidental misuse, the register is named <code>R18_PLATFORM</code>.

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,114 @@
<!--{
"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="image/draw"><dt><a href="/pkg/image/draw/">image/draw</a></dt>
<dd>
<p><!-- CL 340049 -->
The <code>Draw</code> and <code>DrawMask</code> fallback implementations
(used when the arguments are not the most common image types) are now
faster when those arguments implement the optional
<a href="/pkg/image/draw/#RGBA64Image"><code>draw.RGBA64Image</code></a>
and <a href="/pkg/image/#RGBA64Image"><code>image.RGBA64Image</code></a>
interfaces that were added in Go 1.17.
</p>
</dd>
</dl><!-- image/draw -->
<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", "Title": "The Go Programming Language Specification",
"Subtitle": "Version of Jun 22, 2021", "Subtitle": "Version of Aug 23, 2021",
"Path": "/ref/spec" "Path": "/ref/spec"
}--> }-->
@ -490,8 +490,8 @@ After a backslash, certain single-character escapes represent special values:
\n U+000A line feed or newline \n U+000A line feed or newline
\r U+000D carriage return \r U+000D carriage return
\t U+0009 horizontal tab \t U+0009 horizontal tab
\v U+000b vertical tab \v U+000B vertical tab
\\ U+005c backslash \\ U+005C backslash
\' U+0027 single quote (valid escape only within rune literals) \' U+0027 single quote (valid escape only within rune literals)
\" U+0022 double quote (valid escape only within string literals) \" U+0022 double quote (valid escape only within string literals)
</pre> </pre>
@ -3000,6 +3000,18 @@ method value; the saved copy is then used as the receiver in any calls,
which may be executed later. which may be executed later.
</p> </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> <p>
The type <code>T</code> may be an interface or non-interface type. The type <code>T</code> may be an interface or non-interface type.
</p> </p>
@ -4329,12 +4341,16 @@ a <a href="#Run_time_panics">run-time panic</a> occurs.
<pre> <pre>
s := make([]byte, 2, 4) s := make([]byte, 2, 4)
s0 := (*[0]byte)(s) // s0 != nil 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] s2 := (*[2]byte)(s) // &amp;s2[0] == &amp;s[0]
s4 := (*[4]byte)(s) // panics: len([4]byte) > len(s) s4 := (*[4]byte)(s) // panics: len([4]byte) > len(s)
var t []string var t []string
t0 := (*[0]string)(t) // t0 == nil t0 := (*[0]string)(t) // t0 == nil
t1 := (*[1]string)(t) // panics: len([1]string) > len(s) t1 := (*[1]string)(t) // panics: len([1]string) > len(t)
u := make([]byte, 0)
u0 := (*[0]byte)(u) // u0 != nil
</pre> </pre>
<h3 id="Constant_expressions">Constant expressions</h3> <h3 id="Constant_expressions">Constant expressions</h3>
@ -6782,18 +6798,26 @@ The rules for <a href="/pkg/unsafe#Pointer">valid uses</a> of <code>Pointer</cod
<p> <p>
The function <code>Slice</code> returns a slice whose underlying array starts at <code>ptr</code> The function <code>Slice</code> returns a slice whose underlying array starts at <code>ptr</code>
and whose length and capacity are <code>len</code>: and whose length and capacity are <code>len</code>.
<code>Slice(ptr, len)</code> is equivalent to
</p> </p>
<pre> <pre>
(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:] (*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
</pre> </pre>
<p>
except that, as a special case, if <code>ptr</code>
is <code>nil</code> and <code>len</code> is zero,
<code>Slice</code> returns <code>nil</code>.
</p>
<p> <p>
The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>. The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
A constant <code>len</code> argument must be non-negative and <a href="#Representability">representable</a> by a value of type <code>int</code>; A constant <code>len</code> argument must be non-negative and <a href="#Representability">representable</a> by a value of type <code>int</code>;
if it is an untyped constant it is given type <code>int</code>. if it is an untyped constant it is given type <code>int</code>.
If <code>ptr</code> is <code>nil</code> or <code>len</code> is negative at run time, At run time, if <code>len</code> is negative,
or if <code>ptr</code> is <code>nil</code> and <code>len</code> is not zero,
a <a href="#Run_time_panics">run-time panic</a> occurs. a <a href="#Run_time_panics">run-time panic</a> occurs.
</p> </p>

View File

@ -4,7 +4,7 @@ The IANA asserts that the database is in the public domain.
For more information, see For more information, see
https://www.iana.org/time-zones https://www.iana.org/time-zones
ftp://ftp.iana.org/tz/code/tz-link.htm ftp://ftp.iana.org/tz/code/tz-link.html
http://tools.ietf.org/html/rfc6557 https://datatracker.ietf.org/doc/html/rfc6557
To rebuild the archive, read and run update.bash. To rebuild the archive, read and run update.bash.

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build ignore
// +build ignore // +build ignore
// This program can be used as go_android_GOARCH_exec by the Go tool. // This program can be used as go_android_GOARCH_exec by the Go tool.

View File

@ -91,10 +91,18 @@ func main() {
// issue 26745 // issue 26745
_ = func(i int) int { _ = 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) { _ = 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 C.fi = C.fi // ERROR HERE

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build ignore
// +build ignore // +build ignore
// Compute Fibonacci numbers with two goroutines // Compute Fibonacci numbers with two goroutines

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build ignore
// +build ignore // +build ignore
package main package main

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build linux && freebsd && openbsd
// +build linux,freebsd,openbsd // +build linux,freebsd,openbsd
package cgotest package cgotest

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !windows
// +build !windows // +build !windows
package cgotest package cgotest

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build linux && cgo
// +build linux,cgo // +build linux,cgo
package cgotest package cgotest

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !windows
// +build !windows // +build !windows
// Issue 18146: pthread_create failure during syscall.Exec. // 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 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build darwin && cgo && !internal
// +build darwin,cgo,!internal // +build darwin,cgo,!internal
package cgotest package cgotest

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !darwin || !cgo || internal
// +build !darwin !cgo internal // +build !darwin !cgo internal
package cgotest package cgotest

View File

@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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 // +build !darwin !internal_pie,!arm64
// Excluded in darwin internal linking PIE mode, as dynamic export is not // 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 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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 // +build windows static darwin,internal_pie darwin,arm64
package cgotest package cgotest

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !android
// +build !android // +build !android
// Test that pthread_cancel works as expected // Test that pthread_cancel works as expected

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !windows
// +build !windows // +build !windows
package cgotest package cgotest

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !android
// +build !android // +build !android
package cgotest package cgotest

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !windows && !android
// +build !windows,!android // +build !windows,!android
// Test that the Go runtime still works if C code changes the signal stack. // 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 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !windows
// +build !windows // +build !windows
package cgotest package cgotest

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !windows
// +build !windows // +build !windows
package cgotest 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: "msan5.go"},
{src: "msan6.go"}, {src: "msan6.go"},
{src: "msan7.go"}, {src: "msan7.go"},
{src: "msan8.go"},
{src: "msan_fail.go", wantErr: true}, {src: "msan_fail.go", wantErr: true},
} }
for _, tc := range cases { 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 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !cgo
// +build !cgo // +build !cgo
package so_test package so_test

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build cgo
// +build cgo // +build cgo
package so_test package so_test

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !cgo
// +build !cgo // +build !cgo
package so_test package so_test

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build cgo
// +build cgo // +build cgo
package so_test package so_test

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !windows
// +build !windows // +build !windows
package cgotlstest package cgotlstest

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build ignore
// +build ignore // +build ignore
// detect attempts to autodetect the correct // detect attempts to autodetect the correct

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build explicit
// +build explicit // +build explicit
// Package experiment_toolid_test verifies that GOEXPERIMENT settings built // Package experiment_toolid_test verifies that GOEXPERIMENT settings built

View File

@ -1,6 +1,7 @@
// Copyright 2018 The Go Authors. All rights reserved. // Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
"use strict";
(() => { (() => {
// Map multiple JavaScript environments to a single common API, // Map multiple JavaScript environments to a single common API,

View File

@ -316,10 +316,10 @@ func invertSparseEntries(src []sparseEntry, size int64) []sparseEntry {
// fileState tracks the number of logical (includes sparse holes) and physical // fileState tracks the number of logical (includes sparse holes) and physical
// (actual in tar archive) bytes remaining for the current file. // (actual in tar archive) bytes remaining for the current file.
// //
// Invariant: LogicalRemaining >= PhysicalRemaining // Invariant: logicalRemaining >= physicalRemaining
type fileState interface { type fileState interface {
LogicalRemaining() int64 logicalRemaining() int64
PhysicalRemaining() int64 physicalRemaining() int64
} }
// allowedFormats determines which formats can be used. // 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. // Check basic fields.
var blk block var blk block
v7 := blk.V7() v7 := blk.toV7()
ustar := blk.USTAR() ustar := blk.toUSTAR()
gnu := blk.GNU() gnu := blk.toGNU()
verifyString(h.Name, len(v7.Name()), "Name", paxPath) verifyString(h.Name, len(v7.name()), "Name", paxPath)
verifyString(h.Linkname, len(v7.LinkName()), "Linkname", paxLinkpath) verifyString(h.Linkname, len(v7.linkName()), "Linkname", paxLinkpath)
verifyString(h.Uname, len(ustar.UserName()), "Uname", paxUname) verifyString(h.Uname, len(ustar.userName()), "Uname", paxUname)
verifyString(h.Gname, len(ustar.GroupName()), "Gname", paxGname) verifyString(h.Gname, len(ustar.groupName()), "Gname", paxGname)
verifyNumeric(h.Mode, len(v7.Mode()), "Mode", paxNone) verifyNumeric(h.Mode, len(v7.mode()), "Mode", paxNone)
verifyNumeric(int64(h.Uid), len(v7.UID()), "Uid", paxUid) verifyNumeric(int64(h.Uid), len(v7.uid()), "Uid", paxUid)
verifyNumeric(int64(h.Gid), len(v7.GID()), "Gid", paxGid) verifyNumeric(int64(h.Gid), len(v7.gid()), "Gid", paxGid)
verifyNumeric(h.Size, len(v7.Size()), "Size", paxSize) verifyNumeric(h.Size, len(v7.size()), "Size", paxSize)
verifyNumeric(h.Devmajor, len(ustar.DevMajor()), "Devmajor", paxNone) verifyNumeric(h.Devmajor, len(ustar.devMajor()), "Devmajor", paxNone)
verifyNumeric(h.Devminor, len(ustar.DevMinor()), "Devminor", paxNone) verifyNumeric(h.Devminor, len(ustar.devMinor()), "Devminor", paxNone)
verifyTime(h.ModTime, len(v7.ModTime()), "ModTime", paxMtime) verifyTime(h.ModTime, len(v7.modTime()), "ModTime", paxMtime)
verifyTime(h.AccessTime, len(gnu.AccessTime()), "AccessTime", paxAtime) verifyTime(h.AccessTime, len(gnu.accessTime()), "AccessTime", paxAtime)
verifyTime(h.ChangeTime, len(gnu.ChangeTime()), "ChangeTime", paxCtime) verifyTime(h.ChangeTime, len(gnu.changeTime()), "ChangeTime", paxCtime)
// Check for header-only types. // Check for header-only types.
var whyOnlyPAX, whyOnlyGNU string var whyOnlyPAX, whyOnlyGNU string

View File

@ -156,28 +156,28 @@ var zeroBlock block
type block [blockSize]byte type block [blockSize]byte
// Convert block to any number of formats. // Convert block to any number of formats.
func (b *block) V7() *headerV7 { return (*headerV7)(b) } func (b *block) toV7() *headerV7 { return (*headerV7)(b) }
func (b *block) GNU() *headerGNU { return (*headerGNU)(b) } func (b *block) toGNU() *headerGNU { return (*headerGNU)(b) }
func (b *block) STAR() *headerSTAR { return (*headerSTAR)(b) } func (b *block) toSTAR() *headerSTAR { return (*headerSTAR)(b) }
func (b *block) USTAR() *headerUSTAR { return (*headerUSTAR)(b) } func (b *block) toUSTAR() *headerUSTAR { return (*headerUSTAR)(b) }
func (b *block) Sparse() sparseArray { return sparseArray(b[:]) } func (b *block) toSparse() sparseArray { return sparseArray(b[:]) }
// GetFormat checks that the block is a valid tar header based on the checksum. // 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. // It then attempts to guess the specific format based on magic values.
// If the checksum fails, then FormatUnknown is returned. // If the checksum fails, then FormatUnknown is returned.
func (b *block) GetFormat() Format { func (b *block) getFormat() Format {
// Verify checksum. // Verify checksum.
var p parser var p parser
value := p.parseOctal(b.V7().Chksum()) value := p.parseOctal(b.toV7().chksum())
chksum1, chksum2 := b.ComputeChecksum() chksum1, chksum2 := b.computeChecksum()
if p.err != nil || (value != chksum1 && value != chksum2) { if p.err != nil || (value != chksum1 && value != chksum2) {
return FormatUnknown return FormatUnknown
} }
// Guess the magic values. // Guess the magic values.
magic := string(b.USTAR().Magic()) magic := string(b.toUSTAR().magic())
version := string(b.USTAR().Version()) version := string(b.toUSTAR().version())
trailer := string(b.STAR().Trailer()) trailer := string(b.toSTAR().trailer())
switch { switch {
case magic == magicUSTAR && trailer == trailerSTAR: case magic == magicUSTAR && trailer == trailerSTAR:
return formatSTAR 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. // and then updates the checksum accordingly.
func (b *block) SetFormat(format Format) { func (b *block) setFormat(format Format) {
// Set the magic values. // Set the magic values.
switch { switch {
case format.has(formatV7): case format.has(formatV7):
// Do nothing. // Do nothing.
case format.has(FormatGNU): case format.has(FormatGNU):
copy(b.GNU().Magic(), magicGNU) copy(b.toGNU().magic(), magicGNU)
copy(b.GNU().Version(), versionGNU) copy(b.toGNU().version(), versionGNU)
case format.has(formatSTAR): case format.has(formatSTAR):
copy(b.STAR().Magic(), magicUSTAR) copy(b.toSTAR().magic(), magicUSTAR)
copy(b.STAR().Version(), versionUSTAR) copy(b.toSTAR().version(), versionUSTAR)
copy(b.STAR().Trailer(), trailerSTAR) copy(b.toSTAR().trailer(), trailerSTAR)
case format.has(FormatUSTAR | FormatPAX): case format.has(FormatUSTAR | FormatPAX):
copy(b.USTAR().Magic(), magicUSTAR) copy(b.toUSTAR().magic(), magicUSTAR)
copy(b.USTAR().Version(), versionUSTAR) copy(b.toUSTAR().version(), versionUSTAR)
default: default:
panic("invalid format") panic("invalid format")
} }
@ -214,17 +214,17 @@ func (b *block) SetFormat(format Format) {
// Update checksum. // Update checksum.
// This field is special in that it is terminated by a NULL then space. // This field is special in that it is terminated by a NULL then space.
var f formatter var f formatter
field := b.V7().Chksum() field := b.toV7().chksum()
chksum, _ := b.ComputeChecksum() // Possible values are 256..128776 chksum, _ := b.computeChecksum() // Possible values are 256..128776
f.formatOctal(field[:7], chksum) // Never fails since 128776 < 262143 f.formatOctal(field[:7], chksum) // Never fails since 128776 < 262143
field[7] = ' ' 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 // POSIX specifies a sum of the unsigned byte values, but the Sun tar used
// signed byte values. // signed byte values.
// We compute and return both. // We compute and return both.
func (b *block) ComputeChecksum() (unsigned, signed int64) { func (b *block) computeChecksum() (unsigned, signed int64) {
for i, c := range b { for i, c := range b {
if 148 <= i && i < 156 { if 148 <= i && i < 156 {
c = ' ' // Treat the checksum field itself as all spaces. 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. // Reset clears the block with all zeros.
func (b *block) Reset() { func (b *block) reset() {
*b = block{} *b = block{}
} }
type headerV7 [blockSize]byte type headerV7 [blockSize]byte
func (h *headerV7) Name() []byte { return h[000:][:100] } func (h *headerV7) name() []byte { return h[000:][:100] }
func (h *headerV7) Mode() []byte { return h[100:][:8] } func (h *headerV7) mode() []byte { return h[100:][:8] }
func (h *headerV7) UID() []byte { return h[108:][:8] } func (h *headerV7) uid() []byte { return h[108:][:8] }
func (h *headerV7) GID() []byte { return h[116:][:8] } func (h *headerV7) gid() []byte { return h[116:][:8] }
func (h *headerV7) Size() []byte { return h[124:][:12] } func (h *headerV7) size() []byte { return h[124:][:12] }
func (h *headerV7) ModTime() []byte { return h[136:][:12] } func (h *headerV7) modTime() []byte { return h[136:][:12] }
func (h *headerV7) Chksum() []byte { return h[148:][:8] } func (h *headerV7) chksum() []byte { return h[148:][:8] }
func (h *headerV7) TypeFlag() []byte { return h[156:][:1] } func (h *headerV7) typeFlag() []byte { return h[156:][:1] }
func (h *headerV7) LinkName() []byte { return h[157:][:100] } func (h *headerV7) linkName() []byte { return h[157:][:100] }
type headerGNU [blockSize]byte type headerGNU [blockSize]byte
func (h *headerGNU) V7() *headerV7 { return (*headerV7)(h) } func (h *headerGNU) v7() *headerV7 { return (*headerV7)(h) }
func (h *headerGNU) Magic() []byte { return h[257:][:6] } func (h *headerGNU) magic() []byte { return h[257:][:6] }
func (h *headerGNU) Version() []byte { return h[263:][:2] } func (h *headerGNU) version() []byte { return h[263:][:2] }
func (h *headerGNU) UserName() []byte { return h[265:][:32] } func (h *headerGNU) userName() []byte { return h[265:][:32] }
func (h *headerGNU) GroupName() []byte { return h[297:][:32] } func (h *headerGNU) groupName() []byte { return h[297:][:32] }
func (h *headerGNU) DevMajor() []byte { return h[329:][:8] } func (h *headerGNU) devMajor() []byte { return h[329:][:8] }
func (h *headerGNU) DevMinor() []byte { return h[337:][:8] } func (h *headerGNU) devMinor() []byte { return h[337:][:8] }
func (h *headerGNU) AccessTime() []byte { return h[345:][:12] } func (h *headerGNU) accessTime() []byte { return h[345:][:12] }
func (h *headerGNU) ChangeTime() []byte { return h[357:][: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) sparse() sparseArray { return sparseArray(h[386:][:24*4+1]) }
func (h *headerGNU) RealSize() []byte { return h[483:][:12] } func (h *headerGNU) realSize() []byte { return h[483:][:12] }
type headerSTAR [blockSize]byte type headerSTAR [blockSize]byte
func (h *headerSTAR) V7() *headerV7 { return (*headerV7)(h) } func (h *headerSTAR) v7() *headerV7 { return (*headerV7)(h) }
func (h *headerSTAR) Magic() []byte { return h[257:][:6] } func (h *headerSTAR) magic() []byte { return h[257:][:6] }
func (h *headerSTAR) Version() []byte { return h[263:][:2] } func (h *headerSTAR) version() []byte { return h[263:][:2] }
func (h *headerSTAR) UserName() []byte { return h[265:][:32] } func (h *headerSTAR) userName() []byte { return h[265:][:32] }
func (h *headerSTAR) GroupName() []byte { return h[297:][:32] } func (h *headerSTAR) groupName() []byte { return h[297:][:32] }
func (h *headerSTAR) DevMajor() []byte { return h[329:][:8] } func (h *headerSTAR) devMajor() []byte { return h[329:][:8] }
func (h *headerSTAR) DevMinor() []byte { return h[337:][:8] } func (h *headerSTAR) devMinor() []byte { return h[337:][:8] }
func (h *headerSTAR) Prefix() []byte { return h[345:][:131] } func (h *headerSTAR) prefix() []byte { return h[345:][:131] }
func (h *headerSTAR) AccessTime() []byte { return h[476:][:12] } func (h *headerSTAR) accessTime() []byte { return h[476:][:12] }
func (h *headerSTAR) ChangeTime() []byte { return h[488:][:12] } func (h *headerSTAR) changeTime() []byte { return h[488:][:12] }
func (h *headerSTAR) Trailer() []byte { return h[508:][:4] } func (h *headerSTAR) trailer() []byte { return h[508:][:4] }
type headerUSTAR [blockSize]byte type headerUSTAR [blockSize]byte
func (h *headerUSTAR) V7() *headerV7 { return (*headerV7)(h) } func (h *headerUSTAR) v7() *headerV7 { return (*headerV7)(h) }
func (h *headerUSTAR) Magic() []byte { return h[257:][:6] } func (h *headerUSTAR) magic() []byte { return h[257:][:6] }
func (h *headerUSTAR) Version() []byte { return h[263:][:2] } func (h *headerUSTAR) version() []byte { return h[263:][:2] }
func (h *headerUSTAR) UserName() []byte { return h[265:][:32] } func (h *headerUSTAR) userName() []byte { return h[265:][:32] }
func (h *headerUSTAR) GroupName() []byte { return h[297:][:32] } func (h *headerUSTAR) groupName() []byte { return h[297:][:32] }
func (h *headerUSTAR) DevMajor() []byte { return h[329:][:8] } func (h *headerUSTAR) devMajor() []byte { return h[329:][:8] }
func (h *headerUSTAR) DevMinor() []byte { return h[337:][:8] } func (h *headerUSTAR) devMinor() []byte { return h[337:][:8] }
func (h *headerUSTAR) Prefix() []byte { return h[345:][:155] } func (h *headerUSTAR) prefix() []byte { return h[345:][:155] }
type sparseArray []byte type sparseArray []byte
func (s sparseArray) Entry(i int) sparseElem { return sparseElem(s[i*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) isExtended() []byte { return s[24*s.maxEntries():][:1] }
func (s sparseArray) MaxEntries() int { return len(s) / 24 } func (s sparseArray) maxEntries() int { return len(s) / 24 }
type sparseElem []byte type sparseElem []byte
func (s sparseElem) Offset() []byte { return s[00:][:12] } func (s sparseElem) offset() []byte { return s[00:][:12] }
func (s sparseElem) Length() []byte { return s[12:][: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 format := FormatUSTAR | FormatPAX | FormatGNU
for { for {
// Discard the remainder of the file and any padding. // 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 return nil, err
} }
if _, err := tryReadFull(tr.r, tr.blk[:tr.pad]); err != nil { 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. // Verify the header matches a known format.
format := tr.blk.GetFormat() format := tr.blk.getFormat()
if format == FormatUnknown { if format == FormatUnknown {
return nil, nil, ErrHeader return nil, nil, ErrHeader
} }
@ -364,30 +364,30 @@ func (tr *Reader) readHeader() (*Header, *block, error) {
hdr := new(Header) hdr := new(Header)
// Unpack the V7 header. // Unpack the V7 header.
v7 := tr.blk.V7() v7 := tr.blk.toV7()
hdr.Typeflag = v7.TypeFlag()[0] hdr.Typeflag = v7.typeFlag()[0]
hdr.Name = p.parseString(v7.Name()) hdr.Name = p.parseString(v7.name())
hdr.Linkname = p.parseString(v7.LinkName()) hdr.Linkname = p.parseString(v7.linkName())
hdr.Size = p.parseNumeric(v7.Size()) hdr.Size = p.parseNumeric(v7.size())
hdr.Mode = p.parseNumeric(v7.Mode()) hdr.Mode = p.parseNumeric(v7.mode())
hdr.Uid = int(p.parseNumeric(v7.UID())) hdr.Uid = int(p.parseNumeric(v7.uid()))
hdr.Gid = int(p.parseNumeric(v7.GID())) hdr.Gid = int(p.parseNumeric(v7.gid()))
hdr.ModTime = time.Unix(p.parseNumeric(v7.ModTime()), 0) hdr.ModTime = time.Unix(p.parseNumeric(v7.modTime()), 0)
// Unpack format specific fields. // Unpack format specific fields.
if format > formatV7 { if format > formatV7 {
ustar := tr.blk.USTAR() ustar := tr.blk.toUSTAR()
hdr.Uname = p.parseString(ustar.UserName()) hdr.Uname = p.parseString(ustar.userName())
hdr.Gname = p.parseString(ustar.GroupName()) hdr.Gname = p.parseString(ustar.groupName())
hdr.Devmajor = p.parseNumeric(ustar.DevMajor()) hdr.Devmajor = p.parseNumeric(ustar.devMajor())
hdr.Devminor = p.parseNumeric(ustar.DevMinor()) hdr.Devminor = p.parseNumeric(ustar.devMinor())
var prefix string var prefix string
switch { switch {
case format.has(FormatUSTAR | FormatPAX): case format.has(FormatUSTAR | FormatPAX):
hdr.Format = format hdr.Format = format
ustar := tr.blk.USTAR() ustar := tr.blk.toUSTAR()
prefix = p.parseString(ustar.Prefix()) prefix = p.parseString(ustar.prefix())
// For Format detection, check if block is properly formatted since // For Format detection, check if block is properly formatted since
// the parser is more liberal than what USTAR actually permits. // 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. hdr.Format = FormatUnknown // Non-ASCII characters in block.
} }
nul := func(b []byte) bool { return int(b[len(b)-1]) == 0 } 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()) && if !(nul(v7.size()) && nul(v7.mode()) && nul(v7.uid()) && nul(v7.gid()) &&
nul(v7.ModTime()) && nul(ustar.DevMajor()) && nul(ustar.DevMinor())) { nul(v7.modTime()) && nul(ustar.devMajor()) && nul(ustar.devMinor())) {
hdr.Format = FormatUnknown // Numeric fields must end in NUL hdr.Format = FormatUnknown // Numeric fields must end in NUL
} }
case format.has(formatSTAR): case format.has(formatSTAR):
star := tr.blk.STAR() star := tr.blk.toSTAR()
prefix = p.parseString(star.Prefix()) prefix = p.parseString(star.prefix())
hdr.AccessTime = time.Unix(p.parseNumeric(star.AccessTime()), 0) hdr.AccessTime = time.Unix(p.parseNumeric(star.accessTime()), 0)
hdr.ChangeTime = time.Unix(p.parseNumeric(star.ChangeTime()), 0) hdr.ChangeTime = time.Unix(p.parseNumeric(star.changeTime()), 0)
case format.has(FormatGNU): case format.has(FormatGNU):
hdr.Format = format hdr.Format = format
var p2 parser var p2 parser
gnu := tr.blk.GNU() gnu := tr.blk.toGNU()
if b := gnu.AccessTime(); b[0] != 0 { if b := gnu.accessTime(); b[0] != 0 {
hdr.AccessTime = time.Unix(p2.parseNumeric(b), 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) 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 // See https://golang.org/issues/21005
if p2.err != nil { if p2.err != nil {
hdr.AccessTime, hdr.ChangeTime = time.Time{}, time.Time{} hdr.AccessTime, hdr.ChangeTime = time.Time{}, time.Time{}
ustar := tr.blk.USTAR() ustar := tr.blk.toUSTAR()
if s := p.parseString(ustar.Prefix()); isASCII(s) { if s := p.parseString(ustar.prefix()); isASCII(s) {
prefix = s prefix = s
} }
hdr.Format = FormatUnknown // Buggy file is not GNU 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. // Make sure that the input format is GNU.
// Unfortunately, the STAR format also has a sparse header format that uses // Unfortunately, the STAR format also has a sparse header format that uses
// the same type flag but has a completely different layout. // the same type flag but has a completely different layout.
if blk.GetFormat() != FormatGNU { if blk.getFormat() != FormatGNU {
return nil, ErrHeader return nil, ErrHeader
} }
hdr.Format.mayOnlyBe(FormatGNU) hdr.Format.mayOnlyBe(FormatGNU)
var p parser var p parser
hdr.Size = p.parseNumeric(blk.GNU().RealSize()) hdr.Size = p.parseNumeric(blk.toGNU().realSize())
if p.err != nil { if p.err != nil {
return nil, p.err return nil, p.err
} }
s := blk.GNU().Sparse() s := blk.toGNU().sparse()
spd := make(sparseDatas, 0, s.MaxEntries()) spd := make(sparseDatas, 0, s.maxEntries())
for { 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. // 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) break // Don't return, need to process extended headers (even if empty)
} }
offset := p.parseNumeric(s.Entry(i).Offset()) offset := p.parseNumeric(s.entry(i).offset())
length := p.parseNumeric(s.Entry(i).Length()) length := p.parseNumeric(s.entry(i).length())
if p.err != nil { if p.err != nil {
return nil, p.err return nil, p.err
} }
spd = append(spd, sparseEntry{Offset: offset, Length: length}) 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. // There are more entries. Read an extension header and parse its entries.
if _, err := mustReadFull(tr.r, blk[:]); err != nil { if _, err := mustReadFull(tr.r, blk[:]); err != nil {
return nil, err return nil, err
} }
s = blk.Sparse() s = blk.toSparse()
continue continue
} }
return spd, nil // Done 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}) 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 return fr.nb
} }
func (fr regFileReader) PhysicalRemaining() int64 { // logicalRemaining implements fileState.physicalRemaining.
func (fr regFileReader) physicalRemaining() int64 {
return fr.nb return fr.nb
} }
@ -694,9 +696,9 @@ type sparseFileReader struct {
} }
func (sr *sparseFileReader) Read(b []byte) (n int, err error) { func (sr *sparseFileReader) Read(b []byte) (n int, err error) {
finished := int64(len(b)) >= sr.LogicalRemaining() finished := int64(len(b)) >= sr.logicalRemaining()
if finished { if finished {
b = b[:sr.LogicalRemaining()] b = b[:sr.logicalRemaining()]
} }
b0 := b 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 return n, errMissData // Less data in dense file than sparse file
case err != nil: case err != nil:
return n, err 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 return n, errUnrefData // More data in dense file than sparse file
case finished: case finished:
return n, io.EOF return n, io.EOF
@ -746,7 +748,7 @@ func (sr *sparseFileReader) WriteTo(w io.Writer) (n int64, err error) {
var writeLastByte bool var writeLastByte bool
pos0 := sr.pos pos0 := sr.pos
for sr.LogicalRemaining() > 0 && !writeLastByte && err == nil { for sr.logicalRemaining() > 0 && !writeLastByte && err == nil {
var nf int64 // Size of fragment var nf int64 // Size of fragment
holeStart, holeEnd := sr.sp[0].Offset, sr.sp[0].endOffset() holeStart, holeEnd := sr.sp[0].Offset, sr.sp[0].endOffset()
if sr.pos < holeStart { // In a data fragment 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) nf, err = io.CopyN(ws, sr.fr, nf)
} else { // In a hole fragment } else { // In a hole fragment
nf = holeEnd - sr.pos nf = holeEnd - sr.pos
if sr.PhysicalRemaining() == 0 { if sr.physicalRemaining() == 0 {
writeLastByte = true writeLastByte = true
nf-- 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 return n, errMissData // Less data in dense file than sparse file
case err != nil: case err != nil:
return n, err 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 return n, errUnrefData // More data in dense file than sparse file
default: default:
return n, nil return n, nil
} }
} }
func (sr sparseFileReader) LogicalRemaining() int64 { func (sr sparseFileReader) logicalRemaining() int64 {
return sr.sp[len(sr.sp)-1].endOffset() - sr.pos return sr.sp[len(sr.sp)-1].endOffset() - sr.pos
} }
func (sr sparseFileReader) PhysicalRemaining() int64 { func (sr sparseFileReader) physicalRemaining() int64 {
return sr.fr.PhysicalRemaining() return sr.fr.physicalRemaining()
} }
type zeroReader struct{} type zeroReader struct{}

View File

@ -1021,12 +1021,12 @@ func TestParsePAX(t *testing.T) {
func TestReadOldGNUSparseMap(t *testing.T) { func TestReadOldGNUSparseMap(t *testing.T) {
populateSparseMap := func(sa sparseArray, sps []string) []string { populateSparseMap := func(sa sparseArray, sps []string) []string {
for i := 0; len(sps) > 0 && i < sa.MaxEntries(); i++ { for i := 0; len(sps) > 0 && i < sa.maxEntries(); i++ {
copy(sa.Entry(i), sps[0]) copy(sa.entry(i), sps[0])
sps = sps[1:] sps = sps[1:]
} }
if len(sps) > 0 { if len(sps) > 0 {
copy(sa.IsExtended(), "\x80") copy(sa.isExtended(), "\x80")
} }
return sps return sps
} }
@ -1034,19 +1034,19 @@ func TestReadOldGNUSparseMap(t *testing.T) {
makeInput := func(format Format, size string, sps ...string) (out []byte) { makeInput := func(format Format, size string, sps ...string) (out []byte) {
// Write the initial GNU header. // Write the initial GNU header.
var blk block var blk block
gnu := blk.GNU() gnu := blk.toGNU()
sparse := gnu.Sparse() sparse := gnu.sparse()
copy(gnu.RealSize(), size) copy(gnu.realSize(), size)
sps = populateSparseMap(sparse, sps) sps = populateSparseMap(sparse, sps)
if format != FormatUnknown { if format != FormatUnknown {
blk.SetFormat(format) blk.setFormat(format)
} }
out = append(out, blk[:]...) out = append(out, blk[:]...)
// Write extended sparse blocks. // Write extended sparse blocks.
for len(sps) > 0 { for len(sps) > 0 {
var blk block var blk block
sps = populateSparseMap(blk.Sparse(), sps) sps = populateSparseMap(blk.toSparse(), sps)
out = append(out, blk[:]...) out = append(out, blk[:]...)
} }
return out return out
@ -1359,7 +1359,7 @@ func TestFileReader(t *testing.T) {
wantCnt int64 wantCnt int64
wantErr error wantErr error
} }
testRemaining struct { // LogicalRemaining() == wantLCnt, PhysicalRemaining() == wantPCnt testRemaining struct { // logicalRemaining() == wantLCnt, physicalRemaining() == wantPCnt
wantLCnt int64 wantLCnt int64
wantPCnt 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)) t.Errorf("test %d.%d, expected %d more operations", i, j, len(f.ops))
} }
case testRemaining: case testRemaining:
if got := fr.LogicalRemaining(); got != tf.wantLCnt { if got := fr.logicalRemaining(); got != tf.wantLCnt {
t.Errorf("test %d.%d, LogicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt) t.Errorf("test %d.%d, logicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt)
} }
if got := fr.PhysicalRemaining(); got != tf.wantPCnt { if got := fr.physicalRemaining(); got != tf.wantPCnt {
t.Errorf("test %d.%d, PhysicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt) t.Errorf("test %d.%d, physicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt)
} }
default: default:
t.Fatalf("test %d.%d, unknown test operation: %T", i, j, tf) 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 { if tw.err != nil {
return tw.err 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) return fmt.Errorf("archive/tar: missed writing %d bytes", nb)
} }
if _, tw.err = tw.w.Write(zeroBlock[:tw.pad]); tw.err != nil { 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. // Pack the main header.
var f formatter var f formatter
blk := tw.templateV7Plus(hdr, f.formatString, f.formatOctal) blk := tw.templateV7Plus(hdr, f.formatString, f.formatOctal)
f.formatString(blk.USTAR().Prefix(), namePrefix) f.formatString(blk.toUSTAR().prefix(), namePrefix)
blk.SetFormat(FormatUSTAR) blk.setFormat(FormatUSTAR)
if f.err != nil { if f.err != nil {
return f.err // Should never happen since header is validated 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 var f formatter // Ignore errors since they are expected
fmtStr := func(b []byte, s string) { f.formatString(b, toASCII(s)) } fmtStr := func(b []byte, s string) { f.formatString(b, toASCII(s)) }
blk := tw.templateV7Plus(hdr, fmtStr, f.formatOctal) blk := tw.templateV7Plus(hdr, fmtStr, f.formatOctal)
blk.SetFormat(FormatPAX) blk.setFormat(FormatPAX)
if err := tw.writeRawHeader(blk, hdr.Size, hdr.Typeflag); err != nil { if err := tw.writeRawHeader(blk, hdr.Size, hdr.Typeflag); err != nil {
return err return err
} }
@ -250,10 +250,10 @@ func (tw *Writer) writeGNUHeader(hdr *Header) error {
var spb []byte var spb []byte
blk := tw.templateV7Plus(hdr, f.formatString, f.formatNumeric) blk := tw.templateV7Plus(hdr, f.formatString, f.formatNumeric)
if !hdr.AccessTime.IsZero() { if !hdr.AccessTime.IsZero() {
f.formatNumeric(blk.GNU().AccessTime(), hdr.AccessTime.Unix()) f.formatNumeric(blk.toGNU().accessTime(), hdr.AccessTime.Unix())
} }
if !hdr.ChangeTime.IsZero() { 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. // TODO(dsnet): Re-enable this when adding sparse support.
// See https://golang.org/issue/22735 // See https://golang.org/issue/22735
@ -293,7 +293,7 @@ func (tw *Writer) writeGNUHeader(hdr *Header) error {
f.formatNumeric(blk.GNU().RealSize(), realSize) f.formatNumeric(blk.GNU().RealSize(), realSize)
} }
*/ */
blk.SetFormat(FormatGNU) blk.setFormat(FormatGNU)
if err := tw.writeRawHeader(blk, hdr.Size, hdr.Typeflag); err != nil { if err := tw.writeRawHeader(blk, hdr.Size, hdr.Typeflag); err != nil {
return err return err
} }
@ -321,28 +321,28 @@ type (
// The block returned is only valid until the next call to // The block returned is only valid until the next call to
// templateV7Plus or writeRawFile. // templateV7Plus or writeRawFile.
func (tw *Writer) templateV7Plus(hdr *Header, fmtStr stringFormatter, fmtNum numberFormatter) *block { func (tw *Writer) templateV7Plus(hdr *Header, fmtStr stringFormatter, fmtNum numberFormatter) *block {
tw.blk.Reset() tw.blk.reset()
modTime := hdr.ModTime modTime := hdr.ModTime
if modTime.IsZero() { if modTime.IsZero() {
modTime = time.Unix(0, 0) modTime = time.Unix(0, 0)
} }
v7 := tw.blk.V7() v7 := tw.blk.toV7()
v7.TypeFlag()[0] = hdr.Typeflag v7.typeFlag()[0] = hdr.Typeflag
fmtStr(v7.Name(), hdr.Name) fmtStr(v7.name(), hdr.Name)
fmtStr(v7.LinkName(), hdr.Linkname) fmtStr(v7.linkName(), hdr.Linkname)
fmtNum(v7.Mode(), hdr.Mode) fmtNum(v7.mode(), hdr.Mode)
fmtNum(v7.UID(), int64(hdr.Uid)) fmtNum(v7.uid(), int64(hdr.Uid))
fmtNum(v7.GID(), int64(hdr.Gid)) fmtNum(v7.gid(), int64(hdr.Gid))
fmtNum(v7.Size(), hdr.Size) fmtNum(v7.size(), hdr.Size)
fmtNum(v7.ModTime(), modTime.Unix()) fmtNum(v7.modTime(), modTime.Unix())
ustar := tw.blk.USTAR() ustar := tw.blk.toUSTAR()
fmtStr(ustar.UserName(), hdr.Uname) fmtStr(ustar.userName(), hdr.Uname)
fmtStr(ustar.GroupName(), hdr.Gname) fmtStr(ustar.groupName(), hdr.Gname)
fmtNum(ustar.DevMajor(), hdr.Devmajor) fmtNum(ustar.devMajor(), hdr.Devmajor)
fmtNum(ustar.DevMinor(), hdr.Devminor) fmtNum(ustar.devMinor(), hdr.Devminor)
return &tw.blk 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 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). // 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 { func (tw *Writer) writeRawFile(name, data string, flag byte, format Format) error {
tw.blk.Reset() tw.blk.reset()
// Best effort for the filename. // Best effort for the filename.
name = toASCII(name) name = toASCII(name)
@ -361,15 +361,15 @@ func (tw *Writer) writeRawFile(name, data string, flag byte, format Format) erro
name = strings.TrimRight(name, "/") name = strings.TrimRight(name, "/")
var f formatter var f formatter
v7 := tw.blk.V7() v7 := tw.blk.toV7()
v7.TypeFlag()[0] = flag v7.typeFlag()[0] = flag
f.formatString(v7.Name(), name) f.formatString(v7.name(), name)
f.formatOctal(v7.Mode(), 0) f.formatOctal(v7.mode(), 0)
f.formatOctal(v7.UID(), 0) f.formatOctal(v7.uid(), 0)
f.formatOctal(v7.GID(), 0) f.formatOctal(v7.gid(), 0)
f.formatOctal(v7.Size(), int64(len(data))) // Must be < 8GiB f.formatOctal(v7.size(), int64(len(data))) // Must be < 8GiB
f.formatOctal(v7.ModTime(), 0) f.formatOctal(v7.modTime(), 0)
tw.blk.SetFormat(format) tw.blk.setFormat(format)
if f.err != nil { if f.err != nil {
return f.err // Only occurs if size condition is violated 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) 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 return fw.nb
} }
func (fw regFileWriter) PhysicalRemaining() int64 {
// logicalRemaining implements fileState.physicalRemaining.
func (fw regFileWriter) physicalRemaining() int64 {
return fw.nb return fw.nb
} }
@ -526,9 +529,9 @@ type sparseFileWriter struct {
} }
func (sw *sparseFileWriter) Write(b []byte) (n int, err error) { func (sw *sparseFileWriter) Write(b []byte) (n int, err error) {
overwrite := int64(len(b)) > sw.LogicalRemaining() overwrite := int64(len(b)) > sw.logicalRemaining()
if overwrite { if overwrite {
b = b[:sw.LogicalRemaining()] b = b[:sw.logicalRemaining()]
} }
b0 := b 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 return n, errMissData // Not possible; implies bug in validation logic
case err != nil: case err != nil:
return n, err 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 return n, errUnrefData // Not possible; implies bug in validation logic
case overwrite: case overwrite:
return n, ErrWriteTooLong return n, ErrWriteTooLong
@ -578,12 +581,12 @@ func (sw *sparseFileWriter) ReadFrom(r io.Reader) (n int64, err error) {
var readLastByte bool var readLastByte bool
pos0 := sw.pos pos0 := sw.pos
for sw.LogicalRemaining() > 0 && !readLastByte && err == nil { for sw.logicalRemaining() > 0 && !readLastByte && err == nil {
var nf int64 // Size of fragment var nf int64 // Size of fragment
dataStart, dataEnd := sw.sp[0].Offset, sw.sp[0].endOffset() dataStart, dataEnd := sw.sp[0].Offset, sw.sp[0].endOffset()
if sw.pos < dataStart { // In a hole fragment if sw.pos < dataStart { // In a hole fragment
nf = dataStart - sw.pos nf = dataStart - sw.pos
if sw.PhysicalRemaining() == 0 { if sw.physicalRemaining() == 0 {
readLastByte = true readLastByte = true
nf-- 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 return n, errMissData // Not possible; implies bug in validation logic
case err != nil: case err != nil:
return n, err 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 return n, errUnrefData // Not possible; implies bug in validation logic
default: default:
return n, ensureEOF(rs) return n, ensureEOF(rs)
} }
} }
func (sw sparseFileWriter) LogicalRemaining() int64 { func (sw sparseFileWriter) logicalRemaining() int64 {
return sw.sp[len(sw.sp)-1].endOffset() - sw.pos return sw.sp[len(sw.sp)-1].endOffset() - sw.pos
} }
func (sw sparseFileWriter) PhysicalRemaining() int64 { func (sw sparseFileWriter) physicalRemaining() int64 {
return sw.fw.PhysicalRemaining() return sw.fw.physicalRemaining()
} }
// zeroWriter may only be written with NULs, otherwise it returns errWriteHole. // 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. // The prefix field should never appear in the GNU format.
var blk block var blk block
copy(blk[:], b.Bytes()) copy(blk[:], b.Bytes())
prefix := string(blk.USTAR().Prefix()) prefix := string(blk.toUSTAR().prefix())
if i := strings.IndexByte(prefix, 0); i >= 0 { if i := strings.IndexByte(prefix, 0); i >= 0 {
prefix = prefix[:i] // Truncate at the NUL terminator 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) t.Errorf("test %d, found prefix in GNU format: %s", i, prefix)
} }
@ -1029,7 +1029,7 @@ func TestFileWriter(t *testing.T) {
wantCnt int64 wantCnt int64
wantErr error wantErr error
} }
testRemaining struct { // LogicalRemaining() == wantLCnt, PhysicalRemaining() == wantPCnt testRemaining struct { // logicalRemaining() == wantLCnt, physicalRemaining() == wantPCnt
wantLCnt int64 wantLCnt int64
wantPCnt 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)) t.Errorf("test %d.%d, expected %d more operations", i, j, len(f.ops))
} }
case testRemaining: case testRemaining:
if got := fw.LogicalRemaining(); got != tf.wantLCnt { if got := fw.logicalRemaining(); got != tf.wantLCnt {
t.Errorf("test %d.%d, LogicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt) t.Errorf("test %d.%d, logicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt)
} }
if got := fw.PhysicalRemaining(); got != tf.wantPCnt { if got := fw.physicalRemaining(); got != tf.wantPCnt {
t.Errorf("test %d.%d, PhysicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt) t.Errorf("test %d.%d, physicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt)
} }
default: default:
t.Fatalf("test %d.%d, unknown test operation: %T", i, j, tf) 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 // 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 // header which will be _at least_ 30 bytes we can safely preallocate
// if (data size / 30) >= end.directoryRecords. // 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.File = make([]*File, 0, end.directoryRecords)
} }
z.Comment = end.comment 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)) 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

@ -888,11 +888,6 @@ func (as *asciiSet) contains(c byte) bool {
} }
func makeCutsetFunc(cutset string) func(r rune) bool { func makeCutsetFunc(cutset string) func(r rune) bool {
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
return func(r rune) bool {
return r == rune(cutset[0])
}
}
if as, isASCII := makeASCIISet(cutset); isASCII { if as, isASCII := makeASCIISet(cutset); isASCII {
return func(r rune) bool { return func(r rune) bool {
return r < utf8.RuneSelf && as.contains(byte(r)) return r < utf8.RuneSelf && as.contains(byte(r))
@ -911,21 +906,44 @@ func makeCutsetFunc(cutset string) func(r rune) bool {
// Trim returns a subslice of s by slicing off all leading and // Trim returns a subslice of s by slicing off all leading and
// trailing UTF-8-encoded code points contained in cutset. // trailing UTF-8-encoded code points contained in cutset.
func Trim(s []byte, cutset string) []byte { func Trim(s []byte, cutset string) []byte {
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0])
}
return TrimFunc(s, makeCutsetFunc(cutset)) return TrimFunc(s, makeCutsetFunc(cutset))
} }
// TrimLeft returns a subslice of s by slicing off all leading // TrimLeft returns a subslice of s by slicing off all leading
// UTF-8-encoded code points contained in cutset. // UTF-8-encoded code points contained in cutset.
func TrimLeft(s []byte, cutset string) []byte { func TrimLeft(s []byte, cutset string) []byte {
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
return trimLeftByte(s, cutset[0])
}
return TrimLeftFunc(s, makeCutsetFunc(cutset)) return TrimLeftFunc(s, makeCutsetFunc(cutset))
} }
func trimLeftByte(s []byte, c byte) []byte {
for len(s) > 0 && s[0] == c {
s = s[1:]
}
return s
}
// TrimRight returns a subslice of s by slicing off all trailing // TrimRight returns a subslice of s by slicing off all trailing
// UTF-8-encoded code points that are contained in cutset. // UTF-8-encoded code points that are contained in cutset.
func TrimRight(s []byte, cutset string) []byte { func TrimRight(s []byte, cutset string) []byte {
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
return trimRightByte(s, cutset[0])
}
return TrimRightFunc(s, makeCutsetFunc(cutset)) return TrimRightFunc(s, makeCutsetFunc(cutset))
} }
func trimRightByte(s []byte, c byte) []byte {
for len(s) > 0 && s[len(s)-1] == c {
s = s[:len(s)-1]
}
return s
}
// TrimSpace returns a subslice of s by slicing off all leading and // TrimSpace returns a subslice of s by slicing off all leading and
// trailing white space, as defined by Unicode. // trailing white space, as defined by Unicode.
func TrimSpace(s []byte) []byte { func TrimSpace(s []byte) []byte {

View File

@ -1251,7 +1251,9 @@ var trimTests = []TrimTest{
{"TrimLeft", "abba", "ab", ""}, {"TrimLeft", "abba", "ab", ""},
{"TrimRight", "abba", "ab", ""}, {"TrimRight", "abba", "ab", ""},
{"TrimLeft", "abba", "a", "bba"}, {"TrimLeft", "abba", "a", "bba"},
{"TrimLeft", "abba", "b", "abba"},
{"TrimRight", "abba", "a", "abb"}, {"TrimRight", "abba", "a", "abb"},
{"TrimRight", "abba", "b", "abba"},
{"Trim", "<tag>", "<>", "tag"}, {"Trim", "<tag>", "<>", "tag"},
{"Trim", "* listitem", " *", "listitem"}, {"Trim", "* listitem", " *", "listitem"},
{"Trim", `"quote"`, `"`, "quote"}, {"Trim", `"quote"`, `"`, "quote"},
@ -1963,6 +1965,13 @@ func BenchmarkTrimASCII(b *testing.B) {
} }
} }
func BenchmarkTrimByte(b *testing.B) {
x := []byte(" the quick brown fox ")
for i := 0; i < b.N; i++ {
Trim(x, " ")
}
}
func BenchmarkIndexPeriodic(b *testing.B) { func BenchmarkIndexPeriodic(b *testing.B) {
key := []byte{1, 1} key := []byte{1, 1}
for _, skip := range [...]int{2, 4, 8, 16, 32, 64} { for _, skip := range [...]int{2, 4, 8, 16, 32, 64} {

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 reg <= arm64.REG_R31 && reg >= arm64.REG_R0 {
if !isAmount {
return errors.New("invalid register extension")
}
switch ext { switch ext {
case "UXTB": case "UXTB":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM { if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode") return errors.New("invalid shift for the register offset addressing mode")
} }
a.Reg = arm64.REG_UXTB + Rnum a.Reg = arm64.REG_UXTB + Rnum
case "UXTH": case "UXTH":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM { if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode") return errors.New("invalid shift for the register offset addressing mode")
} }
a.Reg = arm64.REG_UXTH + Rnum a.Reg = arm64.REG_UXTH + Rnum
case "UXTW": case "UXTW":
if !isAmount {
return errors.New("invalid register extension")
}
// effective address of memory is a base register value and an offset register value. // effective address of memory is a base register value and an offset register value.
if a.Type == obj.TYPE_MEM { if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_UXTW + Rnum 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 a.Reg = arm64.REG_UXTW + Rnum
} }
case "UXTX": case "UXTX":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM { if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode") return errors.New("invalid shift for the register offset addressing mode")
} }
a.Reg = arm64.REG_UXTX + Rnum a.Reg = arm64.REG_UXTX + Rnum
case "SXTB": case "SXTB":
if !isAmount { if a.Type == obj.TYPE_MEM {
return errors.New("invalid register extension") return errors.New("invalid shift for the register offset addressing mode")
} }
a.Reg = arm64.REG_SXTB + Rnum a.Reg = arm64.REG_SXTB + Rnum
case "SXTH": case "SXTH":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM { if a.Type == obj.TYPE_MEM {
return errors.New("invalid shift for the register offset addressing mode") return errors.New("invalid shift for the register offset addressing mode")
} }
a.Reg = arm64.REG_SXTH + Rnum a.Reg = arm64.REG_SXTH + Rnum
case "SXTW": case "SXTW":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM { if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_SXTW + Rnum a.Index = arm64.REG_SXTW + Rnum
} else { } else {
a.Reg = arm64.REG_SXTW + Rnum a.Reg = arm64.REG_SXTW + Rnum
} }
case "SXTX": case "SXTX":
if !isAmount {
return errors.New("invalid register extension")
}
if a.Type == obj.TYPE_MEM { if a.Type == obj.TYPE_MEM {
a.Index = arm64.REG_SXTX + Rnum a.Index = arm64.REG_SXTX + Rnum
} else { } else {
a.Reg = arm64.REG_SXTX + Rnum a.Reg = arm64.REG_SXTX + Rnum
} }
case "LSL": case "LSL":
if !isAmount {
return errors.New("invalid register extension")
}
a.Index = arm64.REG_LSL + Rnum a.Index = arm64.REG_LSL + Rnum
default: default:
return errors.New("unsupported general register extension type: " + ext) return errors.New("unsupported general register extension type: " + ext)

View File

@ -793,6 +793,13 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
return return
} }
} }
if p.arch.Family == sys.RISCV64 {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.SetRestArgs([]obj.Addr{a[2]})
prog.To = a[3]
break
}
if p.arch.Family == sys.S390X { if p.arch.Family == sys.S390X {
if a[1].Type != obj.TYPE_REG { if a[1].Type != obj.TYPE_REG {
p.errorf("second operand must be a register in %s instruction", op) p.errorf("second operand must be a register in %s instruction", op)

View File

@ -89,7 +89,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
CMP R1<<33, R2 CMP R1<<33, R2
CMP R22.SXTX, RSP // ffe336eb CMP R22.SXTX, RSP // ffe336eb
CMP $0x22220000, RSP // CMP $572653568, RSP // 5b44a4d2ff633beb CMP $0x22220000, RSP // CMP $572653568, RSP // 5b44a4d2ff633beb
CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a452ff633b6b CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a452ff433b6b
CCMN MI, ZR, R1, $4 // e44341ba CCMN MI, ZR, R1, $4 // e44341ba
// MADD Rn,Rm,Ra,Rd // MADD Rn,Rm,Ra,Rd
MADD R1, R2, R3, R4 // 6408019b MADD R1, R2, R3, R4 // 6408019b
@ -334,6 +334,8 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
EONW $0x6006000060060, R5 // EONW $1689262177517664, R5 // 1b0c8052db00a072a5003b4a EONW $0x6006000060060, R5 // EONW $1689262177517664, R5 // 1b0c8052db00a072a5003b4a
ORNW $0x6006000060060, R5 // ORNW $1689262177517664, R5 // 1b0c8052db00a072a5003b2a ORNW $0x6006000060060, R5 // ORNW $1689262177517664, R5 // 1b0c8052db00a072a5003b2a
BICSW $0x6006000060060, R5 // BICSW $1689262177517664, R5 // 1b0c8052db00a072a5003b6a BICSW $0x6006000060060, R5 // BICSW $1689262177517664, R5 // 1b0c8052db00a072a5003b6a
AND $1, ZR // fb0340b2ff031b8a
ANDW $1, ZR // fb030032ff031b0a
// TODO: this could have better encoding // TODO: this could have better encoding
ANDW $-1, R10 // 1b0080124a011b0a ANDW $-1, R10 // 1b0080124a011b0a
AND $8, R0, RSP // 1f007d92 AND $8, R0, RSP // 1f007d92
@ -369,14 +371,15 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
MOVD $-1, R1 // 01008092 MOVD $-1, R1 // 01008092
MOVD $0x210000, R0 // MOVD $2162688, R0 // 2004a0d2 MOVD $0x210000, R0 // MOVD $2162688, R0 // 2004a0d2
MOVD $0xffffffffffffaaaa, R1 // MOVD $-21846, R1 // a1aa8a92 MOVD $0xffffffffffffaaaa, R1 // MOVD $-21846, R1 // a1aa8a92
MOVW $1, ZR MOVW $1, ZR // 3f008052
MOVW $1, R1 MOVW $1, R1
MOVD $1, ZR MOVD $1, ZR // 3f0080d2
MOVD $1, R1 MOVD $1, R1
MOVK $1, R1 MOVK $1, R1
MOVD $0x1000100010001000, RSP // MOVD $1152939097061330944, RSP // ff8304b2 MOVD $0x1000100010001000, RSP // MOVD $1152939097061330944, RSP // ff8304b2
MOVW $0x10001000, RSP // MOVW $268439552, RSP // ff830432 MOVW $0x10001000, RSP // MOVW $268439552, RSP // ff830432
ADDW $0x10001000, R1 // ADDW $268439552, R1 // fb83043221001b0b ADDW $0x10001000, R1 // ADDW $268439552, R1 // fb83043221001b0b
ADDW $0x22220000, RSP, R3 // ADDW $572653568, RSP, R3 // 5b44a452e3433b0b
// move a large constant to a Vd. // move a large constant to a Vd.
VMOVS $0x80402010, V11 // VMOVS $2151686160, V11 VMOVS $0x80402010, V11 // VMOVS $2151686160, V11
@ -385,10 +388,10 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
VMOVQ $0x8040201008040202, $0x7040201008040201, V20 // VMOVQ $-9205322385119247870, $8088500183983456769, V20 VMOVQ $0x8040201008040202, $0x7040201008040201, V20 // VMOVQ $-9205322385119247870, $8088500183983456769, V20
// mov(to/from sp) // mov(to/from sp)
MOVD $0x1002(RSP), R1 // MOVD $4098(RSP), R1 // fb074091610b0091 MOVD $0x1002(RSP), R1 // MOVD $4098(RSP), R1 // e107409121080091
MOVD $0x1708(RSP), RSP // MOVD $5896(RSP), RSP // fb0740917f231c91 MOVD $0x1708(RSP), RSP // MOVD $5896(RSP), RSP // ff074091ff231c91
MOVD $0x2001(R7), R1 // MOVD $8193(R7), R1 // fb08409161070091 MOVD $0x2001(R7), R1 // MOVD $8193(R7), R1 // e108409121040091
MOVD $0xffffff(R7), R1 // MOVD $16777215(R7), R1 // fbfc7f9161ff3f91 MOVD $0xffffff(R7), R1 // MOVD $16777215(R7), R1 // e1fc7f9121fc3f91
MOVD $-0x1(R7), R1 // MOVD $-1(R7), R1 // e10400d1 MOVD $-0x1(R7), R1 // MOVD $-1(R7), R1 // e10400d1
MOVD $-0x30(R7), R1 // MOVD $-48(R7), R1 // e1c000d1 MOVD $-0x30(R7), R1 // MOVD $-48(R7), R1 // e1c000d1
MOVD $-0x708(R7), R1 // MOVD $-1800(R7), R1 // e1201cd1 MOVD $-0x708(R7), R1 // MOVD $-1800(R7), R1 // e1201cd1

View File

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
TEXT errors(SB),$0 TEXT errors(SB),$0
AND $1, RSP // ERROR "illegal combination" AND $1, RSP // ERROR "illegal source register"
ANDS $1, R0, RSP // ERROR "illegal combination" ANDS $1, R0, RSP // ERROR "illegal combination"
ADDSW R7->32, R14, R13 // ERROR "shift amount out of range 0 to 31" 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" 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" ADD R1>>2, RSP, R3 // ERROR "illegal combination"
ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference" ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference"
CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4" 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 RET

View File

@ -10,20 +10,35 @@ start:
// 2.4: Integer Computational Instructions // 2.4: Integer Computational Instructions
ADDI $2047, X5, X6 // 1383f27f
ADDI $-2048, X5, X6 // 13830280
ADDI $2047, X5 // 9382f27f ADDI $2047, X5 // 9382f27f
ADDI $-2048, X5 // 93820280 ADDI $-2048, X5 // 93820280
ADDI $2048, X5 // 9382024093820240
ADDI $-2049, X5 // 938202c09382f2bf
ADDI $4094, X5 // 9382f27f9382f27f
ADDI $-4096, X5 // 9382028093820280
ADDI $4095, X5 // b71f00009b8fffffb382f201
ADDI $-4097, X5 // b7ffffff9b8fffffb382f201
ADDI $2047, X5, X6 // 1383f27f
ADDI $-2048, X5, X6 // 13830280
ADDI $2048, X5, X6 // 1383024013030340
ADDI $-2049, X5, X6 // 138302c01303f3bf
ADDI $4094, X5, X6 // 1383f27f1303f37f
ADDI $-4096, X5, X6 // 1383028013030380
ADDI $4095, X5, X6 // b71f00009b8fffff3383f201
ADDI $-4097, X5, X6 // b7ffffff9b8fffff3383f201
SLTI $55, X5, X7 // 93a37203 SLTI $55, X5, X7 // 93a37203
SLTIU $55, X5, X7 // 93b37203 SLTIU $55, X5, X7 // 93b37203
ANDI $1, X5, X6 // 13f31200 ANDI $1, X5, X6 // 13f31200
ANDI $1, X5 // 93f21200 ANDI $1, X5 // 93f21200
ANDI $2048, X5 // b71f00009b8f0f80b3f2f201
ORI $1, X5, X6 // 13e31200 ORI $1, X5, X6 // 13e31200
ORI $1, X5 // 93e21200 ORI $1, X5 // 93e21200
ORI $2048, X5 // b71f00009b8f0f80b3e2f201
XORI $1, X5, X6 // 13c31200 XORI $1, X5, X6 // 13c31200
XORI $1, X5 // 93c21200 XORI $1, X5 // 93c21200
XORI $2048, X5 // b71f00009b8f0f80b3c2f201
SLLI $1, X5, X6 // 13931200 SLLI $1, X5, X6 // 13931200
SLLI $1, X5 // 93921200 SLLI $1, X5 // 93921200
@ -86,20 +101,15 @@ start:
SRA $1, X5 // 93d21240 SRA $1, X5 // 93d21240
// 2.5: Control Transfer Instructions // 2.5: Control Transfer Instructions
JAL X5, 2(PC) // ef028000
// These jumps and branches get printed as a jump or branch
// to 2 because they transfer control to the second instruction
// in the function (the first instruction being an invisible
// stack pointer adjustment).
JAL X5, start // JAL X5, 2 // eff25ff0
JALR X6, (X5) // 67830200 JALR X6, (X5) // 67830200
JALR X6, 4(X5) // 67834200 JALR X6, 4(X5) // 67834200
BEQ X5, X6, start // BEQ X5, X6, 2 // e38c62ee BEQ X5, X6, 2(PC) // 63846200
BNE X5, X6, start // BNE X5, X6, 2 // e39a62ee BNE X5, X6, 2(PC) // 63946200
BLT X5, X6, start // BLT X5, X6, 2 // e3c862ee BLT X5, X6, 2(PC) // 63c46200
BLTU X5, X6, start // BLTU X5, X6, 2 // e3e662ee BLTU X5, X6, 2(PC) // 63e46200
BGE X5, X6, start // BGE X5, X6, 2 // e3d462ee BGE X5, X6, 2(PC) // 63d46200
BGEU X5, X6, start // BGEU X5, X6, 2 // e3f262ee BGEU X5, X6, 2(PC) // 63f46200
// 2.6: Load and Store Instructions // 2.6: Load and Store Instructions
LW (X5), X6 // 03a30200 LW (X5), X6 // 03a30200
@ -219,6 +229,10 @@ start:
FMVSX X5, F0 // 538002f0 FMVSX X5, F0 // 538002f0
FMVXW F0, X5 // d30200e0 FMVXW F0, X5 // d30200e0
FMVWX X5, F0 // 538002f0 FMVWX X5, F0 // 538002f0
FMADDS F1, F2, F3, F4 // 43822018
FMSUBS F1, F2, F3, F4 // 47822018
FNMSUBS F1, F2, F3, F4 // 4b822018
FNMADDS F1, F2, F3, F4 // 4f822018
// 11.8: Single-Precision Floating-Point Compare Instructions // 11.8: Single-Precision Floating-Point Compare Instructions
FEQS F0, F1, X7 // d3a300a0 FEQS F0, F1, X7 // d3a300a0
@ -259,6 +273,10 @@ start:
FSGNJXD F1, F0, F2 // 53211022 FSGNJXD F1, F0, F2 // 53211022
FMVXD F0, X5 // d30200e2 FMVXD F0, X5 // d30200e2
FMVDX X5, F0 // 538002f2 FMVDX X5, F0 // 538002f2
FMADDD F1, F2, F3, F4 // 4382201a
FMSUBD F1, F2, F3, F4 // 4782201a
FNMSUBD F1, F2, F3, F4 // 4b82201a
FNMADDD F1, F2, F3, F4 // 4f82201a
// 12.6: Double-Precision Floating-Point Classify Instruction // 12.6: Double-Precision Floating-Point Classify Instruction
FCLASSD F0, X5 // d31200e2 FCLASSD F0, X5 // d31200e2
@ -277,11 +295,17 @@ start:
// MOV pseudo-instructions // MOV pseudo-instructions
MOV X5, X6 // 13830200 MOV X5, X6 // 13830200
MOV $2047, X5 // 9b02f07f MOV $2047, X5 // 9302f07f
MOV $-2048, X5 // 9b020080 MOV $-2048, X5 // 93020080
MOV $2048, X5 // b71200009b820280
MOV $-2049, X5 // b7f2ffff9b82f27f
MOV $4096, X5 // b7120000
MOV $2147479552, X5 // b7f2ff7f
MOV $2147483647, X5 // b70200809b82f2ff
MOV $-2147483647, X5 // b70200809b821200
// Converted to load of symbol. // Converted to load of symbol (AUIPC + LD)
MOV $4294967296, X5 // 97020000 MOV $4294967296, X5 // 9702000083b20200
MOV (X5), X6 // 03b30200 MOV (X5), X6 // 03b30200
MOV 4(X5), X6 // 03b34200 MOV 4(X5), X6 // 03b34200
@ -325,10 +349,11 @@ start:
NEGW X5 // bb025040 NEGW X5 // bb025040
NEGW X5, X6 // 3b035040 NEGW X5, X6 // 3b035040
// These jumps can get printed as jumps to 2 because they go to the // This jumps to the second instruction in the function (the
// second instruction in the function (the first instruction is an // first instruction is an invisible stack pointer adjustment).
// invisible stack pointer adjustment). JMP start // JMP 2
JMP start // JMP 2 // 6ff01fc2
JMP 2(PC) // 6f008000
JMP (X5) // 67800200 JMP (X5) // 67800200
JMP 4(X5) // 67804200 JMP 4(X5) // 67804200
@ -341,16 +366,16 @@ start:
JMP asmtest(SB) // 970f0000 JMP asmtest(SB) // 970f0000
// Branch pseudo-instructions // Branch pseudo-instructions
BEQZ X5, start // BEQZ X5, 2 // e38202c0 BEQZ X5, 2(PC) // 63840200
BGEZ X5, start // BGEZ X5, 2 // e3d002c0 BGEZ X5, 2(PC) // 63d40200
BGT X5, X6, start // BGT X5, X6, 2 // e34e53be BGT X5, X6, 2(PC) // 63445300
BGTU X5, X6, start // BGTU X5, X6, 2 // e36c53be BGTU X5, X6, 2(PC) // 63645300
BGTZ X5, start // BGTZ X5, 2 // e34a50be BGTZ X5, 2(PC) // 63445000
BLE X5, X6, start // BLE X5, X6, 2 // e35853be BLE X5, X6, 2(PC) // 63545300
BLEU X5, X6, start // BLEU X5, X6, 2 // e37653be BLEU X5, X6, 2(PC) // 63745300
BLEZ X5, start // BLEZ X5, 2 // e35450be BLEZ X5, 2(PC) // 63545000
BLTZ X5, start // BLTZ X5, 2 // e3c202be BLTZ X5, 2(PC) // 63c40200
BNEZ X5, start // BNEZ X5, 2 // e39002be BNEZ X5, 2(PC) // 63940200
// Set pseudo-instructions // Set pseudo-instructions
SEQZ X15, X15 // 93b71700 SEQZ X15, X15 // 93b71700

View File

@ -3,6 +3,14 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
TEXT errors(SB),$0 TEXT errors(SB),$0
MOV $errors(SB), (X5) // ERROR "address load must target register"
MOV $8(SP), (X5) // ERROR "address load must target register"
MOVB $8(SP), X5 // ERROR "unsupported address load"
MOVH $8(SP), X5 // ERROR "unsupported address load"
MOVW $8(SP), X5 // ERROR "unsupported address load"
MOVF $8(SP), X5 // ERROR "unsupported address load"
MOV $1234, 0(SP) // ERROR "constant load must target register"
MOV $1234, 8(SP) // ERROR "constant load must target register"
MOV $0, 0(SP) // ERROR "constant load must target register" MOV $0, 0(SP) // ERROR "constant load must target register"
MOV $0, 8(SP) // ERROR "constant load must target register" MOV $0, 8(SP) // ERROR "constant load must target register"
MOV $1234, 0(SP) // ERROR "constant load must target register" MOV $1234, 0(SP) // ERROR "constant load must target register"
@ -11,4 +19,8 @@ TEXT errors(SB),$0
MOVH $1, X5 // ERROR "unsupported constant load" MOVH $1, X5 // ERROR "unsupported constant load"
MOVW $1, X5 // ERROR "unsupported constant load" MOVW $1, X5 // ERROR "unsupported constant load"
MOVF $1, X5 // ERROR "unsupported constant load" MOVF $1, X5 // ERROR "unsupported constant load"
MOVBU X5, (X6) // ERROR "unsupported unsigned store"
MOVHU X5, (X6) // ERROR "unsupported unsigned store"
MOVWU X5, (X6) // ERROR "unsupported unsigned store"
RET RET

View File

@ -23,10 +23,13 @@ import (
"internal/xcoff" "internal/xcoff"
"math" "math"
"os" "os"
"os/exec"
"strconv" "strconv"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"cmd/internal/str"
) )
var debugDefine = flag.Bool("debug-define", false, "print relevant #defines") var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
@ -382,7 +385,7 @@ func (p *Package) guessKinds(f *File) []*Name {
stderr = p.gccErrors(b.Bytes()) stderr = p.gccErrors(b.Bytes())
} }
if stderr == "" { if stderr == "" {
fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes()) fatalf("%s produced no output\non input:\n%s", gccBaseCmd[0], b.Bytes())
} }
completed := false completed := false
@ -457,7 +460,7 @@ func (p *Package) guessKinds(f *File) []*Name {
} }
if !completed { if !completed {
fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr) fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", gccBaseCmd[0], b.Bytes(), stderr)
} }
for i, n := range names { for i, n := range names {
@ -488,7 +491,7 @@ func (p *Package) guessKinds(f *File) []*Name {
// to users debugging preamble mistakes. See issue 8442. // to users debugging preamble mistakes. See issue 8442.
preambleErrors := p.gccErrors([]byte(f.Preamble)) preambleErrors := p.gccErrors([]byte(f.Preamble))
if len(preambleErrors) > 0 { if len(preambleErrors) > 0 {
error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors) error_(token.NoPos, "\n%s errors for preamble:\n%s", gccBaseCmd[0], preambleErrors)
} }
fatalf("unresolved names") fatalf("unresolved names")
@ -1545,20 +1548,37 @@ func gofmtPos(n ast.Expr, pos token.Pos) string {
return fmt.Sprintf("/*line :%d:%d*/%s", p.Line, p.Column, s) return fmt.Sprintf("/*line :%d:%d*/%s", p.Line, p.Column, s)
} }
// gccBaseCmd returns the start of the compiler command line. // checkGCCBaseCmd returns the start of the compiler command line.
// It uses $CC if set, or else $GCC, or else the compiler recorded // It uses $CC if set, or else $GCC, or else the compiler recorded
// during the initial build as defaultCC. // during the initial build as defaultCC.
// defaultCC is defined in zdefaultcc.go, written by cmd/dist. // defaultCC is defined in zdefaultcc.go, written by cmd/dist.
func (p *Package) gccBaseCmd() []string { //
// The compiler command line is split into arguments on whitespace. Quotes
// are understood, so arguments may contain whitespace.
//
// checkGCCBaseCmd confirms that the compiler exists in PATH, returning
// an error if it does not.
func checkGCCBaseCmd() ([]string, error) {
// Use $CC if set, since that's what the build uses. // Use $CC if set, since that's what the build uses.
if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 { value := os.Getenv("CC")
return ret if value == "" {
// Try $GCC if set, since that's what we used to use.
value = os.Getenv("GCC")
} }
// Try $GCC if set, since that's what we used to use. if value == "" {
if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 { value = defaultCC(goos, goarch)
return ret
} }
return strings.Fields(defaultCC(goos, goarch)) args, err := str.SplitQuotedFields(value)
if err != nil {
return nil, err
}
if len(args) == 0 {
return nil, errors.New("CC not set and no default found")
}
if _, err := exec.LookPath(args[0]); err != nil {
return nil, fmt.Errorf("C compiler %q not found: %v", args[0], err)
}
return args[:len(args):len(args)], nil
} }
// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
@ -1604,7 +1624,7 @@ func gccTmp() string {
// gccCmd returns the gcc command line to use for compiling // gccCmd returns the gcc command line to use for compiling
// the input. // the input.
func (p *Package) gccCmd() []string { func (p *Package) gccCmd() []string {
c := append(p.gccBaseCmd(), c := append(gccBaseCmd,
"-w", // no warnings "-w", // no warnings
"-Wno-error", // warnings are not errors "-Wno-error", // warnings are not errors
"-o"+gccTmp(), // write object to tmp "-o"+gccTmp(), // write object to tmp
@ -2005,7 +2025,7 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
// #defines that gcc encountered while processing the input // #defines that gcc encountered while processing the input
// and its included files. // and its included files.
func (p *Package) gccDefines(stdin []byte) string { func (p *Package) gccDefines(stdin []byte) string {
base := append(p.gccBaseCmd(), "-E", "-dM", "-xc") base := append(gccBaseCmd, "-E", "-dM", "-xc")
base = append(base, p.gccMachine()...) base = append(base, p.gccMachine()...)
stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
return stdout return stdout

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Cgo; see gmp.go for an overview. // Cgo; see doc.go for an overview.
// TODO(rsc): // TODO(rsc):
// Emit correct line number annotations. // Emit correct line number annotations.
@ -21,7 +21,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"reflect" "reflect"
"runtime" "runtime"
@ -248,6 +247,7 @@ var importSyscall = flag.Bool("import_syscall", true, "import syscall in generat
var trimpath = flag.String("trimpath", "", "applies supplied rewrites or trims prefixes to recorded source file paths") var trimpath = flag.String("trimpath", "", "applies supplied rewrites or trims prefixes to recorded source file paths")
var goarch, goos, gomips, gomips64 string var goarch, goos, gomips, gomips64 string
var gccBaseCmd []string
func main() { func main() {
objabi.AddVersionFlag() // -V objabi.AddVersionFlag() // -V
@ -305,10 +305,10 @@ func main() {
p := newPackage(args[:i]) p := newPackage(args[:i])
// We need a C compiler to be available. Check this. // We need a C compiler to be available. Check this.
gccName := p.gccBaseCmd()[0] var err error
_, err := exec.LookPath(gccName) gccBaseCmd, err = checkGCCBaseCmd()
if err != nil { if err != nil {
fatalf("C compiler %q not found: %v", gccName, err) fatalf("%v", err)
os.Exit(2) os.Exit(2)
} }

View File

@ -59,9 +59,9 @@ func (p *Package) writeDefs() {
// Write C main file for using gcc to resolve imports. // Write C main file for using gcc to resolve imports.
fmt.Fprintf(fm, "int main() { return 0; }\n") fmt.Fprintf(fm, "int main() { return 0; }\n")
if *importRuntimeCgo { 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, "__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") fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
} else { } else {
// If we're not importing runtime/cgo, we *are* runtime/cgo, // 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, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n")
fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__);\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_allocate(void *a __attribute__((unused)), int c __attribute__((unused))) { }\n")
fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n") fmt.Fprintf(fm, "void _cgo_panic(void *a __attribute__((unused)), int c __attribute__((unused))) { }\n")
fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n") fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n")
// Write second Go output: definitions of _C_xxx. // Write second Go output: definitions of _C_xxx.

View File

@ -233,7 +233,7 @@ stack frame is laid out in the following sequence:
r1.x uintptr r1.x uintptr
r1.y [2]uintptr r1.y [2]uintptr
a1Spill uint8 a1Spill uint8
a2Spill uint8 a3Spill uint8
_ [6]uint8 // alignment padding _ [6]uint8 // alignment padding
In the stack frame, only the `a2` field is initialized on entry; the In the stack frame, only the `a2` field is initialized on entry; the
@ -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. 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 ## Future directions
### Spill path improvements ### Spill path improvements

View File

@ -144,7 +144,7 @@ func (pa *ABIParamAssignment) RegisterTypesAndOffsets() ([]*types.Type, []int64)
} }
func appendParamTypes(rts []*types.Type, t *types.Type) []*types.Type { func appendParamTypes(rts []*types.Type, t *types.Type) []*types.Type {
w := t.Width w := t.Size()
if w == 0 { if w == 0 {
return rts return rts
} }
@ -193,12 +193,12 @@ func appendParamTypes(rts []*types.Type, t *types.Type) []*types.Type {
// to input offsets, and returns the longer slice and the next unused offset. // to input offsets, and returns the longer slice and the next unused offset.
func appendParamOffsets(offsets []int64, at int64, t *types.Type) ([]int64, int64) { func appendParamOffsets(offsets []int64, at int64, t *types.Type) ([]int64, int64) {
at = align(at, t) at = align(at, t)
w := t.Width w := t.Size()
if w == 0 { if w == 0 {
return offsets, at return offsets, at
} }
if t.IsScalar() || t.IsPtrShaped() { if t.IsScalar() || t.IsPtrShaped() {
if t.IsComplex() || int(t.Width) > types.RegSize { // complex and *int64 on 32-bit if t.IsComplex() || int(t.Size()) > types.RegSize { // complex and *int64 on 32-bit
s := w / 2 s := w / 2
return append(offsets, at, at+s), at + w return append(offsets, at, at+s), at + w
} else { } else {
@ -214,7 +214,7 @@ func appendParamOffsets(offsets []int64, at int64, t *types.Type) ([]int64, int6
case types.TSTRUCT: case types.TSTRUCT:
for i, f := range t.FieldSlice() { for i, f := range t.FieldSlice() {
offsets, at = appendParamOffsets(offsets, at, f.Type) offsets, at = appendParamOffsets(offsets, at, f.Type)
if f.Type.Width == 0 && i == t.NumFields()-1 { if f.Type.Size() == 0 && i == t.NumFields()-1 {
at++ // last field has zero width at++ // last field has zero width
} }
} }
@ -446,35 +446,20 @@ func (config *ABIConfig) ABIAnalyze(t *types.Type, setNname bool) *ABIParamResul
return result return result
} }
// parameterUpdateMu protects the Offset field of function/method parameters (a subset of structure Fields)
var parameterUpdateMu sync.Mutex
// FieldOffsetOf returns a concurrency-safe version of f.Offset
func FieldOffsetOf(f *types.Field) int64 {
parameterUpdateMu.Lock()
defer parameterUpdateMu.Unlock()
return f.Offset
}
func (config *ABIConfig) updateOffset(result *ABIParamResultInfo, f *types.Field, a ABIParamAssignment, isReturn, setNname bool) { func (config *ABIConfig) updateOffset(result *ABIParamResultInfo, f *types.Field, a ABIParamAssignment, isReturn, setNname bool) {
// Everything except return values in registers has either a frame home (if not in a register) or a frame spill location. // Everything except return values in registers has either a frame home (if not in a register) or a frame spill location.
if !isReturn || len(a.Registers) == 0 { if !isReturn || len(a.Registers) == 0 {
// The type frame offset DOES NOT show effects of minimum frame size. // The type frame offset DOES NOT show effects of minimum frame size.
// Getting this wrong breaks stackmaps, see liveness/plive.go:WriteFuncMap and typebits/typebits.go:Set // Getting this wrong breaks stackmaps, see liveness/plive.go:WriteFuncMap and typebits/typebits.go:Set
parameterUpdateMu.Lock()
defer parameterUpdateMu.Unlock()
off := a.FrameOffset(result) off := a.FrameOffset(result)
fOffset := f.Offset fOffset := f.Offset
if fOffset == types.BOGUS_FUNARG_OFFSET { if fOffset == types.BOGUS_FUNARG_OFFSET {
// Set the Offset the first time. After that, we may recompute it, but it should never change. if setNname && f.Nname != nil {
f.Offset = off
if f.Nname != nil {
// always set it in this case.
f.Nname.(*ir.Name).SetFrameOffset(off) f.Nname.(*ir.Name).SetFrameOffset(off)
f.Nname.(*ir.Name).SetIsOutputParamInRegisters(false) f.Nname.(*ir.Name).SetIsOutputParamInRegisters(false)
} }
} else if fOffset != off { } else {
base.Fatalf("offset for %s at %s changed from %d to %d", f.Sym.Name, base.FmtPos(f.Pos), fOffset, off) base.Fatalf("field offset for %s at %s has been set to %d", f.Sym.Name, base.FmtPos(f.Pos), fOffset)
} }
} else { } else {
if setNname && f.Nname != nil { if setNname && f.Nname != nil {
@ -546,7 +531,7 @@ type assignState struct {
// align returns a rounded up to t's alignment // align returns a rounded up to t's alignment
func align(a int64, t *types.Type) int64 { func align(a int64, t *types.Type) int64 {
return alignTo(a, int(t.Align)) return alignTo(a, int(uint8(t.Alignment())))
} }
// alignTo returns a rounded up to t, where t must be 0 or a power of 2. // alignTo returns a rounded up to t, where t must be 0 or a power of 2.
@ -561,7 +546,7 @@ func alignTo(a int64, t int) int64 {
// specified type. // specified type.
func (state *assignState) stackSlot(t *types.Type) int64 { func (state *assignState) stackSlot(t *types.Type) int64 {
rv := align(state.stackOffset, t) rv := align(state.stackOffset, t)
state.stackOffset = rv + t.Width state.stackOffset = rv + t.Size()
return rv return rv
} }
@ -569,7 +554,7 @@ func (state *assignState) stackSlot(t *types.Type) int64 {
// that we've just determined to be register-assignable. The number of registers // that we've just determined to be register-assignable. The number of registers
// needed is assumed to be stored in state.pUsed. // needed is assumed to be stored in state.pUsed.
func (state *assignState) allocateRegs(regs []RegIndex, t *types.Type) []RegIndex { func (state *assignState) allocateRegs(regs []RegIndex, t *types.Type) []RegIndex {
if t.Width == 0 { if t.Size() == 0 {
return regs return regs
} }
ri := state.rUsed.intRegs ri := state.rUsed.intRegs
@ -662,7 +647,7 @@ func (state *assignState) floatUsed() int {
// can register allocate, FALSE otherwise (and updates state // can register allocate, FALSE otherwise (and updates state
// accordingly). // accordingly).
func (state *assignState) regassignIntegral(t *types.Type) bool { func (state *assignState) regassignIntegral(t *types.Type) bool {
regsNeeded := int(types.Rnd(t.Width, int64(types.PtrSize)) / int64(types.PtrSize)) regsNeeded := int(types.Rnd(t.Size(), int64(types.PtrSize)) / int64(types.PtrSize))
if t.IsComplex() { if t.IsComplex() {
regsNeeded = 2 regsNeeded = 2
} }
@ -737,14 +722,17 @@ func setup() {
types.NewField(nxp, fname("len"), ui), types.NewField(nxp, fname("len"), ui),
types.NewField(nxp, fname("cap"), ui), types.NewField(nxp, fname("cap"), ui),
}) })
types.CalcStructSize(synthSlice)
synthString = types.NewStruct(types.NoPkg, []*types.Field{ synthString = types.NewStruct(types.NoPkg, []*types.Field{
types.NewField(nxp, fname("data"), unsp), types.NewField(nxp, fname("data"), unsp),
types.NewField(nxp, fname("len"), ui), types.NewField(nxp, fname("len"), ui),
}) })
types.CalcStructSize(synthString)
synthIface = types.NewStruct(types.NoPkg, []*types.Field{ synthIface = types.NewStruct(types.NoPkg, []*types.Field{
types.NewField(nxp, fname("f1"), unsp), types.NewField(nxp, fname("f1"), unsp),
types.NewField(nxp, fname("f2"), unsp), types.NewField(nxp, fname("f2"), unsp),
}) })
types.CalcStructSize(synthIface)
}) })
} }
@ -779,10 +767,10 @@ func (state *assignState) regassign(pt *types.Type) bool {
// ABIParamResultInfo held in 'state'. // ABIParamResultInfo held in 'state'.
func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, isReturn bool) ABIParamAssignment { func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, isReturn bool) ABIParamAssignment {
state.pUsed = RegAmounts{} state.pUsed = RegAmounts{}
if pt.Width == types.BADWIDTH { if pt.Size() == types.BADWIDTH {
base.Fatalf("should never happen") base.Fatalf("should never happen")
panic("unreachable") panic("unreachable")
} else if pt.Width == 0 { } else if pt.Size() == 0 {
return state.stackAllocate(pt, n) return state.stackAllocate(pt, n)
} else if state.regassign(pt) { } else if state.regassign(pt) {
return state.regAllocate(pt, n, isReturn) return state.regAllocate(pt, n, isReturn)

View File

@ -18,11 +18,10 @@ func Init(arch *ssagen.ArchInfo) {
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop
arch.SSAMarkMoves = ssaMarkMoves arch.SSAMarkMoves = ssaMarkMoves
arch.SSAGenValue = ssaGenValue arch.SSAGenValue = ssaGenValue
arch.SSAGenBlock = ssaGenBlock arch.SSAGenBlock = ssaGenBlock
arch.LoadRegResults = loadRegResults arch.LoadRegResult = loadRegResult
arch.SpillArgReg = spillArgReg 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 { func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, state *uint32) *obj.Prog {
const ( const (
r13 = 1 << iota // if R13 is already zeroed. 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 { 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) 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) { } 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++ { 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) 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)) 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)) { } 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 // Save DI to r12. With the amd64 Go register abi, DI can contain
// an incoming parameter, whereas R12 is always scratch. // 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) p = pp.Append(p, x86.AMOVQ, obj.TYPE_REG, x86.REG_DI, 0, obj.TYPE_REG, x86.REG_R12, 0)

View File

@ -822,8 +822,13 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Type = obj.TYPE_MEM p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg() p.To.Reg = v.Args[0].Reg()
ssagen.AddAux2(&p.To, v, sc.Off64()) ssagen.AddAux2(&p.To, v, sc.Off64())
case ssa.OpAMD64MOVOstorezero: case ssa.OpAMD64MOVOstoreconst:
if !buildcfg.Experiment.RegabiG || s.ABI != obj.ABIInternal { sc := v.AuxValAndOff()
if sc.Val() != 0 {
v.Fatalf("MOVO for non zero constants not implemented: %s", v.LongString())
}
if s.ABI != obj.ABIInternal {
// zero X15 manually // zero X15 manually
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
} }
@ -832,7 +837,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.From.Reg = x86.REG_X15 p.From.Reg = x86.REG_X15
p.To.Type = obj.TYPE_MEM p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg() p.To.Reg = v.Args[0].Reg()
ssagen.AddAux(&p.To, v) ssagen.AddAux2(&p.To, v, sc.Off64())
case ssa.OpAMD64MOVQstoreconstidx1, ssa.OpAMD64MOVQstoreconstidx8, ssa.OpAMD64MOVLstoreconstidx1, ssa.OpAMD64MOVLstoreconstidx4, ssa.OpAMD64MOVWstoreconstidx1, ssa.OpAMD64MOVWstoreconstidx2, ssa.OpAMD64MOVBstoreconstidx1, case ssa.OpAMD64MOVQstoreconstidx1, ssa.OpAMD64MOVQstoreconstidx8, ssa.OpAMD64MOVLstoreconstidx1, ssa.OpAMD64MOVLstoreconstidx4, ssa.OpAMD64MOVWstoreconstidx1, ssa.OpAMD64MOVWstoreconstidx2, ssa.OpAMD64MOVBstoreconstidx1,
ssa.OpAMD64ADDLconstmodifyidx1, ssa.OpAMD64ADDLconstmodifyidx4, ssa.OpAMD64ADDLconstmodifyidx8, ssa.OpAMD64ADDQconstmodifyidx1, ssa.OpAMD64ADDQconstmodifyidx8, ssa.OpAMD64ADDLconstmodifyidx1, ssa.OpAMD64ADDLconstmodifyidx4, ssa.OpAMD64ADDLconstmodifyidx8, ssa.OpAMD64ADDQconstmodifyidx1, ssa.OpAMD64ADDQconstmodifyidx8,
ssa.OpAMD64ANDLconstmodifyidx1, ssa.OpAMD64ANDLconstmodifyidx4, ssa.OpAMD64ANDLconstmodifyidx8, ssa.OpAMD64ANDQconstmodifyidx1, ssa.OpAMD64ANDQconstmodifyidx8, ssa.OpAMD64ANDLconstmodifyidx1, ssa.OpAMD64ANDLconstmodifyidx4, ssa.OpAMD64ANDLconstmodifyidx8, ssa.OpAMD64ANDQconstmodifyidx1, ssa.OpAMD64ANDQconstmodifyidx8,
@ -914,7 +920,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg() p.To.Reg = v.Reg()
case ssa.OpAMD64DUFFZERO: case ssa.OpAMD64DUFFZERO:
if !buildcfg.Experiment.RegabiG || s.ABI != obj.ABIInternal { if s.ABI != obj.ABIInternal {
// zero X15 manually // zero X15 manually
opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15)
} }
@ -997,22 +1003,26 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
// Closure pointer is DX. // Closure pointer is DX.
ssagen.CheckLoweredGetClosurePtr(v) ssagen.CheckLoweredGetClosurePtr(v)
case ssa.OpAMD64LoweredGetG: case ssa.OpAMD64LoweredGetG:
if buildcfg.Experiment.RegabiG && s.ABI == obj.ABIInternal { if s.ABI == obj.ABIInternal {
v.Fatalf("LoweredGetG should not appear in ABIInternal") v.Fatalf("LoweredGetG should not appear in ABIInternal")
} }
r := v.Reg() r := v.Reg()
getgFromTLS(s, r) getgFromTLS(s, r)
case ssa.OpAMD64CALLstatic: 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 // 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 // set G register from TLS
getgFromTLS(s, x86.REG_R14) getgFromTLS(s, x86.REG_R14)
} }
s.Call(v) 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 // 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 // set G register from TLS
getgFromTLS(s, x86.REG_R14) getgFromTLS(s, x86.REG_R14)
} }
@ -1221,6 +1231,10 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Type = obj.TYPE_MEM p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg() p.To.Reg = v.Args[0].Reg()
ssagen.AddAux(&p.To, v) ssagen.AddAux(&p.To, v)
case ssa.OpAMD64PrefetchT0, ssa.OpAMD64PrefetchNTA:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_MEM
p.From.Reg = v.Args[0].Reg()
case ssa.OpClobber: case ssa.OpClobber:
p := s.Prog(x86.AMOVL) p := s.Prog(x86.AMOVL)
p.From.Type = obj.TYPE_CONST p.From.Type = obj.TYPE_CONST
@ -1304,9 +1318,11 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
case ssa.BlockRet: case ssa.BlockRet:
s.Prog(obj.ARET) s.Prog(obj.ARET)
case ssa.BlockRetJmp: 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 // 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 // set G register from TLS
getgFromTLS(s, x86.REG_R14) getgFromTLS(s, x86.REG_R14)
} }
@ -1348,20 +1364,15 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
} }
} }
func loadRegResults(s *ssagen.State, f *ssa.Func) { func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog {
for _, o := range f.OwnAux.ABIInfo().OutParams() { p := s.Prog(loadByType(t))
n := o.Name.(*ir.Name) p.From.Type = obj.TYPE_MEM
rts, offs := o.RegisterTypesAndOffsets() p.From.Name = obj.NAME_AUTO
for i := range o.Registers { p.From.Sym = n.Linksym()
p := s.Prog(loadByType(rts[i])) p.From.Offset = n.FrameOffset() + off
p.From.Type = obj.TYPE_MEM p.To.Type = obj.TYPE_REG
p.From.Name = obj.NAME_AUTO p.To.Reg = reg
p.From.Sym = n.Linksym() return p
p.From.Offset = n.FrameOffset() + offs[i]
p.To.Type = obj.TYPE_REG
p.To.Reg = ssa.ObjRegForAbiReg(o.Registers[i], f.Config)
}
}
} }
func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog { 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.SoftFloat = buildcfg.GOARM == 5
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop
arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {}
arch.SSAGenValue = ssaGenValue arch.SSAGenValue = ssaGenValue

View File

@ -18,9 +18,10 @@ func Init(arch *ssagen.ArchInfo) {
arch.PadFrame = padframe arch.PadFrame = padframe
arch.ZeroRange = zerorange arch.ZeroRange = zerorange
arch.Ginsnop = ginsnop arch.Ginsnop = ginsnop
arch.Ginsnopdefer = ginsnop
arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {}
arch.SSAGenValue = ssaGenValue arch.SSAGenValue = ssaGenValue
arch.SSAGenBlock = ssaGenBlock arch.SSAGenBlock = ssaGenBlock
arch.LoadRegResult = loadRegResult
arch.SpillArgReg = spillArgReg
} }

View File

@ -10,6 +10,7 @@ import (
"cmd/compile/internal/base" "cmd/compile/internal/base"
"cmd/compile/internal/ir" "cmd/compile/internal/ir"
"cmd/compile/internal/logopt" "cmd/compile/internal/logopt"
"cmd/compile/internal/objw"
"cmd/compile/internal/ssa" "cmd/compile/internal/ssa"
"cmd/compile/internal/ssagen" "cmd/compile/internal/ssagen"
"cmd/compile/internal/types" "cmd/compile/internal/types"
@ -161,6 +162,18 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[0].Reg() p.From.Reg = v.Args[0].Reg()
ssagen.AddrAuto(&p.To, v) 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, case ssa.OpARM64ADD,
ssa.OpARM64SUB, ssa.OpARM64SUB,
ssa.OpARM64AND, ssa.OpARM64AND,
@ -1082,6 +1095,12 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.From.Reg = condBits[v.Op] p.From.Reg = condBits[v.Op]
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg() p.To.Reg = v.Reg()
case ssa.OpARM64PRFM:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_MEM
p.From.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_CONST
p.To.Offset = v.AuxInt
case ssa.OpARM64LoweredGetClosurePtr: case ssa.OpARM64LoweredGetClosurePtr:
// Closure pointer is R26 (arm64.REGCTXT). // Closure pointer is R26 (arm64.REGCTXT).
ssagen.CheckLoweredGetClosurePtr(v) ssagen.CheckLoweredGetClosurePtr(v)
@ -1101,8 +1120,34 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
v.Fatalf("FlagConstant op should never make it to codegen %v", v.LongString()) v.Fatalf("FlagConstant op should never make it to codegen %v", v.LongString())
case ssa.OpARM64InvertFlags: case ssa.OpARM64InvertFlags:
v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString()) v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
case ssa.OpClobber, ssa.OpClobberReg: case ssa.OpClobber:
// TODO: implement for clobberdead experiment. Nop is ok for now. // 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: default:
v.Fatalf("genValue not implemented: %s", v.LongString()) v.Fatalf("genValue not implemented: %s", v.LongString())
} }
@ -1266,3 +1311,22 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
b.Fatalf("branch not implemented: %s", b.LongString()) 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"` Panic int `help:"show all compiler panics"`
Slice int `help:"print information about slice compilation"` Slice int `help:"print information about slice compilation"`
SoftFloat int `help:"force compiler to emit soft-float code"` 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"` TypeAssert int `help:"print information about type assertion inlining"`
TypecheckInl int `help:"eager typechecking of inline function bodies"` 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"` WB int `help:"print information about write barriers"`
ABIWrap int `help:"print information about ABI wrapper generation"` 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. // ParseFlags parses the command-line flags into Flag.
func ParseFlags() { func ParseFlags() {
Flag.G = 3
Flag.I = addImportDir Flag.I = addImportDir
Flag.LowerC = 1 Flag.LowerC = 1
@ -159,7 +160,11 @@ func ParseFlags() {
Flag.LinkShared = &Ctxt.Flag_linkshared Flag.LinkShared = &Ctxt.Flag_linkshared
Flag.Shared = &Ctxt.Flag_shared Flag.Shared = &Ctxt.Flag_shared
Flag.WB = true Flag.WB = true
Debug.InlFuncsWithClosures = 1 Debug.InlFuncsWithClosures = 1
if buildcfg.Experiment.Unified {
Debug.Unified = 1
}
Debug.Checkptr = -1 // so we can tell whether it is set explicitly 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 //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
// +build darwin dragonfly freebsd linux netbsd openbsd // +build darwin dragonfly freebsd linux netbsd openbsd
package typecheck package base
import ( import (
"os" "os"
@ -19,7 +19,7 @@ import (
// mapFile returns length bytes from the file starting at the // mapFile returns length bytes from the file starting at the
// specified offset as a string. // 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 // POSIX mmap: "The implementation may require that off is a
// multiple of the page size." // multiple of the page size."
x := offset & int64(os.Getpagesize()-1) x := offset & int64(os.Getpagesize()-1)

View File

@ -5,14 +5,14 @@
//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd //go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
package typecheck package base
import ( import (
"io" "io"
"os" "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) buf := make([]byte, length)
_, err := io.ReadFull(io.NewSectionReader(f, offset, length), buf) _, err := io.ReadFull(io.NewSectionReader(f, offset, length), buf)
if err != nil { if err != nil {

View File

@ -233,6 +233,27 @@ func FatalfAt(pos src.XPos, format string, args ...interface{}) {
ErrorExit() 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. // hcrash crashes the compiler when -h is set, to find out where a message is generated.
func hcrash() { func hcrash() {
if Flag.LowerH != 0 { 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)} 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) { if ir.IsConst(n.Cond, constant.Bool) {
var body ir.Nodes var body ir.Nodes
if ir.BoolVal(n.Cond) { if ir.BoolVal(n.Cond) {
ir.VisitList(n.Else, markHiddenClosureDead)
n.Else = ir.Nodes{} n.Else = ir.Nodes{}
body = n.Body body = n.Body
} else { } else {
ir.VisitList(n.Body, markHiddenClosureDead)
n.Body = ir.Nodes{} n.Body = ir.Nodes{}
body = n.Else body = n.Else
} }
@ -150,3 +153,13 @@ func expr(n ir.Node) ir.Node {
} }
return n 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), Type: base.Ctxt.Lookup(typename),
DeclFile: declpos.RelFilename(), DeclFile: declpos.RelFilename(),
DeclLine: declpos.RelLine(), DeclLine: declpos.RelLine(),
DeclCol: declpos.Col(), DeclCol: declpos.RelCol(),
InlIndex: int32(inlIndex), InlIndex: int32(inlIndex),
ChildIndex: -1, ChildIndex: -1,
}) })
@ -371,7 +371,7 @@ func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
Type: base.Ctxt.Lookup(typename), Type: base.Ctxt.Lookup(typename),
DeclFile: declpos.RelFilename(), DeclFile: declpos.RelFilename(),
DeclLine: declpos.RelLine(), DeclLine: declpos.RelLine(),
DeclCol: declpos.Col(), DeclCol: declpos.RelCol(),
InlIndex: int32(inlIndex), InlIndex: int32(inlIndex),
ChildIndex: -1, 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]]), StackOffset: ssagen.StackOffset(debug.Slots[debug.VarSlots[varID][0]]),
DeclFile: declpos.RelFilename(), DeclFile: declpos.RelFilename(),
DeclLine: declpos.RelLine(), DeclLine: declpos.RelLine(),
DeclCol: declpos.Col(), DeclCol: declpos.RelCol(),
InlIndex: int32(inlIndex), InlIndex: int32(inlIndex),
ChildIndex: -1, ChildIndex: -1,
} }

View File

@ -244,7 +244,7 @@ func makePreinlineDclMap(fnsym *obj.LSym) map[varPos]int {
DeclName: unversion(n.Sym().Name), DeclName: unversion(n.Sym().Name),
DeclFile: pos.RelFilename(), DeclFile: pos.RelFilename(),
DeclLine: pos.RelLine(), DeclLine: pos.RelLine(),
DeclCol: pos.Col(), DeclCol: pos.RelCol(),
} }
if _, found := m[vp]; found { 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. // 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().IsUntyped() && !n.Type().HasPointers() {
k.dst = &e.blankLoc
}
switch n.Op() {
default:
base.Fatalf("unexpected expr: %s %v", n.Op().String(), n)
case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OGETCALLERPC, ir.OGETCALLERSP, ir.OTYPE, ir.OMETHEXPR, ir.OLINKSYMOFFSET:
// nop
case ir.ONAME:
n := n.(*ir.Name)
if n.Class == ir.PFUNC || n.Class == ir.PEXTERN {
return
}
e.flow(k, e.oldLoc(n))
case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT:
n := n.(*ir.UnaryExpr)
e.discard(n.X)
case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
n := n.(*ir.BinaryExpr)
e.discard(n.X)
e.discard(n.Y)
case ir.OANDAND, ir.OOROR:
n := n.(*ir.LogicalExpr)
e.discard(n.X)
e.discard(n.Y)
case ir.OADDR:
n := n.(*ir.AddrExpr)
e.expr(k.addr(n, "address-of"), n.X) // "address-of"
case ir.ODEREF:
n := n.(*ir.StarExpr)
e.expr(k.deref(n, "indirection"), n.X) // "indirection"
case ir.ODOT, ir.ODOTMETH, ir.ODOTINTER:
n := n.(*ir.SelectorExpr)
e.expr(k.note(n, "dot"), n.X)
case ir.ODOTPTR:
n := n.(*ir.SelectorExpr)
e.expr(k.deref(n, "dot of pointer"), n.X) // "dot of pointer"
case ir.ODOTTYPE, ir.ODOTTYPE2:
n := n.(*ir.TypeAssertExpr)
e.expr(k.dotType(n.Type(), n, "dot"), n.X)
case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2:
n := n.(*ir.DynamicTypeAssertExpr)
e.expr(k.dotType(n.Type(), n, "dot"), n.X)
// n.T doesn't need to be tracked; it always points to read-only storage.
case ir.OINDEX:
n := n.(*ir.IndexExpr)
if n.X.Type().IsArray() {
e.expr(k.note(n, "fixed-array-index-of"), n.X)
} else {
// TODO(mdempsky): Fix why reason text.
e.expr(k.deref(n, "dot of pointer"), n.X)
}
e.discard(n.Index)
case ir.OINDEXMAP:
n := n.(*ir.IndexExpr)
e.discard(n.X)
e.discard(n.Index)
case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR:
n := n.(*ir.SliceExpr)
e.expr(k.note(n, "slice"), n.X)
e.discard(n.Low)
e.discard(n.High)
e.discard(n.Max)
case ir.OCONV, ir.OCONVNOP:
n := n.(*ir.ConvExpr)
if ir.ShouldCheckPtr(e.curfn, 2) && n.Type().IsUnsafePtr() && n.X.Type().IsPtr() {
// When -d=checkptr=2 is enabled, treat
// conversions to unsafe.Pointer as an
// escaping operation. This allows better
// runtime instrumentation, since we can more
// easily detect object boundaries on the heap
// than the stack.
e.assignHeap(n.X, "conversion to unsafe.Pointer", n)
} else if n.Type().IsUnsafePtr() && n.X.Type().IsUintptr() {
e.unsafeValue(k, n.X)
} else {
e.expr(k, n.X)
}
case ir.OCONVIFACE, ir.OCONVIDATA:
n := n.(*ir.ConvExpr)
if !n.X.Type().IsInterface() && !types.IsDirectIface(n.X.Type()) {
k = e.spill(k, n)
}
e.expr(k.note(n, "interface-converted"), n.X)
case ir.OEFACE:
n := n.(*ir.BinaryExpr)
// Note: n.X is not needed because it can never point to memory that might escape.
e.expr(k, n.Y)
case ir.OIDATA, ir.OSPTR:
n := n.(*ir.UnaryExpr)
e.expr(k, n.X)
case ir.OSLICE2ARRPTR:
// the slice pointer flows directly to the result
n := n.(*ir.ConvExpr)
e.expr(k, n.X)
case ir.ORECV:
n := n.(*ir.UnaryExpr)
e.discard(n.X)
case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OINLCALL, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.ORECOVER, ir.OUNSAFEADD, ir.OUNSAFESLICE:
e.call([]hole{k}, n)
case ir.ONEW:
n := n.(*ir.UnaryExpr)
e.spill(k, n)
case ir.OMAKESLICE:
n := n.(*ir.MakeExpr)
e.spill(k, n)
e.discard(n.Len)
e.discard(n.Cap)
case ir.OMAKECHAN:
n := n.(*ir.MakeExpr)
e.discard(n.Len)
case ir.OMAKEMAP:
n := n.(*ir.MakeExpr)
e.spill(k, n)
e.discard(n.Len)
case ir.OMETHVALUE:
// Flow the receiver argument to both the closure and
// to the receiver parameter.
n := n.(*ir.SelectorExpr)
closureK := e.spill(k, n)
m := n.Selection
// We don't know how the method value will be called
// later, so conservatively assume the result
// parameters all flow to the heap.
//
// TODO(mdempsky): Change ks into a callback, so that
// we don't have to create this slice?
var ks []hole
for i := m.Type.NumResults(); i > 0; i-- {
ks = append(ks, e.heapHole())
}
name, _ := m.Nname.(*ir.Name)
paramK := e.tagHole(ks, name, m.Type.Recv())
e.expr(e.teeHole(paramK, closureK), n.X)
case ir.OPTRLIT:
n := n.(*ir.AddrExpr)
e.expr(e.spill(k, n), n.X)
case ir.OARRAYLIT:
n := n.(*ir.CompLitExpr)
for _, elt := range n.List {
if elt.Op() == ir.OKEY {
elt = elt.(*ir.KeyExpr).Value
}
e.expr(k.note(n, "array literal element"), elt)
}
case ir.OSLICELIT:
n := n.(*ir.CompLitExpr)
k = e.spill(k, n)
for _, elt := range n.List {
if elt.Op() == ir.OKEY {
elt = elt.(*ir.KeyExpr).Value
}
e.expr(k.note(n, "slice-literal-element"), elt)
}
case ir.OSTRUCTLIT:
n := n.(*ir.CompLitExpr)
for _, elt := range n.List {
e.expr(k.note(n, "struct literal element"), elt.(*ir.StructKeyExpr).Value)
}
case ir.OMAPLIT:
n := n.(*ir.CompLitExpr)
e.spill(k, n)
// Map keys and values are always stored in the heap.
for _, elt := range n.List {
elt := elt.(*ir.KeyExpr)
e.assignHeap(elt.Key, "map literal key", n)
e.assignHeap(elt.Value, "map literal value", n)
}
case ir.OCLOSURE:
n := n.(*ir.ClosureExpr)
k = e.spill(k, n)
e.closures = append(e.closures, closure{k, n})
if fn := n.Func; fn.IsHiddenClosure() {
for _, cv := range fn.ClosureVars {
if loc := e.oldLoc(cv); !loc.captured {
loc.captured = true
// Ignore reassignments to the variable in straightline code
// preceding the first capture by a closure.
if loc.loopDepth == e.loopDepth {
loc.reassigned = false
}
}
}
for _, n := range fn.Dcl {
// Add locations for local variables of the
// closure, if needed, in case we're not including
// the closure func in the batch for escape
// analysis (happens for escape analysis called
// from reflectdata.methodWrapper)
if n.Op() == ir.ONAME && n.Opt == nil {
e.with(fn).newLoc(n, false)
}
}
e.walkFunc(fn)
}
case ir.ORUNES2STR, ir.OBYTES2STR, ir.OSTR2RUNES, ir.OSTR2BYTES, ir.ORUNESTR:
n := n.(*ir.ConvExpr)
e.spill(k, n)
e.discard(n.X)
case ir.OADDSTR:
n := n.(*ir.AddStringExpr)
e.spill(k, n)
// Arguments of OADDSTR never escape;
// runtime.concatstrings makes sure of that.
e.discards(n.List)
case ir.ODYNAMICTYPE:
// Nothing to do - argument is a *runtime._type (+ maybe a *runtime.itab) pointing to static data section
}
}
// unsafeValue evaluates a uintptr-typed arithmetic expression looking
// for conversions from an unsafe.Pointer.
func (e *escape) unsafeValue(k hole, n ir.Node) {
if n.Type().Kind() != types.TUINTPTR {
base.Fatalf("unexpected type %v for %v", n.Type(), n)
}
if k.addrtaken {
base.Fatalf("unexpected addrtaken")
}
e.stmts(n.Init())
switch n.Op() {
case ir.OCONV, ir.OCONVNOP:
n := n.(*ir.ConvExpr)
if n.X.Type().IsUnsafePtr() {
e.expr(k, n.X)
} else {
e.discard(n.X)
}
case ir.ODOTPTR:
n := n.(*ir.SelectorExpr)
if ir.IsReflectHeaderDataField(n) {
e.expr(k.deref(n, "reflect.Header.Data"), n.X)
} else {
e.discard(n.X)
}
case ir.OPLUS, ir.ONEG, ir.OBITNOT:
n := n.(*ir.UnaryExpr)
e.unsafeValue(k, n.X)
case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OAND, ir.OANDNOT:
n := n.(*ir.BinaryExpr)
e.unsafeValue(k, n.X)
e.unsafeValue(k, n.Y)
case ir.OLSH, ir.ORSH:
n := n.(*ir.BinaryExpr)
e.unsafeValue(k, n.X)
// RHS need not be uintptr-typed (#32959) and can't meaningfully
// flow pointers anyway.
e.discard(n.Y)
default:
e.exprSkipInit(e.discardHole(), n)
}
}
// discard evaluates an expression n for side-effects, but discards
// its value.
func (e *escape) discard(n ir.Node) {
e.expr(e.discardHole(), n)
}
func (e *escape) discards(l ir.Nodes) {
for _, n := range l {
e.discard(n)
}
}
// spill allocates a new location associated with expression n, flows
// its address to k, and returns a hole that flows values to it. It's
// intended for use with most expressions that allocate storage.
func (e *escape) spill(k hole, n ir.Node) hole {
loc := e.newLoc(n, true)
e.flow(k.addr(n, "spill"), loc)
return loc.asHole()
}

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().Size() > ir.MaxStackVarSize {
return "too large for stack"
}
if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Size() > ir.MaxImplicitStackVarSize {
return "too large for stack"
}
if n.Op() == ir.OCLOSURE && typecheck.ClosureType(n.(*ir.ClosureExpr)).Size() > ir.MaxImplicitStackVarSize {
return "too large for stack"
}
if n.Op() == ir.OMETHVALUE && typecheck.MethodValueType(n.(*ir.SelectorExpr)).Size() > ir.MaxImplicitStackVarSize {
return "too large for stack"
}
if n.Op() == ir.OMAKESLICE {
n := n.(*ir.MakeExpr)
r := n.Cap
if r == nil {
r = n.Len
}
if !ir.IsSmallIntConst(r) {
return "non-constant size"
}
if t := n.Type(); t.Elem().Size() != 0 && ir.Int64Val(r) > ir.MaxImplicitStackVarSize/t.Elem().Size() {
return "too large for stack"
}
}
return ""
}

View File

@ -5,46 +5,16 @@
package gc package gc
import ( import (
"fmt"
"go/constant"
"cmd/compile/internal/base" "cmd/compile/internal/base"
"cmd/compile/internal/inline"
"cmd/compile/internal/ir" "cmd/compile/internal/ir"
"cmd/compile/internal/typecheck" "cmd/compile/internal/typecheck"
"cmd/compile/internal/types" "cmd/compile/internal/types"
"cmd/internal/bio" "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() { func dumpasmhdr() {
b, err := bio.Create(base.Flag.AsmHdr) b, err := bio.Create(base.Flag.AsmHdr)
if err != nil { if err != nil {
@ -68,7 +38,7 @@ func dumpasmhdr() {
if !t.IsStruct() || t.StructType().Map != nil || t.IsFuncArgStruct() { if !t.IsStruct() || t.StructType().Map != nil || t.IsFuncArgStruct() {
break break
} }
fmt.Fprintf(b, "#define %s__size %d\n", n.Sym().Name, int(t.Width)) fmt.Fprintf(b, "#define %s__size %d\n", n.Sym().Name, int(t.Size()))
for _, f := range t.Fields().Slice() { for _, f := range t.Fields().Slice() {
if !f.Sym.IsBlank() { if !f.Sym.IsBlank() {
fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym().Name, f.Sym.Name, int(f.Offset)) fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym().Name, f.Sym.Name, int(f.Offset))
@ -79,83 +49,3 @@ func dumpasmhdr() {
b.Close() 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" "log"
"os" "os"
"runtime" "runtime"
"sort"
) )
func hidePanic() { func hidePanic() {
@ -83,7 +84,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
types.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin types.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin
// pseudo-package, accessed by import "unsafe" // pseudo-package, accessed by import "unsafe"
ir.Pkgs.Unsafe = types.NewPkg("unsafe", "unsafe") types.UnsafePkg = types.NewPkg("unsafe", "unsafe")
// Pseudo-package that contains the compiler's builtin // Pseudo-package that contains the compiler's builtin
// declarations for package runtime. These are declared in a // declarations for package runtime. These are declared in a
@ -159,9 +160,6 @@ func Main(archInit func(*ssagen.ArchInfo)) {
dwarf.EnableLogging(base.Debug.DwarfInl != 0) dwarf.EnableLogging(base.Debug.DwarfInl != 0)
} }
if base.Debug.SoftFloat != 0 { if base.Debug.SoftFloat != 0 {
if buildcfg.Experiment.RegabiArgs {
log.Fatalf("softfloat mode with GOEXPERIMENT=regabiargs not implemented ")
}
ssagen.Arch.SoftFloat = true ssagen.Arch.SoftFloat = true
} }
@ -181,21 +179,40 @@ func Main(archInit func(*ssagen.ArchInfo)) {
typecheck.Target = new(ir.Package) 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? typecheck.NeedRuntimeType = reflectdata.NeedRuntimeType // TODO(rsc): TypeSym for lock?
base.AutogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0) base.AutogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
typecheck.InitUniverse() typecheck.InitUniverse()
typecheck.InitRuntime()
// Parse and typecheck input. // Parse and typecheck input.
noder.LoadPackage(flag.Args()) noder.LoadPackage(flag.Args())
dwarfgen.RecordPackageName() dwarfgen.RecordPackageName()
// Build init task. // Prepare for backend processing. This must happen before pkginit,
if initTask := pkginit.Task(); initTask != nil { // because it generates itabs for initializing global variables.
typecheck.Export(initTask) ssagen.InitConfig()
// Create "init" function for package-scope variable initialization
// statements, if any.
//
// Note: This needs to happen early, before any optimizations. The
// Go spec defines a precise order than initialization should be
// carried out in, and even mundane optimizations like dead code
// removal can skew the results (e.g., #43444).
pkginit.MakeInit()
// Stability quirk: sort top-level declarations, so we're not
// sensitive to the order that functions are added. In particular,
// the order that noder+typecheck add function closures is very
// subtle, and not important to reproduce.
if base.Debug.UnifiedQuirks != 0 {
s := typecheck.Target.Decls
sort.SliceStable(s, func(i, j int) bool {
return s[i].Pos().Before(s[j].Pos())
})
} }
// Eliminate some obviously dead code. // Eliminate some obviously dead code.
@ -228,6 +245,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
if base.Flag.LowerL != 0 { if base.Flag.LowerL != 0 {
inline.InlinePackage() inline.InlinePackage()
} }
noder.MakeWrappers(typecheck.Target) // must happen after inlining
// Devirtualize. // Devirtualize.
for _, n := range typecheck.Target.Decls { for _, n := range typecheck.Target.Decls {
@ -237,6 +255,11 @@ func Main(archInit func(*ssagen.ArchInfo)) {
} }
ir.CurFunc = nil ir.CurFunc = nil
// Build init task, if needed.
if initTask := pkginit.Task(); initTask != nil {
typecheck.Export(initTask)
}
// Generate ABI wrappers. Must happen before escape analysis // Generate ABI wrappers. Must happen before escape analysis
// and doesn't benefit from dead-coding or inlining. // and doesn't benefit from dead-coding or inlining.
symABIs.GenABIWrappers() symABIs.GenABIWrappers()
@ -252,6 +275,11 @@ func Main(archInit func(*ssagen.ArchInfo)) {
base.Timer.Start("fe", "escapes") base.Timer.Start("fe", "escapes")
escape.Funcs(typecheck.Target.Decls) 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 // Collect information for go:nowritebarrierrec
// checking. This must happen before transforming closures during Walk // checking. This must happen before transforming closures during Walk
// We'll do the final check after write barriers are // We'll do the final check after write barriers are
@ -260,17 +288,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
ssagen.EnableNoWriteBarrierRecCheck() 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 ir.CurFunc = nil
reflectdata.CompileITabs()
// Compile top level functions. // Compile top level functions.
// Don't use range--walk can add functions to Target.Decls. // Don't use range--walk can add functions to Target.Decls.
@ -278,6 +296,10 @@ func Main(archInit func(*ssagen.ArchInfo)) {
fcount := int64(0) fcount := int64(0)
for i := 0; i < len(typecheck.Target.Decls); i++ { for i := 0; i < len(typecheck.Target.Decls); i++ {
if fn, ok := typecheck.Target.Decls[i].(*ir.Func); ok { if fn, ok := typecheck.Target.Decls[i].(*ir.Func); ok {
// Don't try compiling dead hidden closure.
if fn.IsDeadcodeClosure() {
continue
}
enqueueFunc(fn) enqueueFunc(fn)
fcount++ fcount++
} }

View File

@ -7,6 +7,7 @@ package gc
import ( import (
"cmd/compile/internal/base" "cmd/compile/internal/base"
"cmd/compile/internal/ir" "cmd/compile/internal/ir"
"cmd/compile/internal/noder"
"cmd/compile/internal/objw" "cmd/compile/internal/objw"
"cmd/compile/internal/reflectdata" "cmd/compile/internal/reflectdata"
"cmd/compile/internal/staticdata" "cmd/compile/internal/staticdata"
@ -103,7 +104,7 @@ func finishArchiveEntry(bout *bio.Writer, start int64, name string) {
func dumpCompilerObj(bout *bio.Writer) { func dumpCompilerObj(bout *bio.Writer) {
printObjHeader(bout) printObjHeader(bout)
dumpexport(bout) noder.WriteExports(bout)
} }
func dumpdata() { func dumpdata() {
@ -116,7 +117,7 @@ func dumpdata() {
addsignats(typecheck.Target.Externs) addsignats(typecheck.Target.Externs)
reflectdata.WriteRuntimeTypes() reflectdata.WriteRuntimeTypes()
reflectdata.WriteTabs() reflectdata.WriteTabs()
numPTabs, numITabs := reflectdata.CountTabs() numPTabs := reflectdata.CountPTabs()
reflectdata.WriteImportStrings() reflectdata.WriteImportStrings()
reflectdata.WriteBasicTypes() reflectdata.WriteBasicTypes()
dumpembeds() dumpembeds()
@ -148,7 +149,7 @@ func dumpdata() {
if reflectdata.ZeroSize > 0 { if reflectdata.ZeroSize > 0 {
zero := base.PkgLinksym("go.map", "zero", obj.ABI0) zero := base.PkgLinksym("go.map", "zero", obj.ABI0)
objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA) objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA)
zero.Set(obj.AttrContentAddressable, true) zero.Set(obj.AttrStatic, true)
} }
staticdata.WriteFuncSyms() staticdata.WriteFuncSyms()
@ -157,13 +158,10 @@ func dumpdata() {
if numExports != len(typecheck.Target.Exports) { if numExports != len(typecheck.Target.Exports) {
base.Fatalf("Target.Exports changed after compile functions loop") base.Fatalf("Target.Exports changed after compile functions loop")
} }
newNumPTabs, newNumITabs := reflectdata.CountTabs() newNumPTabs := reflectdata.CountPTabs()
if newNumPTabs != numPTabs { if newNumPTabs != numPTabs {
base.Fatalf("ptabs changed after compile functions loop") base.Fatalf("ptabs changed after compile functions loop")
} }
if newNumITabs != numITabs {
base.Fatalf("itabs changed after compile functions loop")
}
} }
func dumpLinkerObj(bout *bio.Writer) { func dumpLinkerObj(bout *bio.Writer) {
@ -276,7 +274,7 @@ func ggloblnod(nam *ir.Name) {
if nam.Type() != nil && !nam.Type().HasPointers() { if nam.Type() != nil && !nam.Type().HasPointers() {
flags |= obj.NOPTR flags |= obj.NOPTR
} }
base.Ctxt.Globl(s, nam.Type().Width, flags) base.Ctxt.Globl(s, nam.Type().Size(), flags)
if nam.LibfuzzerExtraCounter() { if nam.LibfuzzerExtraCounter() {
s.Type = objabi.SLIBFUZZER_EXTRA_COUNTER s.Type = objabi.SLIBFUZZER_EXTRA_COUNTER
} }

View File

@ -1,4 +1,3 @@
// UNREVIEWED
// Copyright 2011 The Go Authors. All rights reserved. // Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.

View File

@ -1,4 +1,3 @@
// UNREVIEWED
// Copyright 2011 The Go Authors. All rights reserved. // Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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' // binary export format starts with a 'c', 'd', or 'v'
// (from "version"). Select appropriate importer. // (from "version"). Select appropriate importer.
if len(data) > 0 && data[0] == 'i' { if len(data) > 0 && data[0] == 'i' {
_, pkg, err = iImportData(packages, data[1:], id) pkg, err = ImportData(packages, string(data[1:]), id)
} else { } else {
err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path) 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. // Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -10,7 +9,6 @@ import (
"cmd/compile/internal/types2" "cmd/compile/internal/types2"
"fmt" "fmt"
"internal/testenv" "internal/testenv"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -64,7 +62,7 @@ const maxTime = 30 * time.Second
func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir) dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
list, err := ioutil.ReadDir(dirname) list, err := os.ReadDir(dirname)
if err != nil { if err != nil {
t.Fatalf("testDir(%s): %s", dirname, err) 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 { func mktmpdir(t *testing.T) string {
tmpdir, err := ioutil.TempDir("", "gcimporter_test") tmpdir, err := os.MkdirTemp("", "gcimporter_test")
if err != nil { if err != nil {
t.Fatal("mktmpdir:", err) t.Fatal("mktmpdir:", err)
} }
@ -142,7 +140,7 @@ func TestVersionHandling(t *testing.T) {
} }
const dir = "./testdata/versions" const dir = "./testdata/versions"
list, err := ioutil.ReadDir(dir) list, err := os.ReadDir(dir)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -195,7 +193,7 @@ func TestVersionHandling(t *testing.T) {
// create file with corrupted export data // create file with corrupted export data
// 1) read file // 1) read file
data, err := ioutil.ReadFile(filepath.Join(dir, name)) data, err := os.ReadFile(filepath.Join(dir, name))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -212,7 +210,7 @@ func TestVersionHandling(t *testing.T) {
// 4) write the file // 4) write the file
pkgpath += "_corrupted" pkgpath += "_corrupted"
filename := filepath.Join(corruptdir, pkgpath) + ".a" 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 // test that importing the corrupted file results in an error
_, err = Import(make(map[string]*types2.Package), pkgpath, corruptdir, nil) _, 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.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
{"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"}, {"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"},
{"go/ast.Node", "type Node interface{End() go/token.Pos; Pos() go/token.Pos}"}, {"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) { func TestImportedTypes(t *testing.T) {
@ -457,17 +454,17 @@ func TestIssue13898(t *testing.T) {
t.Fatal("go/types not found") t.Fatal("go/types not found")
} }
// look for go/types2.Object type // look for go/types.Object type
obj := lookupObj(t, goTypesPkg.Scope(), "Object") obj := lookupObj(t, goTypesPkg.Scope(), "Object")
typ, ok := obj.Type().(*types2.Named) typ, ok := obj.Type().(*types2.Named)
if !ok { 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") m, index, indirect := types2.LookupFieldOrMethod(typ, false, nil, "Pkg")
if m == nil { 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 // the method must belong to go/types

View File

@ -1,4 +1,3 @@
// UNREVIEWED
// Copyright 2018 The Go Authors. All rights reserved. // Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -9,7 +8,6 @@
package importer package importer
import ( import (
"bytes"
"cmd/compile/internal/syntax" "cmd/compile/internal/syntax"
"cmd/compile/internal/types2" "cmd/compile/internal/types2"
"encoding/binary" "encoding/binary"
@ -19,10 +17,11 @@ import (
"io" "io"
"math/big" "math/big"
"sort" "sort"
"strings"
) )
type intReader struct { type intReader struct {
*bytes.Reader *strings.Reader
path string path string
} }
@ -42,6 +41,21 @@ func (r *intReader) uint64() uint64 {
return i 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 const predeclReserved = 32
type itag uint64 type itag uint64
@ -57,6 +71,9 @@ const (
signatureType signatureType
structType structType
interfaceType interfaceType
typeParamType
instType
unionType
) )
const io_SeekCurrent = 1 // io.SeekCurrent (not defined in Go 1.4) 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. // 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 // If the export data version is not recognized or the format is otherwise
// compromised, an error is returned. // compromised, an error is returned.
func iImportData(imports map[string]*types2.Package, data []byte, path string) (_ int, pkg *types2.Package, err error) { func ImportData(imports map[string]*types2.Package, data, path string) (pkg *types2.Package, err error) {
const currentVersion = 1 const currentVersion = iexportVersionCurrent
version := int64(-1) version := int64(-1)
defer func() { defer func() {
if e := recover(); e != nil { 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()) version = int64(r.uint64())
switch version { switch version {
case currentVersion, 0: case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11:
default: 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()) 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) r.Seek(sLen+dLen, io_SeekCurrent)
p := iimporter{ p := iimporter{
ipath: path, exportVersion: version,
version: int(version), ipath: path,
version: int(version),
stringData: stringData, stringData: stringData,
stringCache: make(map[uint64]string), pkgCache: make(map[uint64]*types2.Package),
pkgCache: make(map[uint64]*types2.Package), posBaseCache: make(map[uint64]*syntax.PosBase),
declData: declData, declData: declData,
pkgIndex: make(map[*types2.Package]map[string]uint64), pkgIndex: make(map[*types2.Package]map[string]uint64),
typCache: make(map[uint64]types2.Type), 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 { for i, pt := range predeclared {
@ -117,17 +142,22 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) (
pkgPathOff := r.uint64() pkgPathOff := r.uint64()
pkgPath := p.stringAt(pkgPathOff) pkgPath := p.stringAt(pkgPathOff)
pkgName := p.stringAt(r.uint64()) pkgName := p.stringAt(r.uint64())
_ = r.uint64() // package height; unused by go/types pkgHeight := int(r.uint64())
if pkgPath == "" { if pkgPath == "" {
pkgPath = path pkgPath = path
} }
pkg := imports[pkgPath] pkg := imports[pkgPath]
if pkg == nil { if pkg == nil {
pkg = types2.NewPackage(pkgPath, pkgName) pkg = types2.NewPackageHeight(pkgPath, pkgName, pkgHeight)
imports[pkgPath] = pkg imports[pkgPath] = pkg
} else if pkg.Name() != pkgName { } else {
errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) 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 p.pkgCache[pkgPathOff] = pkg
@ -153,10 +183,6 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) (
p.doDecl(localpkg, name) p.doDecl(localpkg, name)
} }
for _, typ := range p.interfaceList {
typ.Complete()
}
// record all referenced packages as imports // record all referenced packages as imports
list := append(([]*types2.Package)(nil), pkgList[1:]...) list := append(([]*types2.Package)(nil), pkgList[1:]...)
sort.Sort(byPath(list)) 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 // package was imported completely and without errors
localpkg.MarkComplete() localpkg.MarkComplete()
consumed, _ := r.Seek(0, io_SeekCurrent) return localpkg, nil
return int(consumed), localpkg, nil
} }
type iimporter struct { type iimporter struct {
ipath string exportVersion int64
version int ipath string
version int
stringData []byte stringData string
stringCache map[uint64]string pkgCache map[uint64]*types2.Package
pkgCache map[uint64]*types2.Package posBaseCache map[uint64]*syntax.PosBase
declData []byte declData string
pkgIndex map[*types2.Package]map[string]uint64 pkgIndex map[*types2.Package]map[string]uint64
typCache map[uint64]types2.Type typCache map[uint64]types2.Type
tparamIndex map[ident]types2.Type
interfaceList []*types2.Interface 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. // Reader.Reset is not available in Go 1.4.
// Use bytes.NewReader for now. // Use bytes.NewReader for now.
// r.declReader.Reset(p.declData[off:]) // r.declReader.Reset(p.declData[off:])
r.declReader = *bytes.NewReader(p.declData[off:]) r.declReader = *strings.NewReader(p.declData[off:])
r.obj(name) r.obj(name)
} }
func (p *iimporter) stringAt(off uint64) string { func (p *iimporter) stringAt(off uint64) string {
if s, ok := p.stringCache[off]; ok { var x [binary.MaxVarintLen64]byte
return s n := copy(x[:], p.stringData[off:])
}
slen, n := binary.Uvarint(p.stringData[off:]) slen, n := binary.Uvarint(x[:n])
if n <= 0 { if n <= 0 {
errorf("varint failed") errorf("varint failed")
} }
spos := off + uint64(n) spos := off + uint64(n)
s := string(p.stringData[spos : spos+slen]) return p.stringData[spos : spos+slen]
p.stringCache[off] = s
return s
} }
func (p *iimporter) pkgAt(off uint64) *types2.Package { func (p *iimporter) pkgAt(off uint64) *types2.Package {
@ -228,6 +252,16 @@ func (p *iimporter) pkgAt(off uint64) *types2.Package {
return nil 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 { func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type {
if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) { if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) {
return 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. // Reader.Reset is not available in Go 1.4.
// Use bytes.NewReader for now. // Use bytes.NewReader for now.
// r.declReader.Reset(p.declData[off-predeclReserved:]) // 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) t := r.doType(base)
if base == nil || !isInterface(t) { if base == nil || !isInterface(t) {
@ -251,12 +285,12 @@ func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type {
} }
type importReader struct { type importReader struct {
p *iimporter p *iimporter
declReader bytes.Reader declReader strings.Reader
currPkg *types2.Package currPkg *types2.Package
prevFile string prevPosBase *syntax.PosBase
prevLine int64 prevLine int64
prevColumn int64 prevColumn int64
} }
func (r *importReader) obj(name string) { func (r *importReader) obj(name string) {
@ -274,16 +308,26 @@ func (r *importReader) obj(name string) {
r.declare(types2.NewConst(pos, r.currPkg, name, typ, val)) 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 := r.signature(nil)
sig.SetTParams(tparams)
r.declare(types2.NewFunc(pos, r.currPkg, name, sig)) 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 // Types can be recursive. We need to setup a stub
// declaration before recursing. // declaration before recursing.
obj := types2.NewTypeName(pos, r.currPkg, name, nil) obj := types2.NewTypeName(pos, r.currPkg, name, nil)
named := types2.NewNamed(obj, nil, nil) named := types2.NewNamed(obj, nil, nil)
named.SetTParams(tparams)
r.declare(obj) r.declare(obj)
underlying := r.p.typAt(r.uint64(), named).Underlying() underlying := r.p.typAt(r.uint64(), named).Underlying()
@ -296,10 +340,43 @@ func (r *importReader) obj(name string) {
recv := r.param() recv := r.param()
msig := r.signature(recv) 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)) 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': case 'V':
typ := r.typ() typ := r.typ()
@ -439,12 +516,11 @@ func (r *importReader) pos() syntax.Pos {
r.posv0() 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{} return syntax.Pos{}
} }
// TODO(gri) fix this
// return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn)) return syntax.MakePos(r.prevPosBase, uint(r.prevLine), uint(r.prevColumn))
return syntax.Pos{}
} }
func (r *importReader) posv0() { func (r *importReader) posv0() {
@ -454,7 +530,7 @@ func (r *importReader) posv0() {
} else if l := r.int64(); l == -1 { } else if l := r.int64(); l == -1 {
r.prevLine += deltaNewFile r.prevLine += deltaNewFile
} else { } else {
r.prevFile = r.string() r.prevPosBase = r.posBase()
r.prevLine = l r.prevLine = l
} }
} }
@ -466,7 +542,7 @@ func (r *importReader) posv1() {
delta = r.int64() delta = r.int64()
r.prevLine += delta >> 1 r.prevLine += delta >> 1
if delta&1 != 0 { if delta&1 != 0 {
r.prevFile = r.string() r.prevPosBase = r.posBase()
} }
} }
} }
@ -480,8 +556,9 @@ func isInterface(t types2.Type) bool {
return ok return ok
} }
func (r *importReader) pkg() *types2.Package { return r.p.pkgAt(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) 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 { func (r *importReader) doType(base *types2.Named) types2.Type {
switch k := r.kind(); k { switch k := r.kind(); k {
@ -554,6 +631,49 @@ func (r *importReader) doType(base *types2.Named) types2.Type {
typ := types2.NewInterfaceType(methods, embeddeds) typ := types2.NewInterfaceType(methods, embeddeds)
r.p.interfaceList = append(r.p.interfaceList, typ) r.p.interfaceList = append(r.p.interfaceList, typ)
return 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 +688,19 @@ func (r *importReader) signature(recv *types2.Var) *types2.Signature {
return types2.NewSignature(recv, params, results, variadic) 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 { func (r *importReader) paramList() *types2.Tuple {
xs := make([]*types2.Var, r.uint64()) xs := make([]*types2.Var, r.uint64())
for i := range xs { for i := range xs {
@ -610,3 +743,33 @@ func (r *importReader) byte() byte {
} }
return x 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. // Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // 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 // used internally by gc; never used by this package or in .a files
anyType{}, anyType{},
// comparable
types2.Universe.Lookup("comparable").Type(),
} }
type anyType struct{} type anyType struct{}

View File

@ -179,6 +179,8 @@ func CanInline(fn *ir.Func) {
Cost: inlineMaxBudget - visitor.budget, Cost: inlineMaxBudget - visitor.budget,
Dcl: pruneUnusedAutos(n.Defn.(*ir.Func).Dcl, &visitor), Dcl: pruneUnusedAutos(n.Defn.(*ir.Func).Dcl, &visitor),
Body: inlcopylist(fn.Body), Body: inlcopylist(fn.Body),
CanDelayResults: canDelayResults(fn),
} }
if base.Flag.LowerM > 1 { 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 // canDelayResults reports whether inlined calls to fn can delay
// all called functions are marked too. // declaring the result parameter until the "return" statement.
func Inline_Flood(n *ir.Name, exportsym func(*ir.Name)) { func canDelayResults(fn *ir.Func) bool {
if n == nil { // We can delay declaring+initializing result parameters if:
return // (1) there's exactly one "return" statement in the inlined function;
} // (2) it's not an empty return statement (#44355); and
if n.Op() != ir.ONAME || n.Class != ir.PFUNC { // (3) the result parameters aren't named.
base.Fatalf("Inline_Flood: unexpected %v, %v, %v", n, n.Op(), n.Class)
}
fn := n.Func
if fn == nil {
base.Fatalf("Inline_Flood: missing Func on %v", n)
}
if fn.Inl == nil {
return
}
if fn.ExportInline() { nreturns := 0
return ir.VisitList(fn.Body, func(n ir.Node) {
} if n, ok := n.(*ir.ReturnStmt); ok {
fn.SetExportInline(true) nreturns++
if len(n.Results) == 0 {
typecheck.ImportedBody(fn) nreturns++ // empty return statement (case 2)
var doFlood func(n ir.Node)
doFlood = func(n ir.Node) {
switch n.Op() {
case ir.OMETHEXPR, ir.ODOTMETH:
Inline_Flood(ir.MethodExprName(n), exportsym)
case ir.ONAME:
n := n.(*ir.Name)
switch n.Class {
case ir.PFUNC:
Inline_Flood(n, exportsym)
exportsym(n)
case ir.PEXTERN:
exportsym(n)
} }
}
})
case ir.OCALLPART: if nreturns != 1 {
// Okay, because we don't yet inline indirect return false // not exactly one return statement (case 1)
// calls to method values. }
case ir.OCLOSURE:
// VisitList doesn't visit closure bodies, so force a // temporaries for return values.
// recursive call to VisitList on the body of the closure. for _, param := range fn.Type().Results().FieldSlice() {
ir.VisitList(n.(*ir.ClosureExpr).Func.Body, doFlood) 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 return true
// reexport. We want to include even non-called functions,
// because after inlining they might be callable.
ir.VisitList(ir.Nodes(fn.Inl.Body), doFlood)
} }
// hairyVisitor visits a function body to determine its inlining // 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) { if ir.IsIntrinsicCall(n) {
// Treat like any other node. // Treat like any other node.
@ -309,28 +300,8 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
// Call cost for non-leaf inlining. // Call cost for non-leaf inlining.
v.budget -= v.extraCallCost v.budget -= v.extraCallCost
// Call is okay if inlinable and we have the budget for the body.
case ir.OCALLMETH: case ir.OCALLMETH:
n := n.(*ir.CallExpr) base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
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
// Things that are too hairy, irrespective of the budget // Things that are too hairy, irrespective of the budget
case ir.OCALL, ir.OCALLINTER: case ir.OCALL, ir.OCALLINTER:
@ -427,10 +398,14 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
n := n.(*ir.IfStmt) n := n.(*ir.IfStmt)
if ir.IsConst(n.Cond, constant.Bool) { if ir.IsConst(n.Cond, constant.Bool) {
// This if and the condition cost nothing. // This if and the condition cost nothing.
// TODO(rsc): It seems strange that we visit the dead branch. if doList(n.Init(), v.do) {
return doList(n.Init(), v.do) || return true
doList(n.Body, v.do) || }
doList(n.Else, v.do) if ir.BoolVal(n.Cond) {
return doList(n.Body, v.do)
} else {
return doList(n.Else, v.do)
}
} }
case ir.ONAME: case ir.ONAME:
@ -445,7 +420,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
// and don't charge for the OBLOCK itself. The ++ undoes the -- below. // and don't charge for the OBLOCK itself. The ++ undoes the -- below.
v.budget++ v.budget++
case ir.OCALLPART, ir.OSLICELIT: case ir.OMETHVALUE, ir.OSLICELIT:
v.budget-- // Hack for toolstash -cmp. v.budget-- // Hack for toolstash -cmp.
case ir.OMETHEXPR: case ir.OMETHEXPR:
@ -499,9 +474,6 @@ func inlcopy(n ir.Node) ir.Node {
// x.Func.Body for iexport and local inlining. // x.Func.Body for iexport and local inlining.
oldfn := x.Func oldfn := x.Func
newfn := ir.NewFunc(oldfn.Pos()) newfn := ir.NewFunc(oldfn.Pos())
if oldfn.ClosureCalled() {
newfn.SetClosureCalled(true)
}
m.(*ir.ClosureExpr).Func = newfn m.(*ir.ClosureExpr).Func = newfn
newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), oldfn.Nname.Sym()) newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), oldfn.Nname.Sym())
// XXX OK to share fn.Type() ?? // XXX OK to share fn.Type() ??
@ -544,37 +516,6 @@ func InlineCalls(fn *ir.Func) {
ir.CurFunc = savefn 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 // inlnode recurses over the tree to find inlineable calls, which will
// be turned into OINLCALLs by mkinlcall. When the recursion comes // be turned into OINLCALLs by mkinlcall. When the recursion comes
// back up will examine left, right, list, rlist, ninit, ntest, nincr, // back up will examine left, right, list, rlist, ninit, ntest, nincr,
@ -597,7 +538,9 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
case ir.ODEFER, ir.OGO: case ir.ODEFER, ir.OGO:
n := n.(*ir.GoDeferStmt) n := n.(*ir.GoDeferStmt)
switch call := n.Call; call.Op() { 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 := call.(*ir.CallExpr)
call.NoInline = true call.NoInline = true
} }
@ -607,11 +550,18 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
case ir.OCLOSURE: case ir.OCLOSURE:
return n return n
case ir.OCALLMETH: case ir.OCALLMETH:
// Prevent inlining some reflect.Value methods when using checkptr, base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
// even when package reflect was compiled without it (#35073). case ir.OCALLFUNC:
n := n.(*ir.CallExpr) 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") { if n.X.Op() == ir.OMETHEXPR {
return n // 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 +569,18 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
ir.EditChildren(n, edit) 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 // with all the branches out of the way, it is now time to
// transmogrify this node itself unless inhibited by the // transmogrify this node itself unless inhibited by the
// switch at the top of this function. // switch at the top of this function.
switch n.Op() { switch n.Op() {
case ir.OCALLFUNC, ir.OCALLMETH: case ir.OCALLMETH:
n := n.(*ir.CallExpr) base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
if n.NoInline {
return n
}
}
var call *ir.CallExpr
switch n.Op() {
case ir.OCALLFUNC: case ir.OCALLFUNC:
call = n.(*ir.CallExpr) call := n.(*ir.CallExpr)
if call.NoInline {
break
}
if base.Flag.LowerM > 3 { if base.Flag.LowerM > 3 {
fmt.Printf("%v:call to func %+v\n", ir.Line(n), call.X) fmt.Printf("%v:call to func %+v\n", ir.Line(n), call.X)
} }
@ -653,38 +590,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 { if fn := inlCallee(call.X); fn != nil && fn.Inl != nil {
n = mkinlcall(call, fn, maxCost, inlMap, edit) 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 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 return n
} }
@ -740,7 +649,12 @@ var inlgen int
// when producing output for debugging the compiler itself. // when producing output for debugging the compiler itself.
var SSADumpInline = func(*ir.Func) {} 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. // 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 // The returned node's Ninit has the parameter assignments, the Nbody is the
// inlined function body, and (List, Rlist) contain the (input, output) // inlined function body, and (List, Rlist) contain the (input, output)
@ -793,38 +707,90 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
defer func() { defer func() {
inlMap[fn] = false 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 != 0 {
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 {
fmt.Printf("%v: inlining call to %v\n", ir.Line(n), fn) fmt.Printf("%v: inlining call to %v\n", ir.Line(n), fn)
} }
if base.Flag.LowerM > 2 { if base.Flag.LowerM > 2 {
fmt.Printf("%v: Before inlining: %+v\n", ir.Line(n), n) 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) SSADumpInline(fn)
ninit := n.Init() ninit := call.Init()
// For normal function calls, the function callee expression // For normal function calls, the function callee expression
// may contain side effects (e.g., added by addinit during // may contain side effects. Make sure to preserve these,
// inlconv2expr or inlconv2list). Make sure to preserve these,
// if necessary (#42703). // if necessary (#42703).
if n.Op() == ir.OCALLFUNC { if call.Op() == ir.OCALLFUNC {
callee := n.X CalleeEffects(&ninit, call.X)
for callee.Op() == ir.OCONVNOP {
conv := callee.(*ir.ConvExpr)
ninit.Append(ir.TakeInit(conv)...)
callee = conv.X
}
if callee.Op() != ir.ONAME && callee.Op() != ir.OCLOSURE && callee.Op() != ir.OMETHEXPR {
base.Fatalf("unexpected callee expression: %v", callee)
}
} }
// Make temp names to use instead of the originals. // Make temp names to use instead of the originals.
@ -854,25 +820,6 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
} }
// We can delay declaring+initializing result parameters if: // 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. // temporaries for return values.
var retvars []ir.Node var retvars []ir.Node
for i, t := range fn.Type().Results().Fields().Slice() { for i, t := range fn.Type().Results().Fields().Slice() {
@ -882,7 +829,6 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
m = inlvar(n) m = inlvar(n)
m = typecheck.Expr(m).(*ir.Name) m = typecheck.Expr(m).(*ir.Name)
inlvars[n] = m inlvars[n] = m
delayretvars = false // found a named result parameter (case 3)
} else { } else {
// anonymous return values, synthesize names for use in assignment that replaces return // anonymous return values, synthesize names for use in assignment that replaces return
m = retvar(t, i) m = retvar(t, i)
@ -905,61 +851,23 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
// Assign arguments to the parameters' temp names. // Assign arguments to the parameters' temp names.
as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, nil) as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, nil)
as.Def = true as.Def = true
if n.Op() == ir.OCALLMETH { if call.Op() == ir.OCALLMETH {
sel := n.X.(*ir.SelectorExpr) base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
if sel.X == nil {
base.Fatalf("method call without receiver: %+v", n)
}
as.Rhs.Append(sel.X)
} }
as.Rhs.Append(n.Args...) as.Rhs.Append(call.Args...)
// For non-dotted calls to variadic functions, we assign the
// variadic parameter's temp name separately.
var vas *ir.AssignStmt
if recv := fn.Type().Recv(); recv != nil { if recv := fn.Type().Recv(); recv != nil {
as.Lhs.Append(inlParam(recv, as, inlvars)) as.Lhs.Append(inlParam(recv, as, inlvars))
} }
for _, param := range fn.Type().Params().Fields().Slice() { for _, param := range fn.Type().Params().Fields().Slice() {
// For ordinary parameters or variadic parameters in as.Lhs.Append(inlParam(param, as, inlvars))
// 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
}
} }
if len(as.Rhs) != 0 { if len(as.Rhs) != 0 {
ninit.Append(typecheck.Stmt(as)) ninit.Append(typecheck.Stmt(as))
} }
if vas != nil { if !fn.Inl.CanDelayResults {
ninit.Append(typecheck.Stmt(vas))
}
if !delayretvars {
// Zero the return parameters. // Zero the return parameters.
for _, n := range retvars { for _, n := range retvars {
ninit.Append(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name))) ninit.Append(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name)))
@ -972,40 +880,21 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
inlgen++ 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. // Add an inline mark just before the inlined body.
// This mark is inline in the code so that it's a reasonable spot // 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 // 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). // (in which case it could go at the end of the function instead).
// Note issue 28603. // Note issue 28603.
inlMark := ir.NewInlineMarkStmt(base.Pos, types.BADWIDTH) ninit.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(inlIndex)))
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)
}
}
subst := inlsubst{ subst := inlsubst{
retlabel: retlabel, retlabel: retlabel,
retvars: retvars, retvars: retvars,
delayretvars: delayretvars, inlvars: inlvars,
inlvars: inlvars, defnMarker: ir.NilExpr{},
defnMarker: ir.NilExpr{}, bases: make(map[*src.PosBase]*src.PosBase),
bases: make(map[*src.PosBase]*src.PosBase), newInlIndex: inlIndex,
newInlIndex: newIndex, fn: fn,
fn: fn,
} }
subst.edit = subst.node subst.edit = subst.node
@ -1026,26 +915,11 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
//dumplist("ninit post", ninit); //dumplist("ninit post", ninit);
call := ir.NewInlinedCallExpr(base.Pos, nil, nil) res := ir.NewInlinedCallExpr(base.Pos, body, retvars)
*call.PtrInit() = ninit res.SetInit(ninit)
call.Body = body res.SetType(call.Type())
call.ReturnVars = retvars res.SetTypecheck(1)
call.SetType(n.Type()) return res
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
} }
// Every time we expand a function we generate a new set of tmpnames, // Every time we expand a function we generate a new set of tmpnames,
@ -1058,8 +932,10 @@ func inlvar(var_ *ir.Name) *ir.Name {
n := typecheck.NewName(var_.Sym()) n := typecheck.NewName(var_.Sym())
n.SetType(var_.Type()) n.SetType(var_.Type())
n.SetTypecheck(1)
n.Class = ir.PAUTO n.Class = ir.PAUTO
n.SetUsed(true) n.SetUsed(true)
n.SetAutoTemp(var_.AutoTemp())
n.Curfn = ir.CurFunc // the calling function, not the called one n.Curfn = ir.CurFunc // the calling function, not the called one
n.SetAddrtaken(var_.Addrtaken()) n.SetAddrtaken(var_.Addrtaken())
@ -1071,18 +947,7 @@ func inlvar(var_ *ir.Name) *ir.Name {
func retvar(t *types.Field, i int) *ir.Name { func retvar(t *types.Field, i int) *ir.Name {
n := typecheck.NewName(typecheck.LookupNum("~R", i)) n := typecheck.NewName(typecheck.LookupNum("~R", i))
n.SetType(t.Type) n.SetType(t.Type)
n.Class = ir.PAUTO n.SetTypecheck(1)
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.Class = ir.PAUTO n.Class = ir.PAUTO
n.SetUsed(true) n.SetUsed(true)
n.Curfn = ir.CurFunc // the calling function, not the called one n.Curfn = ir.CurFunc // the calling function, not the called one
@ -1099,10 +964,6 @@ type inlsubst struct {
// Temporary result variables. // Temporary result variables.
retvars []ir.Node retvars []ir.Node
// Whether result variables should be initialized at the
// "return" statement.
delayretvars bool
inlvars map[*ir.Name]*ir.Name inlvars map[*ir.Name]*ir.Name
// defnMarker is used to mark a Node for reassignment. // defnMarker is used to mark a Node for reassignment.
// inlsubst.clovar set this during creating new ONAME. // inlsubst.clovar set this during creating new ONAME.
@ -1157,17 +1018,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 // clovar creates a new ONAME node for a local variable or param of a closure
// inside a function being inlined. // inside a function being inlined.
func (subst *inlsubst) clovar(n *ir.Name) *ir.Name { func (subst *inlsubst) clovar(n *ir.Name) *ir.Name {
// TODO(danscales): want to get rid of this shallow copy, with code like the m := ir.NewNameAt(n.Pos(), n.Sym())
// following, but it is hard to copy all the necessary flags in a maintainable way. m.Class = n.Class
// m := ir.NewNameAt(n.Pos(), n.Sym()) m.SetType(n.Type())
// m.Class = n.Class m.SetTypecheck(1)
// m.SetType(n.Type()) if n.IsClosureVar() {
// m.SetTypecheck(1) m.SetIsClosureVar(true)
//if n.IsClosureVar() { }
// m.SetIsClosureVar(true) if n.Addrtaken() {
//} m.SetAddrtaken(true)
m := &ir.Name{} }
*m = *n if n.Used() {
m.SetUsed(true)
}
m.Defn = n.Defn
m.Curfn = subst.newclofn m.Curfn = subst.newclofn
switch defn := n.Defn.(type) { switch defn := n.Defn.(type) {
@ -1200,6 +1065,8 @@ func (subst *inlsubst) clovar(n *ir.Name) *ir.Name {
m.Defn = &subst.defnMarker m.Defn = &subst.defnMarker
case *ir.TypeSwitchGuard: case *ir.TypeSwitchGuard:
// TODO(mdempsky): Set m.Defn properly. See discussion on #45743. // TODO(mdempsky): Set m.Defn properly. See discussion on #45743.
case *ir.RangeStmt:
// TODO: Set m.Defn properly if we support inlining range statement in the future.
default: default:
base.FatalfAt(n.Pos(), "unexpected Defn: %+v", defn) base.FatalfAt(n.Pos(), "unexpected Defn: %+v", defn)
} }
@ -1222,8 +1089,6 @@ func (subst *inlsubst) clovar(n *ir.Name) *ir.Name {
// closure does the necessary substitions for a ClosureExpr n and returns the new // closure does the necessary substitions for a ClosureExpr n and returns the new
// closure node. // closure node.
func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.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 // Prior to the subst edit, set a flag in the inlsubst to
// indicated that we don't want to update the source positions in // 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 // the new closure. If we do this, it will appear that the closure
@ -1231,29 +1096,16 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node {
// issue #46234 for more details. // issue #46234 for more details.
defer func(prev bool) { subst.noPosUpdate = prev }(subst.noPosUpdate) defer func(prev bool) { subst.noPosUpdate = prev }(subst.noPosUpdate)
subst.noPosUpdate = true subst.noPosUpdate = true
ir.EditChildren(m, subst.edit)
//fmt.Printf("Inlining func %v with closure into %v\n", subst.fn, ir.FuncName(ir.CurFunc)) //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 oldfn := n.Func
newfn := ir.NewFunc(oldfn.Pos()) newfn := ir.NewClosureFunc(oldfn.Pos(), true)
// 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
// Ntype can be nil for -G=3 mode. // Ntype can be nil for -G=3 mode.
if oldfn.Nname.Ntype != nil { if oldfn.Nname.Ntype != nil {
newfn.Nname.Ntype = subst.node(oldfn.Nname.Ntype).(ir.Ntype) 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 { if subst.newclofn != nil {
//fmt.Printf("Inlining a closure with a nested closure\n") //fmt.Printf("Inlining a closure with a nested closure\n")
@ -1303,13 +1155,9 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node {
// Actually create the named function for the closure, now that // Actually create the named function for the closure, now that
// the closure is inlined in a specific function. // the closure is inlined in a specific function.
m.SetTypecheck(0) newclo := newfn.OClosure
if oldfn.ClosureCalled() { newclo.SetInit(subst.list(n.Init()))
typecheck.Callee(m) return typecheck.Expr(newclo)
} else {
typecheck.Expr(m)
}
return m
} }
// node recursively copies a node from the saved pristine body of the // node recursively copies a node from the saved pristine body of the
@ -1391,7 +1239,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node {
} }
as.Rhs = subst.list(n.Results) as.Rhs = subst.list(n.Results)
if subst.delayretvars { if subst.fn.Inl.CanDelayResults {
for _, n := range as.Lhs { for _, n := range as.Lhs {
as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name))) as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name)))
n.Name().Defn = as 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). // A CallExpr is a function call X(Args).
type CallExpr struct { type CallExpr struct {
miniExpr miniExpr
origNode origNode
X Node X Node
Args Nodes Args Nodes
KeepAlive []*Name // vars to be kept alive until call returns KeepAlive []*Name // vars to be kept alive until call returns
IsDDD bool IsDDD bool
Use CallUse NoInline bool
NoInline bool
PreserveClosure bool // disable directClosureCall for this call
} }
func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr { func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr {
@ -181,8 +168,12 @@ func (n *CallExpr) SetOp(op Op) {
switch op { switch op {
default: default:
panic(n.no("SetOp " + op.String())) panic(n.no("SetOp " + op.String()))
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, case OAPPEND,
OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER: OCALL, OCALLFUNC, OCALLINTER, OCALLMETH,
ODELETE,
OGETG, OGETCALLERPC, OGETCALLERSP,
OMAKE, OPRINT, OPRINTN,
ORECOVER, ORECOVERFP:
n.op = op n.op = op
} }
} }
@ -192,8 +183,10 @@ type ClosureExpr struct {
miniExpr miniExpr
Func *Func `mknode:"-"` Func *Func `mknode:"-"`
Prealloc *Name 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 { func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
n := &ClosureExpr{Func: fn} n := &ClosureExpr{Func: fn}
n.op = OCLOSURE n.op = OCLOSURE
@ -277,12 +270,12 @@ func (n *ConvExpr) SetOp(op Op) {
switch op { switch op {
default: default:
panic(n.no("SetOp " + op.String())) 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 n.op = op
} }
} }
// An IndexExpr is an index expression X[Y]. // An IndexExpr is an index expression X[Index].
type IndexExpr struct { type IndexExpr struct {
miniExpr miniExpr
X Node X Node
@ -323,26 +316,24 @@ func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr {
// A StructKeyExpr is an Field: Value composite literal key. // A StructKeyExpr is an Field: Value composite literal key.
type StructKeyExpr struct { type StructKeyExpr struct {
miniExpr miniExpr
Field *types.Sym Field *types.Field
Value Node Value Node
Offset int64
} }
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 := &StructKeyExpr{Field: field, Value: value}
n.pos = pos n.pos = pos
n.op = OSTRUCTKEY n.op = OSTRUCTKEY
n.Offset = types.BADWIDTH
return n 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. // An InlinedCallExpr is an inlined function call.
type InlinedCallExpr struct { type InlinedCallExpr struct {
miniExpr miniExpr
Body Nodes Body Nodes
ReturnVars Nodes ReturnVars Nodes // must be side-effect free
} }
func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr {
@ -354,6 +345,21 @@ func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr {
return n 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 ||. // A LogicalExpr is a expression X Op Y where Op is && or ||.
// It is separate from BinaryExpr to make room for statements // It is separate from BinaryExpr to make room for statements
// that must be executed before Y but after X. // that must be executed before Y but after X.
@ -448,6 +454,20 @@ func (n *ParenExpr) SetOTYPE(t *types.Type) {
t.SetNod(n) 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. // A ResultExpr represents a direct access to a result.
type ResultExpr struct { type ResultExpr struct {
miniExpr 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. // A SelectorExpr is a selector expression X.Sel.
type SelectorExpr struct { type SelectorExpr struct {
miniExpr miniExpr
X Node X Node
Sel *types.Sym // 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 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 { 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 { switch op {
default: default:
panic(n.no("SetOp " + op.String())) 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 n.op = op
} }
} }
@ -545,10 +570,11 @@ func (*SelectorExpr) CanBeNtype() {}
// A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max]. // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max].
type SliceExpr struct { type SliceExpr struct {
miniExpr miniExpr
X Node X Node
Low Node Low Node
High Node High Node
Max Node Max Node
CheckPtrCall *CallExpr `mknode:"-"`
} }
func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr { func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr {
@ -652,6 +678,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, // A UnaryExpr is a unary expression Op X,
// or Op(X) for a builtin function that does not end up being a call. // or Op(X) for a builtin function that does not end up being a call.
type UnaryExpr struct { type UnaryExpr struct {
@ -678,6 +736,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. // An InstExpr is a generic function or type instantiation.
type InstExpr struct { type InstExpr struct {
miniExpr miniExpr
@ -773,6 +836,11 @@ func StaticValue(n Node) Node {
continue continue
} }
if n.Op() == OINLCALL {
n = n.(*InlinedCallExpr).SingleResult()
continue
}
n1 := staticValue1(n) n1 := staticValue1(n)
if n1 == nil { if n1 == nil {
return n return n
@ -1071,7 +1139,7 @@ func MethodExprName(n Node) *Name {
// MethodExprFunc is like MethodExprName, but returns the types.Field instead. // MethodExprFunc is like MethodExprName, but returns the types.Field instead.
func MethodExprFunc(n Node) *types.Field { func MethodExprFunc(n Node) *types.Field {
switch n.Op() { switch n.Op() {
case ODOTMETH, OMETHEXPR, OCALLPART: case ODOTMETH, OMETHEXPR, OMETHVALUE:
return n.(*SelectorExpr).Selection return n.(*SelectorExpr).Selection
} }
base.Fatalf("unexpected node: %v (%v)", n, n.Op()) base.Fatalf("unexpected node: %v (%v)", n, n.Op())

View File

@ -185,6 +185,7 @@ var OpPrec = []int{
OCLOSE: 8, OCLOSE: 8,
OCOMPLIT: 8, OCOMPLIT: 8,
OCONVIFACE: 8, OCONVIFACE: 8,
OCONVIDATA: 8,
OCONVNOP: 8, OCONVNOP: 8,
OCONV: 8, OCONV: 8,
OCOPY: 8, OCOPY: 8,
@ -237,7 +238,7 @@ var OpPrec = []int{
ODOTTYPE: 8, ODOTTYPE: 8,
ODOT: 8, ODOT: 8,
OXDOT: 8, OXDOT: 8,
OCALLPART: 8, OMETHVALUE: 8,
OMETHEXPR: 8, OMETHEXPR: 8,
OPLUS: 7, OPLUS: 7,
ONOT: 7, ONOT: 7,
@ -546,7 +547,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
n = nn.X n = nn.X
continue continue
} }
case OCONV, OCONVNOP, OCONVIFACE: case OCONV, OCONVNOP, OCONVIFACE, OCONVIDATA:
nn := nn.(*ConvExpr) nn := nn.(*ConvExpr)
if nn.Implicit() { if nn.Implicit() {
n = nn.X n = nn.X
@ -567,6 +568,11 @@ func exprFmt(n Node, s fmt.State, prec int) {
return return
} }
if n, ok := n.(*RawOrigExpr); ok {
fmt.Fprint(s, n.Raw)
return
}
switch n.Op() { switch n.Op() {
case OPAREN: case OPAREN:
n := n.(*ParenExpr) n := n.(*ParenExpr)
@ -709,6 +715,10 @@ func exprFmt(n Node, s fmt.State, prec int) {
fmt.Fprintf(s, "... argument") fmt.Fprintf(s, "... argument")
return return
} }
if typ := n.Type(); typ != nil {
fmt.Fprintf(s, "%v{%s}", typ, ellipsisIf(len(n.List) != 0))
return
}
if n.Ntype != nil { if n.Ntype != nil {
fmt.Fprintf(s, "%v{%s}", n.Ntype, ellipsisIf(len(n.List) != 0)) fmt.Fprintf(s, "%v{%s}", n.Ntype, ellipsisIf(len(n.List) != 0))
return return
@ -752,7 +762,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
n := n.(*StructKeyExpr) n := n.(*StructKeyExpr)
fmt.Fprintf(s, "%v:%v", n.Field, n.Value) 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) n := n.(*SelectorExpr)
exprFmt(n.X, s, nprec) exprFmt(n.X, s, nprec)
if n.Sel == nil { if n.Sel == nil {
@ -804,6 +814,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
case OCONV, case OCONV,
OCONVIFACE, OCONVIFACE,
OCONVIDATA,
OCONVNOP, OCONVNOP,
OBYTES2STR, OBYTES2STR,
ORUNES2STR, ORUNES2STR,
@ -854,6 +865,15 @@ func exprFmt(n Node, s fmt.State, prec int) {
} }
fmt.Fprintf(s, "(%.v)", n.Args) 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: case OMAKEMAP, OMAKECHAN, OMAKESLICE:
n := n.(*MakeExpr) n := n.(*MakeExpr)
if n.Cap != nil { 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. // Dump prints the message s followed by a debug dump of n.
func Dump(s string, n Node) { 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. // 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() { if n.Pos().IsKnown() {
pfx := "" fmt.Fprint(w, " # ")
switch n.Pos().IsStmt() { switch n.Pos().IsStmt() {
case src.PosNotStmt: case src.PosNotStmt:
pfx = "_" // "-" would be confusing fmt.Fprint(w, "_") // "-" would be confusing
case src.PosIsStmt: 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/compile/internal/types"
"cmd/internal/obj" "cmd/internal/obj"
"cmd/internal/src" "cmd/internal/src"
"fmt"
) )
// A Func corresponds to a single function in a Go program // A Func corresponds to a single function in a Go program
@ -39,14 +40,14 @@ import (
// constructs a fresh node. // constructs a fresh node.
// //
// A method value (t.M) is represented by ODOTMETH/ODOTINTER // 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, // These are like method expressions, except that for ODOTMETH/ODOTINTER,
// the method name is stored in Sym instead of Right. // 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. // 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 // 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 { type Func struct {
miniNode miniNode
Body Nodes Body Nodes
@ -166,6 +167,11 @@ type Inline struct {
// another package is imported. // another package is imported.
Dcl []*Name Dcl []*Name
Body []Node 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. // A Mark represents a scope boundary.
@ -190,13 +196,14 @@ const (
// true if closure inside a function; false if a simple function or a // true if closure inside a function; false if a simple function or a
// closure in a global variable initialization // closure in a global variable initialization
funcIsHiddenClosure funcIsHiddenClosure
funcIsDeadcodeClosure // true if closure is deadcode
funcHasDefer // contains a defer statement funcHasDefer // contains a defer statement
funcNilCheckDisabled // disable nil checks when compiling this function funcNilCheckDisabled // disable nil checks when compiling this function
funcInlinabilityChecked // inliner has already determined whether the function is inlinable funcInlinabilityChecked // inliner has already determined whether the function is inlinable
funcExportInline // include inline body in export data funcExportInline // include inline body in export data
funcInstrumentBody // add race/msan instrumentation during SSA construction funcInstrumentBody // add race/msan instrumentation during SSA construction
funcOpenCodedDeferDisallowed // can't do open-coded defers 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 { 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) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 } func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 }
func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 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) HasDefer() bool { return f.flags&funcHasDefer != 0 }
func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 } func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 }
func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 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) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) }
func (f *Func) SetReflectMethod(b bool) { f.flags.set(funcReflectMethod, 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) 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) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) } func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) } func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) }
@ -272,6 +281,17 @@ func PkgFuncName(f *Func) string {
var CurFunc *Func 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 { func FuncSymName(s *types.Sym) string {
return s.Name + "·f" return s.Name + "·f"
} }
@ -279,7 +299,7 @@ func FuncSymName(s *types.Sym) string {
// MarkFunc marks a node as a function. // MarkFunc marks a node as a function.
func MarkFunc(n *Name) { func MarkFunc(n *Name) {
if n.Op() != ONAME || n.Class != Pxxx { 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 n.Class = PFUNC
@ -296,8 +316,8 @@ func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars) base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
} }
} }
if base.Flag.CompilingRuntime && clo.Esc() == EscHeap { if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
base.ErrorfAt(clo.Pos(), "heap-allocated closure, not allowed in runtime") 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 { func IsTrivialClosure(clo *ClosureExpr) bool {
return len(clo.Func.ClosureVars) == 0 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

@ -51,6 +51,8 @@ type Name struct {
// For a local variable (not param) or extern, the initializing assignment (OAS or OAS2). // For a local variable (not param) or extern, the initializing assignment (OAS or OAS2).
// For a closure var, the ONAME node of the outer captured variable. // For a closure var, the ONAME node of the outer captured variable.
// For the case-local variables of a type switch, the type switch guard (OTYPESW). // For the case-local variables of a type switch, the type switch guard (OTYPESW).
// For a range variable, the range statement (ORANGE)
// For a recv variable in a case of a select statement, the receive assignment (OSELRECV2)
// For the name of a function, points to corresponding Func node. // For the name of a function, points to corresponding Func node.
Defn Node Defn Node
@ -358,39 +360,74 @@ func (n *Name) Byval() bool {
return n.Canonical().flags&nameByval != 0 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 // 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 // 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 // within a function that encloses fn, then CaptureName returns the closure
// variable that refers to n and adds it to fn.ClosureVars. Otherwise, it simply // variable that refers to n within fn, creating it if necessary.
// returns n. // Otherwise, it simply returns n.
func CaptureName(pos src.XPos, fn *Func, n *Name) *Name { func CaptureName(pos src.XPos, fn *Func, n *Name) *Name {
if n.Op() != ONAME || n.Curfn == nil {
return n // okay to use directly
}
if n.IsClosureVar() { if n.IsClosureVar() {
base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n) 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 { if fn == nil {
base.FatalfAt(pos, "package-block reference to %v, declared in %v", n, n.Curfn) 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. // Do not have a closure var for the active closure yet; make one.
c = NewNameAt(pos, n.Sym()) c = NewClosureVar(pos, fn, c)
c.Curfn = fn
c.Class = PAUTOHEAP
c.SetIsClosureVar(true)
c.Defn = n
// Link into list of active closure variables. // Link into list of active closure variables.
// Popped from list in FinishCaptureNames. // Popped from list in FinishCaptureNames.
c.Outer = n.Innermost
n.Innermost = c n.Innermost = c
fn.ClosureVars = append(fn.ClosureVars, c)
return c return c
} }

View File

@ -159,7 +159,6 @@ const (
OCALLFUNC // X(Args) (function call f(args)) OCALLFUNC // X(Args) (function call f(args))
OCALLMETH // X(Args) (direct method call x.Method(args)) OCALLMETH // X(Args) (direct method call x.Method(args))
OCALLINTER // X(Args) (interface 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) OCAP // cap(X)
OCLOSE // close(X) OCLOSE // close(X)
OCLOSURE // func Type { Func.Closure.Body } (func literal) OCLOSURE // func Type { Func.Closure.Body } (func literal)
@ -171,6 +170,7 @@ const (
OPTRLIT // &X (X is composite literal) OPTRLIT // &X (X is composite literal)
OCONV // Type(X) (type conversion) OCONV // Type(X) (type conversion)
OCONVIFACE // Type(X) (type conversion, to interface) 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) OCONVNOP // Type(X) (type conversion, no effect)
OCOPY // copy(X, Y) OCOPY // copy(X, Y)
ODCL // var X (declares X of type X.Type) ODCL // var X (declares X of type X.Type)
@ -237,6 +237,7 @@ const (
OSLICE3ARR // X[Low : High : Max] (X is pointer to array) 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) OSLICEHEADER // sliceheader{Ptr, Len, Cap} (Ptr is unsafe.Pointer, Len is length, Cap is capacity)
ORECOVER // recover() ORECOVER // recover()
ORECOVERFP // recover(Args) w/ explicit FP argument
ORECV // <-X ORECV // <-X
ORUNESTR // Type(X) (Type is string, X is rune) 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) 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) OSIZEOF // unsafe.Sizeof(X)
OUNSAFEADD // unsafe.Add(X, Y) OUNSAFEADD // unsafe.Add(X, Y)
OUNSAFESLICE // unsafe.Slice(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 // statements
OBLOCK // { List } (block of code) OBLOCK // { List } (block of code)
OBREAK // break [Label] OBREAK // break [Label]
// OCASE: case List: Body (List==nil means default) // OCASE: case List: Body (List==nil means default)
// For OTYPESW, List is a OTYPE node for the specified type (or OLITERAL // 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 // ONAME for the version of the type-switch variable with the specified
// type. // type.
OCASE OCASE
@ -317,13 +320,30 @@ const (
OINLMARK // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree. OINLMARK // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree.
OLINKSYMOFFSET // offset within a name 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 // arch-specific opcodes
OTAILCALL // tail call to another function OTAILCALL // tail call to another function
OGETG // runtime.getg() (read g pointer) OGETG // runtime.getg() (read g pointer)
OGETCALLERPC // runtime.getcallerpc() (continuation PC in caller frame)
OGETCALLERSP // runtime.getcallersp() (stack pointer in caller frame)
OEND OEND
) )
// IsCmp reports whether op is a comparison operation (==, !=, <, <=,
// >, or >=).
func (op Op) IsCmp() bool {
switch op {
case OEQ, ONE, OLT, OLE, OGT, OGE:
return true
}
return false
}
// Nodes is a pointer to a slice of *Node. // Nodes is a pointer to a slice of *Node.
// For fields that are not used in most nodes, this is used instead of // For fields that are not used in most nodes, this is used instead of
// a slice to save space. // a slice to save space.
@ -436,18 +456,19 @@ func (s NameSet) Sorted(less func(*Name, *Name) bool) []*Name {
return res return res
} }
type PragmaFlag int16 type PragmaFlag uint16
const ( const (
// Func pragmas. // Func pragmas.
Nointerface PragmaFlag = 1 << iota Nointerface PragmaFlag = 1 << iota
Noescape // func parameters don't escape Noescape // func parameters don't escape
Norace // func must not have race detector annotations Norace // func must not have race detector annotations
Nosplit // func should not execute on separate stack Nosplit // func should not execute on separate stack
Noinline // func should not be inlined Noinline // func should not be inlined
NoCheckPtr // func should not be instrumented by checkptr NoCheckPtr // func should not be instrumented by checkptr
CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all
UintptrEscapes // pointers converted to uintptr escape UintptrKeepAlive // pointers converted to uintptr must be kept alive (compiler internal only)
UintptrEscapes // pointers converted to uintptr escape
// Runtime-only func pragmas. // Runtime-only func pragmas.
// See ../../../../runtime/README.md for detailed descriptions. // See ../../../../runtime/README.md for detailed descriptions.
@ -563,7 +584,7 @@ func OuterValue(n Node) Node {
for { for {
switch nn := n; nn.Op() { switch nn := n; nn.Op() {
case OXDOT: case OXDOT:
base.Fatalf("OXDOT in walk") base.FatalfAt(n.Pos(), "OXDOT in walk: %v", n)
case ODOT: case ODOT:
nn := nn.(*SelectorExpr) nn := nn.(*SelectorExpr)
n = nn.X 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) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
func (n *ForStmt) copy() Node { func (n *ForStmt) copy() Node {
c := *n 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) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
func (n *ResultExpr) copy() Node { func (n *ResultExpr) copy() Node {
c := *n c := *n

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