mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
[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:
commit
5abfd2379b
136
CONTRIBUTORS
136
CONTRIBUTORS
@ -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>
|
||||||
|
@ -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"
|
||||||
|
205
api/next.txt
205
api/next.txt
@ -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
|
|
||||||
|
12
doc/asm.html
12
doc/asm.html
@ -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>-></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>.
|
||||||
|
1175
doc/go1.17.html
1175
doc/go1.17.html
File diff suppressed because it is too large
Load Diff
114
doc/go1.18.html
Normal file
114
doc/go1.18.html
Normal 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 -->
|
@ -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:]) // &s1[0] == &s[1]
|
||||||
s2 := (*[2]byte)(s) // &s2[0] == &s[0]
|
s2 := (*[2]byte)(s) // &s2[0] == &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>
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
12
misc/cgo/errors/testdata/err2.go
vendored
12
misc/cgo/errors/testdata/err2.go
vendored
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
9
misc/cgo/test/testdata/issue43639.go
vendored
Normal 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"
|
8
misc/cgo/test/testdata/issue43639/a.go
vendored
Normal file
8
misc/cgo/test/testdata/issue43639/a.go
vendored
Normal 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"
|
@ -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 {
|
||||||
|
109
misc/cgo/testsanitizers/testdata/msan8.go
vendored
Normal file
109
misc/cgo/testsanitizers/testdata/msan8.go
vendored
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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] }
|
||||||
|
@ -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{}
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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} {
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
17
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
17
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
@ -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
|
||||||
|
@ -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
|
||||||
|
89
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
89
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
@ -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
|
||||||
|
12
src/cmd/asm/internal/asm/testdata/riscv64error.s
vendored
12
src/cmd/asm/internal/asm/testdata/riscv64error.s
vendored
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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 Go’s
|
||||||
|
stack-based calling convention.
|
||||||
|
|
||||||
|
*Rationale*: The link register, R30, holds the function return
|
||||||
|
address at the function entry. For functions that have frames
|
||||||
|
(including most non-leaf functions), R30 is saved to stack in the
|
||||||
|
function prologue and restored in the epilogue. Within the function
|
||||||
|
body, R30 can be used as a scratch register.
|
||||||
|
|
||||||
|
*Implementation note*: Registers with fixed meaning at calls but not
|
||||||
|
in function bodies must be initialized by "injected" calls such as
|
||||||
|
signal-based panics.
|
||||||
|
|
||||||
|
#### Stack layout
|
||||||
|
|
||||||
|
The stack pointer, RSP, grows down and is always aligned to 16 bytes.
|
||||||
|
|
||||||
|
*Rationale*: The arm64 architecture requires the stack pointer to be
|
||||||
|
16-byte aligned.
|
||||||
|
|
||||||
|
A function's stack frame, after the frame is created, is laid out as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
+------------------------------+
|
||||||
|
| ... locals ... |
|
||||||
|
| ... outgoing arguments ... |
|
||||||
|
| return PC | ← RSP points to
|
||||||
|
| frame pointer on entry |
|
||||||
|
+------------------------------+ ↓ lower addresses
|
||||||
|
|
||||||
|
The "return PC" is loaded to the link register, R30, as part of the
|
||||||
|
arm64 `CALL` operation.
|
||||||
|
|
||||||
|
On entry, a function subtracts from RSP to open its stack frame, and
|
||||||
|
saves the values of R30 and R29 at the bottom of the frame.
|
||||||
|
Specifically, R30 is saved at 0(RSP) and R29 is saved at -8(RSP),
|
||||||
|
after RSP is updated.
|
||||||
|
|
||||||
|
A leaf function that does not require any stack space may omit the
|
||||||
|
saved R30 and R29.
|
||||||
|
|
||||||
|
The Go ABI's use of R29 as a frame pointer register is compatible with
|
||||||
|
arm64 architecture requirement so that Go can inter-operate with platform
|
||||||
|
debuggers and profilers.
|
||||||
|
|
||||||
|
This stack layout is used by both register-based (ABIInternal) and
|
||||||
|
stack-based (ABI0) calling conventions.
|
||||||
|
|
||||||
|
#### Flags
|
||||||
|
|
||||||
|
The arithmetic status flags (NZCV) are treated like scratch registers
|
||||||
|
and not preserved across calls.
|
||||||
|
All other bits in PSTATE are system flags and are not modified by Go.
|
||||||
|
|
||||||
|
The floating-point status register (FPSR) is treated like scratch
|
||||||
|
registers and not preserved across calls.
|
||||||
|
|
||||||
|
At calls, the floating-point control register (FPCR) bits are always
|
||||||
|
set as follows:
|
||||||
|
|
||||||
|
| Flag | Bit | Value | Meaning |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| DN | 25 | 0 | Propagate NaN operands |
|
||||||
|
| FZ | 24 | 0 | Do not flush to zero |
|
||||||
|
| RC | 23/22 | 0 (RN) | Round to nearest, choose even if tied |
|
||||||
|
| IDE | 15 | 0 | Denormal operations trap disabled |
|
||||||
|
| IXE | 12 | 0 | Inexact trap disabled |
|
||||||
|
| UFE | 11 | 0 | Underflow trap disabled |
|
||||||
|
| OFE | 10 | 0 | Overflow trap disabled |
|
||||||
|
| DZE | 9 | 0 | Divide-by-zero trap disabled |
|
||||||
|
| IOE | 8 | 0 | Invalid operations trap disabled |
|
||||||
|
| NEP | 2 | 0 | Scalar operations do not affect higher elements in vector registers |
|
||||||
|
| AH | 1 | 0 | No alternate handling of de-normal inputs |
|
||||||
|
| FIZ | 0 | 0 | Do not zero de-normals |
|
||||||
|
|
||||||
|
*Rationale*: Having a fixed FPCR control configuration allows Go
|
||||||
|
functions to use floating-point and vector (SIMD) operations without
|
||||||
|
modifying or saving the FPCR.
|
||||||
|
Functions are allowed to modify it between calls (as long as they
|
||||||
|
restore it), but as of this writing Go code never does.
|
||||||
|
|
||||||
## Future directions
|
## Future directions
|
||||||
|
|
||||||
### Spill path improvements
|
### Spill path improvements
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
12
src/cmd/compile/internal/base/bootstrap_false.go
Normal file
12
src/cmd/compile/internal/base/bootstrap_false.go
Normal 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
|
12
src/cmd/compile/internal/base/bootstrap_true.go
Normal file
12
src/cmd/compile/internal/base/bootstrap_true.go
Normal 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
|
@ -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"`
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
@ -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 {
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
120
src/cmd/compile/internal/escape/assign.go
Normal file
120
src/cmd/compile/internal/escape/assign.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
428
src/cmd/compile/internal/escape/call.go
Normal file
428
src/cmd/compile/internal/escape/call.go
Normal 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...)
|
||||||
|
}
|
37
src/cmd/compile/internal/escape/desugar.go
Normal file
37
src/cmd/compile/internal/escape/desugar.go
Normal 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
335
src/cmd/compile/internal/escape/expr.go
Normal file
335
src/cmd/compile/internal/escape/expr.go
Normal 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()
|
||||||
|
}
|
324
src/cmd/compile/internal/escape/graph.go
Normal file
324
src/cmd/compile/internal/escape/graph.go
Normal 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 = ¬e{
|
||||||
|
next: k.notes,
|
||||||
|
where: where,
|
||||||
|
why: why,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k hole) shift(delta int) hole {
|
||||||
|
k.derefs += delta
|
||||||
|
if k.derefs < -1 {
|
||||||
|
base.Fatalf("derefs underflow: %v", k.derefs)
|
||||||
|
}
|
||||||
|
k.addrtaken = delta < 0
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k hole) deref(where ir.Node, why string) hole { return k.shift(1).note(where, why) }
|
||||||
|
func (k hole) addr(where ir.Node, why string) hole { return k.shift(-1).note(where, why) }
|
||||||
|
|
||||||
|
func (k hole) dotType(t *types.Type, where ir.Node, why string) hole {
|
||||||
|
if !t.IsInterface() && !types.IsDirectIface(t) {
|
||||||
|
k = k.shift(1)
|
||||||
|
}
|
||||||
|
return k.note(where, why)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *batch) flow(k hole, src *location) {
|
||||||
|
if k.addrtaken {
|
||||||
|
src.addrtaken = true
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := k.dst
|
||||||
|
if dst == &b.blankLoc {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if dst == src && k.derefs >= 0 { // dst = dst, dst = *dst, ...
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if dst.escapes && k.derefs < 0 { // dst = &src
|
||||||
|
if base.Flag.LowerM >= 2 || logopt.Enabled() {
|
||||||
|
pos := base.FmtPos(src.n.Pos())
|
||||||
|
if base.Flag.LowerM >= 2 {
|
||||||
|
fmt.Printf("%s: %v escapes to heap:\n", pos, src.n)
|
||||||
|
}
|
||||||
|
explanation := b.explainFlow(pos, dst, src, k.derefs, k.notes, []*logopt.LoggedOpt{})
|
||||||
|
if logopt.Enabled() {
|
||||||
|
var e_curfn *ir.Func // TODO(mdempsky): Fix.
|
||||||
|
logopt.LogOpt(src.n.Pos(), "escapes", "escape", ir.FuncName(e_curfn), fmt.Sprintf("%v escapes to heap", src.n), explanation)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
src.escapes = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdempsky): Deduplicate edges?
|
||||||
|
dst.edges = append(dst.edges, edge{src: src, derefs: k.derefs, notes: k.notes})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *batch) heapHole() hole { return b.heapLoc.asHole() }
|
||||||
|
func (b *batch) discardHole() hole { return b.blankLoc.asHole() }
|
||||||
|
|
||||||
|
func (b *batch) oldLoc(n *ir.Name) *location {
|
||||||
|
if n.Canonical().Opt == nil {
|
||||||
|
base.Fatalf("%v has no location", n)
|
||||||
|
}
|
||||||
|
return n.Canonical().Opt.(*location)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *escape) newLoc(n ir.Node, transient bool) *location {
|
||||||
|
if e.curfn == nil {
|
||||||
|
base.Fatalf("e.curfn isn't set")
|
||||||
|
}
|
||||||
|
if n != nil && n.Type() != nil && n.Type().NotInHeap() {
|
||||||
|
base.ErrorfAt(n.Pos(), "%v is incomplete (or unallocatable); stack allocation disallowed", n.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != nil && n.Op() == ir.ONAME {
|
||||||
|
if canon := n.(*ir.Name).Canonical(); n != canon {
|
||||||
|
base.Fatalf("newLoc on non-canonical %v (canonical is %v)", n, canon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loc := &location{
|
||||||
|
n: n,
|
||||||
|
curfn: e.curfn,
|
||||||
|
loopDepth: e.loopDepth,
|
||||||
|
transient: transient,
|
||||||
|
}
|
||||||
|
e.allLocs = append(e.allLocs, loc)
|
||||||
|
if n != nil {
|
||||||
|
if n.Op() == ir.ONAME {
|
||||||
|
n := n.(*ir.Name)
|
||||||
|
if n.Class == ir.PPARAM && n.Curfn == nil {
|
||||||
|
// ok; hidden parameter
|
||||||
|
} else if n.Curfn != e.curfn {
|
||||||
|
base.Fatalf("curfn mismatch: %v != %v for %v", n.Curfn, e.curfn, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.Opt != nil {
|
||||||
|
base.Fatalf("%v already has a location", n)
|
||||||
|
}
|
||||||
|
n.Opt = loc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return loc
|
||||||
|
}
|
||||||
|
|
||||||
|
// teeHole returns a new hole that flows into each hole of ks,
|
||||||
|
// similar to the Unix tee(1) command.
|
||||||
|
func (e *escape) teeHole(ks ...hole) hole {
|
||||||
|
if len(ks) == 0 {
|
||||||
|
return e.discardHole()
|
||||||
|
}
|
||||||
|
if len(ks) == 1 {
|
||||||
|
return ks[0]
|
||||||
|
}
|
||||||
|
// TODO(mdempsky): Optimize if there's only one non-discard hole?
|
||||||
|
|
||||||
|
// Given holes "l1 = _", "l2 = **_", "l3 = *_", ..., create a
|
||||||
|
// new temporary location ltmp, wire it into place, and return
|
||||||
|
// a hole for "ltmp = _".
|
||||||
|
loc := e.newLoc(nil, true)
|
||||||
|
for _, k := range ks {
|
||||||
|
// N.B., "p = &q" and "p = &tmp; tmp = q" are not
|
||||||
|
// semantically equivalent. To combine holes like "l1
|
||||||
|
// = _" and "l2 = &_", we'd need to wire them as "l1 =
|
||||||
|
// *ltmp" and "l2 = ltmp" and return "ltmp = &_"
|
||||||
|
// instead.
|
||||||
|
if k.derefs < 0 {
|
||||||
|
base.Fatalf("teeHole: negative derefs")
|
||||||
|
}
|
||||||
|
|
||||||
|
e.flow(k, loc)
|
||||||
|
}
|
||||||
|
return loc.asHole()
|
||||||
|
}
|
||||||
|
|
||||||
|
// later returns a new hole that flows into k, but some time later.
|
||||||
|
// Its main effect is to prevent immediate reuse of temporary
|
||||||
|
// variables introduced during Order.
|
||||||
|
func (e *escape) later(k hole) hole {
|
||||||
|
loc := e.newLoc(nil, false)
|
||||||
|
e.flow(k, loc)
|
||||||
|
return loc.asHole()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fmt is called from node printing to print information about escape analysis results.
|
||||||
|
func Fmt(n ir.Node) string {
|
||||||
|
text := ""
|
||||||
|
switch n.Esc() {
|
||||||
|
case ir.EscUnknown:
|
||||||
|
break
|
||||||
|
|
||||||
|
case ir.EscHeap:
|
||||||
|
text = "esc(h)"
|
||||||
|
|
||||||
|
case ir.EscNone:
|
||||||
|
text = "esc(no)"
|
||||||
|
|
||||||
|
case ir.EscNever:
|
||||||
|
text = "esc(N)"
|
||||||
|
|
||||||
|
default:
|
||||||
|
text = fmt.Sprintf("esc(%d)", n.Esc())
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.Op() == ir.ONAME {
|
||||||
|
n := n.(*ir.Name)
|
||||||
|
if loc, ok := n.Opt.(*location); ok && loc.loopDepth != 0 {
|
||||||
|
if text != "" {
|
||||||
|
text += " "
|
||||||
|
}
|
||||||
|
text += fmt.Sprintf("ld(%d)", loc.loopDepth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return text
|
||||||
|
}
|
106
src/cmd/compile/internal/escape/leaks.go
Normal file
106
src/cmd/compile/internal/escape/leaks.go
Normal 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
|
||||||
|
}
|
289
src/cmd/compile/internal/escape/solve.go
Normal file
289
src/cmd/compile/internal/escape/solve.go
Normal 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)] == '.'
|
||||||
|
}
|
207
src/cmd/compile/internal/escape/stmt.go
Normal file
207
src/cmd/compile/internal/escape/stmt.go
Normal 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()
|
||||||
|
}
|
215
src/cmd/compile/internal/escape/utils.go
Normal file
215
src/cmd/compile/internal/escape/utils.go
Normal 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 ""
|
||||||
|
}
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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++
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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{}
|
||||||
|
@ -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
|
||||||
|
@ -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())
|
||||||
|
@ -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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user