From 88e33f6ecb9ea44a464bd3863f8037bc081b2a6e Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 25 Nov 2020 14:02:46 -0800 Subject: [PATCH 001/212] [dev.regabi] cmd/compile: fix latent import/export issue with break/continue In CL 145200, I changed OBREAK, OCONTINUE, OGOTO, and OLABEL to just use Sym instead of Node. However, within the export data, I forgot to update the code for OBREAK and OCONTINUE. This isn't currently an issue because the inliner currently disallows these anyway, but it'll be an issue in the future once we add support for inlining them. Also, Russ independently ran into it in CL 273246. Updates #14768. Change-Id: I94575df59c08a750b0dce1d3ce612aba7bfeeb76 Reviewed-on: https://go-review.googlesource.com/c/go/+/273270 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/iexport.go | 13 ++++++------- src/cmd/compile/internal/gc/iimport.go | 14 ++++---------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index ef52e40f21..7c42e43bee 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -1146,18 +1146,17 @@ func (w *exportWriter) stmt(n ir.Node) { w.op(ir.OFALL) w.pos(n.Pos()) - case ir.OBREAK, ir.OCONTINUE: - w.op(op) - w.pos(n.Pos()) - w.exprsOrNil(n.Left(), nil) - case ir.OEMPTY: // nothing to emit - case ir.OGOTO, ir.OLABEL: + case ir.OBREAK, ir.OCONTINUE, ir.OGOTO, ir.OLABEL: w.op(op) w.pos(n.Pos()) - w.string(n.Sym().Name) + label := "" + if sym := n.Sym(); sym != nil { + label = sym.Name + } + w.string(label) default: base.Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op()) diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 77078c118a..066d956b93 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -1052,20 +1052,14 @@ func (r *importReader) node() ir.Node { n := ir.NodAt(r.pos(), ir.OFALL, nil, nil) return n - case ir.OBREAK, ir.OCONTINUE: - pos := r.pos() - left, _ := r.exprsOrNil() - if left != nil { - left = NewName(left.Sym()) - } - return ir.NodAt(pos, op, left, nil) - // case OEMPTY: // unreachable - not emitted by exporter - case ir.OGOTO, ir.OLABEL: + case ir.OBREAK, ir.OCONTINUE, ir.OGOTO, ir.OLABEL: n := ir.NodAt(r.pos(), op, nil, nil) - n.SetSym(lookup(r.string())) + if label := r.string(); label != "" { + n.SetSym(lookup(label)) + } return n case ir.OEND: From f0ff6d4a67ec9a956aa655d487543da034cf576b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 25 Nov 2020 13:47:42 -0800 Subject: [PATCH 002/212] reflect: fix Value.Convert for int-to-string conversions (regression) The bug was introduced by https://golang.org/cl/220844. Updates #42792. Fixes #42835. Change-Id: I03065c7526488aded35ef2f800b7162e1606877a Reviewed-on: https://go-review.googlesource.com/c/go/+/273326 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/reflect/all_test.go | 3 +++ src/reflect/value.go | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index a12712d254..b01158635f 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -4007,9 +4007,12 @@ var convertTests = []struct { {V(int16(-3)), V(string("\uFFFD"))}, {V(int32(-4)), V(string("\uFFFD"))}, {V(int64(-5)), V(string("\uFFFD"))}, + {V(int64(-1 << 32)), V(string("\uFFFD"))}, + {V(int64(1 << 32)), V(string("\uFFFD"))}, {V(uint(0x110001)), V(string("\uFFFD"))}, {V(uint32(0x110002)), V(string("\uFFFD"))}, {V(uint64(0x110003)), V(string("\uFFFD"))}, + {V(uint64(1 << 32)), V(string("\uFFFD"))}, {V(uintptr(0x110004)), V(string("\uFFFD"))}, // named string diff --git a/src/reflect/value.go b/src/reflect/value.go index bf926a7453..1f185b52e4 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -2681,12 +2681,20 @@ func cvtComplex(v Value, t Type) Value { // convertOp: intXX -> string func cvtIntString(v Value, t Type) Value { - return makeString(v.flag.ro(), string(rune(v.Int())), t) + s := "\uFFFD" + if x := v.Int(); int64(rune(x)) == x { + s = string(rune(x)) + } + return makeString(v.flag.ro(), s, t) } // convertOp: uintXX -> string func cvtUintString(v Value, t Type) Value { - return makeString(v.flag.ro(), string(rune(v.Uint())), t) + s := "\uFFFD" + if x := v.Uint(); uint64(rune(x)) == x { + s = string(rune(x)) + } + return makeString(v.flag.ro(), s, t) } // convertOp: []byte -> string From 926994fd7cf65b2703552686965fb05569699897 Mon Sep 17 00:00:00 2001 From: Rodolfo Carvalho Date: Thu, 26 Nov 2020 17:01:35 +0100 Subject: [PATCH 003/212] log: make Default doc comment consistent with package doc None of the other, older, doc comments use the '*Logger' form, and while 'Logger' and 'logger' are both used in the package doc comment, the common term used with the intended meaning is 'standard logger', which appears another eleven times in doc comments. Change-Id: I089103198fc82390517615eb27bbe7ef77107d34 Reviewed-on: https://go-review.googlesource.com/c/go/+/273486 Reviewed-by: Rob Pike Reviewed-by: Ian Lance Taylor Trust: Ian Lance Taylor --- src/log/log.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/log/log.go b/src/log/log.go index 8c0f83f0d1..b77af29032 100644 --- a/src/log/log.go +++ b/src/log/log.go @@ -75,7 +75,7 @@ func (l *Logger) SetOutput(w io.Writer) { var std = New(os.Stderr, "", LstdFlags) -// Default returns the *Logger used by the package-level output functions. +// Default returns the standard logger used by the package-level output functions. func Default() *Logger { return std } // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding. From 91f77ca2f8590ed2051ee9a62d52676cf1bff98d Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 27 Nov 2020 20:45:15 +0100 Subject: [PATCH 004/212] runtime: return 0 from C function in test This function's prototype includes a return value, so return a value. Otherwise clang gets upset: --- FAIL: TestDLLPreloadMitigation (1.40s) syscall_windows_test.go:986: failed to build dll: exit status 1 - nojack.c:7:1: error: non-void function does not return a value [-Werror,-Wreturn-type] } ^ 1 error generated. Fixes #42860. Change-Id: I65b8eb9ccb502692c5b65bd34829f331cd86eef0 Reviewed-on: https://go-review.googlesource.com/c/go/+/273726 Trust: Jason A. Donenfeld Trust: Brad Fitzpatrick Reviewed-by: Brad Fitzpatrick --- src/runtime/syscall_windows_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go index 3827c6ed83..a20573eb6a 100644 --- a/src/runtime/syscall_windows_test.go +++ b/src/runtime/syscall_windows_test.go @@ -969,8 +969,9 @@ func TestDLLPreloadMitigation(t *testing.T) { #include #include -uintptr_t cfunc() { +uintptr_t cfunc(void) { SetLastError(123); + return 0; } ` srcname := "nojack.c" From 0252cfd84d6268985199f96239e65a0b0d32363c Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 27 Nov 2020 22:07:23 +0100 Subject: [PATCH 005/212] runtime: adjust address calculation in identifying abort on windows/arm Apparently we're being called on arm 1 byte off, just like on 386 and amd64, so unify the handler for isAbortPC. Fixes #42859. Updates #29050. Change-Id: I97fffeb4a33d93ca3397ce1c9ba2b05137f391ca Reviewed-on: https://go-review.googlesource.com/c/go/+/273727 Run-TryBot: Jason A. Donenfeld Reviewed-by: Alex Brainman Trust: Alex Brainman Trust: Jason A. Donenfeld --- src/runtime/signal_windows.go | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go index 6d98d02598..3af2e39b08 100644 --- a/src/runtime/signal_windows.go +++ b/src/runtime/signal_windows.go @@ -43,16 +43,9 @@ func initExceptionHandler() { // //go:nosplit func isAbort(r *context) bool { - switch GOARCH { - case "386", "amd64": - // In the case of an abort, the exception IP is one byte after - // the INT3 (this differs from UNIX OSes). - return isAbortPC(r.ip() - 1) - case "arm": - return isAbortPC(r.ip()) - default: - return false - } + // In the case of an abort, the exception IP is one byte after + // the INT3 (this differs from UNIX OSes). + return isAbortPC(r.ip() - 1) } // isgoexception reports whether this exception should be translated From cb84d831c956026f477b52c9f8a7c1ed2b2724ad Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 26 Nov 2020 22:38:45 +0100 Subject: [PATCH 006/212] cmd/link: mark windows/arm as all PIE If the linker thinks that it's in exe mode instead of pie mode, it won't emit relocations when generating the pcln table, and we wind up with crashes like this on windows/arm, where all binaries are in fact relocated: Building Go toolchain2 using go_bootstrap and Go toolchain1. fatal error: minpc or maxpc invalid runtime: panic before malloc heap initialized This problem was already solved by darwin/arm64, so solve it the same way here for windows/arm. Fixes CL 228478. Fixes #42786. Change-Id: I6d1db6907c131183649fc263ccca06783188f344 Reviewed-on: https://go-review.googlesource.com/c/go/+/273566 Run-TryBot: Jason A. Donenfeld Reviewed-by: Alex Brainman Trust: Alex Brainman Trust: Jason A. Donenfeld --- src/cmd/link/internal/ld/config.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 0cb3cc25c0..d1e06239a5 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -35,11 +35,12 @@ func (mode *BuildMode) Set(s string) error { default: return fmt.Errorf("invalid buildmode: %q", s) case "exe": - if objabi.GOOS == "darwin" && objabi.GOARCH == "arm64" { - *mode = BuildModePIE // On darwin/arm64 everything is PIE. - break + switch objabi.GOOS + "/" + objabi.GOARCH { + case "darwin/arm64", "windows/arm": // On these platforms, everything is PIE + *mode = BuildModePIE + default: + *mode = BuildModeExe } - *mode = BuildModeExe case "pie": switch objabi.GOOS { case "aix", "android", "linux", "windows", "darwin", "ios": From b94346e69bb01e1cd522ddfa9d09f41d9d4d3e98 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 26 Nov 2020 12:26:02 -0800 Subject: [PATCH 007/212] test: match gofrontend error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These changes match the following gofrontend error messages: blank1.go:16:1: error: may not define methods on non-local type chan/perm.go:28:9: error: expected channel chan/perm.go:29:11: error: left operand of ‘<-’ must be channel chan/perm.go:69:9: error: argument must be channel complit1.go:25:16: error: attempt to slice object that is not array, slice, or string complit1.go:26:16: error: attempt to slice object that is not array, slice, or string complit1.go:27:17: error: attempt to slice object that is not array, slice, or string complit1.go:49:41: error: may only omit types within composite literals of slice, array, or map type complit1.go:50:14: error: expected struct, slice, array, or map type for composite literal convlit.go:24:9: error: invalid type conversion (cannot use type unsafe.Pointer as type string) convlit.go:25:9: error: invalid type conversion (cannot use type unsafe.Pointer as type float64) convlit.go:26:9: error: invalid type conversion (cannot use type unsafe.Pointer as type int) ddd1.go:63:9: error: invalid use of ‘...’ calling non-variadic function fixedbugs/bug176.go:12:18: error: index expression is not integer constant fixedbugs/bug332.go:17:10: error: use of undefined type ‘T’ fixedbugs/issue4232.go:22:16: error: integer constant overflow fixedbugs/issue4232.go:33:16: error: integer constant overflow fixedbugs/issue4232.go:44:25: error: integer constant overflow fixedbugs/issue4232.go:55:16: error: integer constant overflow fixedbugs/issue4458.go:19:14: error: type has no method ‘foo’ fixedbugs/issue5172.go:24:14: error: too many expressions for struct init.go:17:9: error: reference to undefined name ‘runtime’ initializerr.go:26:29: error: duplicate value for index 1 interface/explicit.go:60:14: error: type assertion only valid for interface types label.go:64:9: error: reference to undefined label ‘go2’ label1.go:18:97: error: continue statement not within for label1.go:22:97: error: continue statement not within for label1.go:106:89: error: continue statement not within for label1.go:108:26: error: invalid continue label ‘on’ label1.go:111:118: error: break statement not within for or switch or select label1.go:113:23: error: invalid break label ‘dance’ map1.go:64:9: error: not enough arguments map1.go:65:9: error: not enough arguments map1.go:67:9: error: argument 1 must be a map method2.go:36:11: error: reference to undefined field or method ‘val’ method2.go:37:11: error: reference to undefined field or method ‘val’ method2.go:41:12: error: method requires pointer (use ‘(*T).g’) syntax/chan1.go:13:19: error: send statement used as value; use select for non-blocking send syntax/chan1.go:17:11: error: send statement used as value; use select for non-blocking send Change-Id: I98047b60a376e3d2788836300f7fcac3f2c285cb Reviewed-on: https://go-review.googlesource.com/c/go/+/273527 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- test/blank1.go | 2 +- test/chan/perm.go | 6 +++--- test/complit1.go | 10 +++++----- test/convlit.go | 6 +++--- test/ddd1.go | 2 +- test/fixedbugs/bug176.go | 2 +- test/fixedbugs/bug332.go | 2 +- test/fixedbugs/issue4232.go | 8 ++++---- test/fixedbugs/issue4458.go | 2 +- test/fixedbugs/issue5172.go | 2 +- test/init.go | 2 +- test/initializerr.go | 2 +- test/interface/explicit.go | 2 +- test/label.go | 2 +- test/label1.go | 12 ++++++------ test/map1.go | 8 ++++---- test/method2.go | 6 +++--- test/syntax/chan1.go | 4 ++-- 18 files changed, 40 insertions(+), 40 deletions(-) diff --git a/test/blank1.go b/test/blank1.go index c9a8e6a290..70e01b1a30 100644 --- a/test/blank1.go +++ b/test/blank1.go @@ -13,7 +13,7 @@ var t struct { _ int } -func (x int) _() { // ERROR "cannot define new methods on non-local type" +func (x int) _() { // ERROR "methods on non-local type" println(x) } diff --git a/test/chan/perm.go b/test/chan/perm.go index 7da88bdae8..0c96d921d1 100644 --- a/test/chan/perm.go +++ b/test/chan/perm.go @@ -25,8 +25,8 @@ func main() { cs = cr // ERROR "illegal types|incompatible|cannot" var n int - <-n // ERROR "receive from non-chan" - n <- 2 // ERROR "send to non-chan" + <-n // ERROR "receive from non-chan|expected channel" + n <- 2 // ERROR "send to non-chan|must be channel" c <- 0 // ok <-c // ok @@ -66,5 +66,5 @@ func main() { close(c) close(cs) close(cr) // ERROR "receive" - close(n) // ERROR "invalid operation.*non-chan type" + close(n) // ERROR "invalid operation.*non-chan type|must be channel" } diff --git a/test/complit1.go b/test/complit1.go index eb0f920fcb..7c2a4e2996 100644 --- a/test/complit1.go +++ b/test/complit1.go @@ -22,9 +22,9 @@ var ( _ = m[0][:] // ERROR "slice of unaddressable value" _ = f()[:] // ERROR "slice of unaddressable value" - _ = 301[:] // ERROR "cannot slice" - _ = 3.1[:] // ERROR "cannot slice" - _ = true[:] // ERROR "cannot slice" + _ = 301[:] // ERROR "cannot slice|attempt to slice object that is not" + _ = 3.1[:] // ERROR "cannot slice|attempt to slice object that is not" + _ = true[:] // ERROR "cannot slice|attempt to slice object that is not" // these are okay because they are slicing a pointer to an array _ = (&[3]int{1, 2, 3})[:] @@ -46,8 +46,8 @@ var ( _ = &T{0, 0, "", nil} // ok _ = &T{i: 0, f: 0, s: "", next: {}} // ERROR "missing type in composite literal|omit types within composite literal" _ = &T{0, 0, "", {}} // ERROR "missing type in composite literal|omit types within composite literal" - _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid composite literal type TP" - _ = &Ti{} // ERROR "invalid composite literal type Ti" + _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid composite literal type TP|omit types within composite literal" + _ = &Ti{} // ERROR "invalid composite literal type Ti|expected.*type for composite literal" ) type M map[T]T diff --git a/test/convlit.go b/test/convlit.go index de760542da..1c66c89e88 100644 --- a/test/convlit.go +++ b/test/convlit.go @@ -21,9 +21,9 @@ var x6 = int(1e100) // ERROR "overflow" var x7 = float32(1e1000) // ERROR "overflow" // unsafe.Pointer can only convert to/from uintptr -var _ = string(unsafe.Pointer(uintptr(65))) // ERROR "convert" -var _ = float64(unsafe.Pointer(uintptr(65))) // ERROR "convert" -var _ = int(unsafe.Pointer(uintptr(65))) // ERROR "convert" +var _ = string(unsafe.Pointer(uintptr(65))) // ERROR "convert|conversion" +var _ = float64(unsafe.Pointer(uintptr(65))) // ERROR "convert|conversion" +var _ = int(unsafe.Pointer(uintptr(65))) // ERROR "convert|conversion" // implicit conversions merit scrutiny var s string diff --git a/test/ddd1.go b/test/ddd1.go index 9857814648..01b9c0eadb 100644 --- a/test/ddd1.go +++ b/test/ddd1.go @@ -60,5 +60,5 @@ func bad(args ...int) { _ = [...]byte("foo") // ERROR "[.][.][.]" _ = [...][...]int{{1,2,3},{4,5,6}} // ERROR "[.][.][.]" - Foo(x...) // ERROR "invalid use of [.][.][.] in call" + Foo(x...) // ERROR "invalid use of .*[.][.][.]" } diff --git a/test/fixedbugs/bug176.go b/test/fixedbugs/bug176.go index ea3a909747..7001dd081e 100644 --- a/test/fixedbugs/bug176.go +++ b/test/fixedbugs/bug176.go @@ -9,6 +9,6 @@ package main var x int var a = []int{ x: 1} // ERROR "constant" -var b = [...]int{x: 1} +var b = [...]int{x: 1} // GCCGO_ERROR "constant" var c = map[int]int{ x: 1} diff --git a/test/fixedbugs/bug332.go b/test/fixedbugs/bug332.go index d43c2ddcff..159c8b4e68 100644 --- a/test/fixedbugs/bug332.go +++ b/test/fixedbugs/bug332.go @@ -14,4 +14,4 @@ func main() {} // important: no newline on end of next line. // 6g used to print instead of bug332.go:111 -func (t *T) F() {} // ERROR "undefined: T" \ No newline at end of file +func (t *T) F() {} // ERROR "undefined.*T" \ No newline at end of file diff --git a/test/fixedbugs/issue4232.go b/test/fixedbugs/issue4232.go index 935f3820c6..30d132683a 100644 --- a/test/fixedbugs/issue4232.go +++ b/test/fixedbugs/issue4232.go @@ -19,7 +19,7 @@ func f() { _ = a[10:10] _ = a[9:12] // ERROR "invalid slice index 12|index out of bounds" _ = a[11:12] // ERROR "invalid slice index 11|index out of bounds" - _ = a[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds" + _ = a[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds" var s []int _ = s[-1] // ERROR "invalid slice index -1|index out of bounds" @@ -30,7 +30,7 @@ func f() { _ = s[10:10] _ = s[9:12] _ = s[11:12] - _ = s[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds" + _ = s[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds" const c = "foofoofoof" _ = c[-1] // ERROR "invalid string index -1|index out of bounds" @@ -41,7 +41,7 @@ func f() { _ = c[10:10] _ = c[9:12] // ERROR "invalid slice index 12|index out of bounds" _ = c[11:12] // ERROR "invalid slice index 11|index out of bounds" - _ = c[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds" + _ = c[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds" var t string _ = t[-1] // ERROR "invalid string index -1|index out of bounds" @@ -52,5 +52,5 @@ func f() { _ = t[10:10] _ = t[9:12] _ = t[11:12] - _ = t[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds" + _ = t[1<<100 : 1<<110] // ERROR "overflows int|integer constant overflow" "invalid slice index 1 << 100|index out of bounds" } diff --git a/test/fixedbugs/issue4458.go b/test/fixedbugs/issue4458.go index 98ffea79dc..59cfa9fcee 100644 --- a/test/fixedbugs/issue4458.go +++ b/test/fixedbugs/issue4458.go @@ -16,5 +16,5 @@ func (T) foo() {} func main() { av := T{} pav := &av - (**T).foo(&pav) // ERROR "no method foo|requires named type or pointer to named" + (**T).foo(&pav) // ERROR "no method .*foo|requires named type or pointer to named" } diff --git a/test/fixedbugs/issue5172.go b/test/fixedbugs/issue5172.go index 0339935b64..ed92ac6ff2 100644 --- a/test/fixedbugs/issue5172.go +++ b/test/fixedbugs/issue5172.go @@ -21,6 +21,6 @@ func main() { go f.bar() // ERROR "undefined" defer f.bar() // ERROR "undefined" - t := T{1} // ERROR "too many values" + t := T{1} // ERROR "too many" go t.Bar() } diff --git a/test/init.go b/test/init.go index 317f2472cb..5e182281da 100644 --- a/test/init.go +++ b/test/init.go @@ -14,6 +14,6 @@ func init() { func main() { init() // ERROR "undefined.*init" - runtime.init() // ERROR "undefined.*runtime\.init" + runtime.init() // ERROR "undefined.*runtime\.init|reference to undefined name" var _ = init // ERROR "undefined.*init" } diff --git a/test/initializerr.go b/test/initializerr.go index 990ab60f96..5e2e9a91a0 100644 --- a/test/initializerr.go +++ b/test/initializerr.go @@ -23,7 +23,7 @@ var a2 = S { Y: 3, Z: 2, Y: 3 } // ERROR "duplicate" var a3 = T { S{}, 2, 3, 4, 5, 6 } // ERROR "convert|too many" var a4 = [5]byte{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } // ERROR "index|too many" var a5 = []byte { x: 2 } // ERROR "index" -var a6 = []byte{1: 1, 2: 2, 1: 3} // ERROR "duplicate index" +var a6 = []byte{1: 1, 2: 2, 1: 3} // ERROR "duplicate" var ok1 = S { } // should be ok var ok2 = T { S: ok1 } // should be ok diff --git a/test/interface/explicit.go b/test/interface/explicit.go index 1fb3b6a05a..3f9451e8d2 100644 --- a/test/interface/explicit.go +++ b/test/interface/explicit.go @@ -57,7 +57,7 @@ func main() { // cannot type-assert non-interfaces f := 2.0 - _ = f.(int) // ERROR "non-interface type" + _ = f.(int) // ERROR "non-interface type|only valid for interface types" } diff --git a/test/label.go b/test/label.go index 11716cc2c5..7deead6fba 100644 --- a/test/label.go +++ b/test/label.go @@ -61,5 +61,5 @@ L10: goto L10 - goto go2 // ERROR "label go2 not defined" + goto go2 // ERROR "label go2 not defined|reference to undefined label .*go2" } diff --git a/test/label1.go b/test/label1.go index b2e0ef09b8..a8eaecbff2 100644 --- a/test/label1.go +++ b/test/label1.go @@ -15,11 +15,11 @@ var x int func f1() { switch x { case 1: - continue // ERROR "continue is not in a loop$" + continue // ERROR "continue is not in a loop$|continue statement not within for" } select { default: - continue // ERROR "continue is not in a loop$" + continue // ERROR "continue is not in a loop$|continue statement not within for" } } @@ -103,14 +103,14 @@ L5: } } - continue // ERROR "continue is not in a loop$" + continue // ERROR "continue is not in a loop$|continue statement not within for" for { - continue on // ERROR "continue label not defined: on" + continue on // ERROR "continue label not defined: on|invalid continue label .*on" } - break // ERROR "break is not in a loop, switch, or select" + break // ERROR "break is not in a loop, switch, or select|break statement not within for or switch or select" for { - break dance // ERROR "break label not defined: dance" + break dance // ERROR "break label not defined: dance|invalid break label .*dance" } for { diff --git a/test/map1.go b/test/map1.go index 498c2ec45b..b4aa70755f 100644 --- a/test/map1.go +++ b/test/map1.go @@ -61,8 +61,8 @@ type T8 struct { F *T7 } func main() { m := make(map[int]int) - delete() // ERROR "missing arguments" - delete(m) // ERROR "missing second \(key\) argument" + delete() // ERROR "missing arguments|not enough arguments" + delete(m) // ERROR "missing second \(key\) argument|not enough arguments" delete(m, 2, 3) // ERROR "too many arguments" - delete(1, m) // ERROR "first argument to delete must be map" -} \ No newline at end of file + delete(1, m) // ERROR "first argument to delete must be map|argument 1 must be a map" +} diff --git a/test/method2.go b/test/method2.go index a45a943156..7feb675055 100644 --- a/test/method2.go +++ b/test/method2.go @@ -33,9 +33,9 @@ var _ = (*Val).val // ERROR "method" var v Val var pv = &v -var _ = pv.val() // ERROR "pv.val undefined" -var _ = pv.val // ERROR "pv.val undefined" +var _ = pv.val() // ERROR "undefined" +var _ = pv.val // ERROR "undefined" func (t *T) g() int { return t.a } -var _ = (T).g() // ERROR "needs pointer receiver|undefined" +var _ = (T).g() // ERROR "needs pointer receiver|undefined|method requires pointer" diff --git a/test/syntax/chan1.go b/test/syntax/chan1.go index 56103d1d79..88a5b4777b 100644 --- a/test/syntax/chan1.go +++ b/test/syntax/chan1.go @@ -10,8 +10,8 @@ var c chan int var v int func main() { - if c <- v { // ERROR "cannot use c <- v as value" + if c <- v { // ERROR "cannot use c <- v as value|send statement used as value" } } -var _ = c <- v // ERROR "unexpected <-" +var _ = c <- v // ERROR "unexpected <-|send statement used as value" From 358d35455d06b1ebee948efff123842490dcb797 Mon Sep 17 00:00:00 2001 From: smasher164 Date: Thu, 26 Nov 2020 14:16:33 -0500 Subject: [PATCH 008/212] bufio: make string(int) conversion safer Updates #42792. Change-Id: I7e53426c41e5609d9dadceb300f7983ba7ad6577 Reviewed-on: https://go-review.googlesource.com/c/go/+/273526 Run-TryBot: Akhil Indurti TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer --- src/bufio/bufio_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go index 75086f1f24..d7b34bd0d8 100644 --- a/src/bufio/bufio_test.go +++ b/src/bufio/bufio_test.go @@ -146,7 +146,7 @@ func TestReader(t *testing.T) { for i := 0; i < len(texts)-1; i++ { texts[i] = str + "\n" all += texts[i] - str += string(rune(i)%26 + 'a') + str += string(rune(i%26 + 'a')) } texts[len(texts)-1] = all From 4ce0a7cea6805277c3bfecbaab2170e5c2543cba Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 28 Nov 2020 14:38:29 +0100 Subject: [PATCH 009/212] runtime/pprof: ignore test failures on windows/arm This is blocking forward progress of the de-bitrotting work, and I don't know off hand how to fix this. Seeing as its disabled on other platforms, I suspect pprof might not be a very reliable feature, so just allow for the tests to fail for now, until somebody more motivated comes along to fix it. Updates #42862. Change-Id: Ibc5cd1d82d97b9c2f887d7f3565f2fa70207c8b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/273826 Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick Trust: Jason A. Donenfeld --- src/runtime/pprof/pprof_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 43307aeab9..b807072485 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -286,6 +286,10 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { broken = true } + case "windows": + if runtime.GOARCH == "arm" { + broken = true // See https://golang.org/issues/42862 + } } maxDuration := 5 * time.Second From e5da18df52e3f81534d7cdb6920cf993b5f079d2 Mon Sep 17 00:00:00 2001 From: "Joshua M. Clulow" Date: Sun, 29 Nov 2020 17:18:51 -0800 Subject: [PATCH 010/212] os/exec: constrain thread usage in leaked descriptor test on illumos On illumos systems, libc can under some conditions make use of files from /proc. In the case of this test, the creation of new threads was (in the target thread) causing libc to open and close "/proc/self/lwp/5/lwpname" to set the thread name, which raced with the leaking descriptor check (see detailed analysis in #42431). This change requests that the Go runtime use less threads in the child process used to check for leaked descriptors, without just disabling the test. After a thousand repeated trials, the test no longer fails on illumos. Fixes #42431. Change-Id: Iefda26134fc91f7cb205754676e9845d9b7205cc Reviewed-on: https://go-review.googlesource.com/c/go/+/273966 Reviewed-by: Brad Fitzpatrick Reviewed-by: Ian Lance Taylor Trust: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot --- src/os/exec/exec_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index cd3d759ebc..fc49b8a332 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -691,6 +691,18 @@ func TestExtraFiles(t *testing.T) { c.Stdout = &stdout c.Stderr = &stderr c.ExtraFiles = []*os.File{tf} + if runtime.GOOS == "illumos" { + // Some facilities in illumos are implemented via access + // to /proc by libc; such accesses can briefly occupy a + // low-numbered fd. If this occurs concurrently with the + // test that checks for leaked descriptors, the check can + // become confused and report a spurious leaked descriptor. + // (See issue #42431 for more detailed analysis.) + // + // Attempt to constrain the use of additional threads in the + // child process to make this test less flaky: + c.Env = append(os.Environ(), "GOMAXPROCS=1") + } err = c.Run() if err != nil { t.Fatalf("Run: %v\n--- stdout:\n%s--- stderr:\n%s", err, stdout.Bytes(), stderr.Bytes()) From 294c214ccac877be8d8ce16b0302434a15a2476b Mon Sep 17 00:00:00 2001 From: KimMachineGun Date: Fri, 20 Nov 2020 08:32:06 +0000 Subject: [PATCH 011/212] runtime: gofmt CL 268578 was not formatted properly. Change-Id: I08d2fc691e4f90a38d8165344c135b7b4f73b339 GitHub-Last-Rev: 6183bb063962ef4bf5a6050c1f5108976108ff42 GitHub-Pull-Request: golang/go#42736 Reviewed-on: https://go-review.googlesource.com/c/go/+/271807 Reviewed-by: Alberto Donizetti Reviewed-by: Michael Pratt Trust: Michael Pratt Trust: Alberto Donizetti Run-TryBot: Michael Pratt --- src/runtime/crash_unix_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index c50d62d552..ebbdbfe5b9 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -244,7 +244,7 @@ func TestPanicSystemstack(t *testing.T) { // we don't have a way to know when it is fully blocked, sleep a bit to // make us less likely to lose the race and signal before the child // blocks. - time.Sleep(100*time.Millisecond) + time.Sleep(100 * time.Millisecond) // Send SIGQUIT. if err := cmd.Process.Signal(syscall.SIGQUIT); err != nil { From c193279e2c9e62e8ddc0893484251b4411461d62 Mon Sep 17 00:00:00 2001 From: Chris Waldon Date: Sun, 29 Nov 2020 23:58:29 +0000 Subject: [PATCH 012/212] os: return proper user directories on iOS Separating iOS into its own runtime constant broke the logic here to derive the correct home, cache, and config directories on iOS devices. Fixes #42878 Change-Id: Ie4ff57895fcc34b0a9af45554ea3a346447d2e7a GitHub-Last-Rev: 5e74e64917fa46e9c6e0d963cab5194ab89e2f64 GitHub-Pull-Request: golang/go#42879 Reviewed-on: https://go-review.googlesource.com/c/go/+/273947 Reviewed-by: Cherry Zhang Trust: Emmanuel Odeke --- src/os/file.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/os/file.go b/src/os/file.go index 835d44ab8c..420e62ef2c 100644 --- a/src/os/file.go +++ b/src/os/file.go @@ -406,7 +406,7 @@ func UserCacheDir() (string, error) { return "", errors.New("%LocalAppData% is not defined") } - case "darwin": + case "darwin", "ios": dir = Getenv("HOME") if dir == "" { return "", errors.New("$HOME is not defined") @@ -457,7 +457,7 @@ func UserConfigDir() (string, error) { return "", errors.New("%AppData% is not defined") } - case "darwin": + case "darwin", "ios": dir = Getenv("HOME") if dir == "" { return "", errors.New("$HOME is not defined") @@ -505,10 +505,8 @@ func UserHomeDir() (string, error) { switch runtime.GOOS { case "android": return "/sdcard", nil - case "darwin": - if runtime.GOARCH == "arm64" { - return "/", nil - } + case "ios": + return "/", nil } return "", errors.New(enverr + " is not defined") } From 65f4ec2faec54b7a3e70f2404132df9d83df11e0 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 27 Nov 2020 23:52:37 -0500 Subject: [PATCH 013/212] [dev.regabi] cmd/compile: cleanup label handling - The use of a label's Name.Defn to point at the named for/select/switch means that any rewrite of the for/select/switch must overwrite the original or else the pointer will dangle. Remove that pointer by adding the label name directly to the for/select/switch representation instead. - The only uses of a label's Sym.Label were ephemeral values during markbreak and escape analysis. Use a map for each. Although in general we are not going to replace all computed fields with maps (too slow), the one in markbreak is only for labeled for/select/switch, and the one in escape is for all labels, but even so, labels are fairly rare. In theory this cleanup should make it easy to allow labeled for/select/switch in inlined bodies, but this CL does not attempt that. It's only concerned with cleanup to enable a new Node representation. Passes buildall w/ toolstash -cmp. Change-Id: I7e36ee98d2ea40dbae94e6722d585f007b7afcfa Reviewed-on: https://go-review.googlesource.com/c/go/+/274086 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/escape.go | 28 +++++++---- src/cmd/compile/internal/gc/inl.go | 8 ++-- src/cmd/compile/internal/gc/noder.go | 9 +++- src/cmd/compile/internal/gc/ssa.go | 21 ++++----- src/cmd/compile/internal/gc/subr.go | 17 ------- src/cmd/compile/internal/gc/typecheck.go | 47 ++++++++----------- src/cmd/compile/internal/types/sizeof_test.go | 2 +- src/cmd/compile/internal/types/sym.go | 5 +- 8 files changed, 60 insertions(+), 77 deletions(-) diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 783bc8c41d..34f52c743a 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -85,6 +85,7 @@ import ( type Escape struct { allLocs []*EscLocation + labels map[*types.Sym]labelState // known labels curfn ir.Node @@ -229,13 +230,16 @@ func (e *Escape) walkFunc(fn ir.Node) { ir.InspectList(fn.Body(), func(n ir.Node) bool { switch n.Op() { case ir.OLABEL: - n.Sym().Label = nonlooping + if e.labels == nil { + e.labels = make(map[*types.Sym]labelState) + } + e.labels[n.Sym()] = nonlooping case ir.OGOTO: // If we visited the label before the goto, // then this is a looping label. - if n.Sym().Label == nonlooping { - n.Sym().Label = looping + if e.labels[n.Sym()] == nonlooping { + e.labels[n.Sym()] = looping } } @@ -245,6 +249,10 @@ func (e *Escape) walkFunc(fn ir.Node) { e.curfn = fn e.loopDepth = 1 e.block(fn.Body()) + + if len(e.labels) != 0 { + base.FatalfAt(fn.Pos(), "leftover labels after walkFunc") + } } // Below we implement the methods for walking the AST and recording @@ -310,7 +318,7 @@ func (e *Escape) stmt(n ir.Node) { } case ir.OLABEL: - switch ir.AsNode(n.Sym().Label) { + switch e.labels[n.Sym()] { case nonlooping: if base.Flag.LowerM > 2 { fmt.Printf("%v:%v non-looping label\n", base.FmtPos(base.Pos), n) @@ -323,7 +331,7 @@ func (e *Escape) stmt(n ir.Node) { default: base.Fatalf("label missing tag") } - n.Sym().Label = nil + delete(e.labels, n.Sym()) case ir.OIF: e.discard(n.Left()) @@ -1615,11 +1623,11 @@ func funcSym(fn ir.Node) *types.Sym { } // Mark labels that have no backjumps to them as not increasing e.loopdepth. -// Walk hasn't generated (goto|label).Left.Sym.Label yet, so we'll cheat -// and set it to one of the following two. Then in esc we'll clear it again. -var ( - looping = ir.Nod(ir.OXXX, nil, nil) - nonlooping = ir.Nod(ir.OXXX, nil, nil) +type labelState int + +const ( + looping labelState = 1 + iota + nonlooping ) func isSliceSelfAssign(dst, src ir.Node) bool { diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 6310762c1f..d43d0d06af 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -405,16 +405,16 @@ func (v *hairyVisitor) visit(n ir.Node) bool { // These nodes don't produce code; omit from inlining budget. return false - case ir.OLABEL: - // TODO(mdempsky): Add support for inlining labeled control statements. - if labeledControl(n) != nil { + case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH: + // ORANGE, OSELECT in "unhandled" above + if n.Sym() != nil { v.reason = "labeled control" return true } case ir.OBREAK, ir.OCONTINUE: if n.Sym() != nil { - // Should have short-circuited due to labeledControl above. + // Should have short-circuited due to labeled control error above. base.Fatalf("unexpected labeled break/continue: %v", n) } diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 950d509047..ecd50b87f6 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -1302,14 +1302,19 @@ func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []i } func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node { - lhs := p.nodSym(label, ir.OLABEL, nil, p.name(label.Label)) + sym := p.name(label.Label) + lhs := p.nodSym(label, ir.OLABEL, nil, sym) var ls ir.Node if label.Stmt != nil { // TODO(mdempsky): Should always be present. ls = p.stmtFall(label.Stmt, fallOK) + switch label.Stmt.(type) { + case *syntax.ForStmt, *syntax.SwitchStmt, *syntax.SelectStmt: + // Attach label directly to control statement too. + ls.SetSym(sym) + } } - lhs.Name().Defn = ls l := []ir.Node{lhs} if ls != nil { if ls.Op() == ir.OBLOCK && ls.Init().Len() == 0 { diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index cb73532b48..bcc126f82e 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -356,7 +356,6 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { // Allocate starting values s.labels = map[string]*ssaLabel{} - s.labeledNodes = map[ir.Node]*ssaLabel{} s.fwdVars = map[ir.Node]*ssa.Value{} s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem) @@ -596,9 +595,8 @@ type state struct { // Node for function curfn ir.Node - // labels and labeled control flow nodes (OFOR, OFORUNTIL, OSWITCH, OSELECT) in f - labels map[string]*ssaLabel - labeledNodes map[ir.Node]*ssaLabel + // labels in f + labels map[string]*ssaLabel // unlabeled break and continue statement tracking breakTo *ssa.Block // current target for plain break statement @@ -1169,11 +1167,6 @@ func (s *state) stmt(n ir.Node) { sym := n.Sym() lab := s.label(sym) - // Associate label with its control flow node, if any - if ctl := labeledControl(n); ctl != nil { - s.labeledNodes[ctl] = lab - } - // The label might already have a target block via a goto. if lab.target == nil { lab.target = s.f.NewBlock(ssa.BlockPlain) @@ -1431,9 +1424,10 @@ func (s *state) stmt(n ir.Node) { prevBreak := s.breakTo s.continueTo = bIncr s.breakTo = bEnd - lab := s.labeledNodes[n] - if lab != nil { + var lab *ssaLabel + if sym := n.Sym(); sym != nil { // labeled for loop + lab = s.label(sym) lab.continueTarget = bIncr lab.breakTarget = bEnd } @@ -1489,9 +1483,10 @@ func (s *state) stmt(n ir.Node) { prevBreak := s.breakTo s.breakTo = bEnd - lab := s.labeledNodes[n] - if lab != nil { + var lab *ssaLabel + if sym := n.Sym(); sym != nil { // labeled + lab = s.label(sym) lab.breakTarget = bEnd } diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index fcda219737..d174ebd582 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -582,23 +582,6 @@ func backingArrayPtrLen(n ir.Node) (ptr, len ir.Node) { return ptr, len } -// labeledControl returns the control flow Node (for, switch, select) -// associated with the label n, if any. -func labeledControl(n ir.Node) ir.Node { - if n.Op() != ir.OLABEL { - base.Fatalf("labeledControl %v", n.Op()) - } - ctl := n.Name().Defn - if ctl == nil { - return nil - } - switch ctl.Op() { - case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OSELECT: - return ctl - } - return nil -} - func syslook(name string) ir.Node { s := Runtimepkg.Lookup(name) if s == nil || s.Def == nil { diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 4e2f205312..ede3778184 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3759,7 +3759,7 @@ func checkmake(t *types.Type, arg string, np *ir.Node) bool { return true } -func markbreak(n ir.Node, implicit ir.Node) { +func markbreak(labels *map[*types.Sym]ir.Node, n ir.Node, implicit ir.Node) { if n == nil { return } @@ -3771,43 +3771,35 @@ func markbreak(n ir.Node, implicit ir.Node) { implicit.SetHasBreak(true) } } else { - lab := ir.AsNode(n.Sym().Label) - if lab != nil { + if lab := (*labels)[n.Sym()]; lab != nil { lab.SetHasBreak(true) } } case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OTYPESW, ir.OSELECT, ir.ORANGE: implicit = n + if sym := n.Sym(); sym != nil { + if *labels == nil { + // Map creation delayed until we need it - most functions don't. + *labels = make(map[*types.Sym]ir.Node) + } + (*labels)[sym] = n + defer delete(*labels, sym) + } fallthrough default: - markbreak(n.Left(), implicit) - markbreak(n.Right(), implicit) - markbreaklist(n.Init(), implicit) - markbreaklist(n.Body(), implicit) - markbreaklist(n.List(), implicit) - markbreaklist(n.Rlist(), implicit) + markbreak(labels, n.Left(), implicit) + markbreak(labels, n.Right(), implicit) + markbreaklist(labels, n.Init(), implicit) + markbreaklist(labels, n.Body(), implicit) + markbreaklist(labels, n.List(), implicit) + markbreaklist(labels, n.Rlist(), implicit) } } -func markbreaklist(l ir.Nodes, implicit ir.Node) { +func markbreaklist(labels *map[*types.Sym]ir.Node, l ir.Nodes, implicit ir.Node) { s := l.Slice() for i := 0; i < len(s); i++ { - n := s[i] - if n == nil { - continue - } - if n.Op() == ir.OLABEL && i+1 < len(s) && n.Name().Defn == s[i+1] { - switch n.Name().Defn.Op() { - case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OTYPESW, ir.OSELECT, ir.ORANGE: - n.Sym().Label = n.Name().Defn - markbreak(n.Name().Defn, n.Name().Defn) - n.Sym().Label = nil - i++ - continue - } - } - - markbreak(n, implicit) + markbreak(labels, s[i], implicit) } } @@ -3874,7 +3866,8 @@ func isTermNode(n ir.Node) bool { // checkreturn makes sure that fn terminates appropriately. func checkreturn(fn ir.Node) { if fn.Type().NumResults() != 0 && fn.Body().Len() != 0 { - markbreaklist(fn.Body(), nil) + var labels map[*types.Sym]ir.Node + markbreaklist(&labels, fn.Body(), nil) if !isTermNodes(fn.Body()) { base.ErrorfAt(fn.Func().Endlineno, "missing return at end of function") } diff --git a/src/cmd/compile/internal/types/sizeof_test.go b/src/cmd/compile/internal/types/sizeof_test.go index 2821d9a3c7..88a2fbba2f 100644 --- a/src/cmd/compile/internal/types/sizeof_test.go +++ b/src/cmd/compile/internal/types/sizeof_test.go @@ -20,7 +20,7 @@ func TestSizeof(t *testing.T) { _32bit uintptr // size on 32bit platforms _64bit uintptr // size on 64bit platforms }{ - {Sym{}, 60, 104}, + {Sym{}, 52, 88}, {Type{}, 56, 96}, {Map{}, 20, 40}, {Forward{}, 20, 32}, diff --git a/src/cmd/compile/internal/types/sym.go b/src/cmd/compile/internal/types/sym.go index 046104d0dc..7272f1f786 100644 --- a/src/cmd/compile/internal/types/sym.go +++ b/src/cmd/compile/internal/types/sym.go @@ -33,13 +33,12 @@ type Sym struct { Name string // object name // saved and restored by dcopy - Def IRNode // definition: ONAME OTYPE OPACK or OLITERAL + Def IRNode // definition: ONAME OTYPE OPACK or OLITERAL Block int32 // blocknumber to catch redeclaration Lastlineno src.XPos // last declaration for diagnostic flags bitset8 - Label IRNode // corresponding label (ephemeral) - Origpkg *Pkg // original package for . import + Origpkg *Pkg // original package for . import } const ( From 0c65a2f31734021654ec5eebc270f8c84e5410c7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 00:05:15 -0500 Subject: [PATCH 014/212] [dev.regabi] cmd/compile: drop Node.HasOpt method Node.HasOpt is only used once, and that use can use Opt instead. Interface is one method smaller. Passes buildall w/ toolstash -cmp. Change-Id: I6a9d5859a9977a8f4c9db70e166f50f0d8052160 Reviewed-on: https://go-review.googlesource.com/c/go/+/274087 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/escape.go | 2 +- src/cmd/compile/internal/ir/node.go | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 34f52c743a..6b6fb44a99 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -1092,7 +1092,7 @@ func (e *Escape) newLoc(n ir.Node, transient bool) *EscLocation { base.Fatalf("curfn mismatch: %v != %v", n.Name().Curfn, e.curfn) } - if n.HasOpt() { + if n.Opt() != nil { base.Fatalf("%v already has a location", n) } n.SetOpt(loc) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 477d07f502..acfddd2dc7 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -111,7 +111,6 @@ type Node interface { SetWalkdef(x uint8) Opt() interface{} SetOpt(x interface{}) - HasOpt() bool Diag() bool SetDiag(x bool) Bounded() bool @@ -325,7 +324,7 @@ func (n *node) Bounded() bool { return n.flags&nodeBounded != 0 } func (n *node) HasCall() bool { return n.flags&nodeHasCall != 0 } func (n *node) Likely() bool { return n.flags&nodeLikely != 0 } func (n *node) HasVal() bool { return n.flags&nodeHasVal != 0 } -func (n *node) HasOpt() bool { return n.flags&nodeHasOpt != 0 } +func (n *node) hasOpt() bool { return n.flags&nodeHasOpt != 0 } func (n *node) Embedded() bool { return n.flags&nodeEmbedded != 0 } func (n *node) SetClass(b Class) { n.flags.set3(nodeClass, uint8(b)) } @@ -399,7 +398,7 @@ func (n *node) Val() constant.Value { // SetVal sets the constant.Value for the node, // which must not have been used with SetOpt. func (n *node) SetVal(v constant.Value) { - if n.HasOpt() { + if n.hasOpt() { base.Flag.LowerH = 1 Dump("have Opt", n) base.Fatalf("have Opt") @@ -413,7 +412,7 @@ func (n *node) SetVal(v constant.Value) { // Opt returns the optimizer data for the node. func (n *node) Opt() interface{} { - if !n.HasOpt() { + if !n.hasOpt() { return nil } return n.e @@ -423,7 +422,7 @@ func (n *node) Opt() interface{} { // SetOpt(nil) is ignored for Vals to simplify call sites that are clearing Opts. func (n *node) SetOpt(x interface{}) { if x == nil { - if n.HasOpt() { + if n.hasOpt() { n.setHasOpt(false) n.e = nil } From 79a3d5ce158de1696256d58aa563ca7cd30f6c3f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 00:14:38 -0500 Subject: [PATCH 015/212] [dev.regabi] cmd/compile: setup for new Node implementations Start a list of which ops are valid for the default node struct implementation (currently all of them). Add a Node implementation helper for a minimal node. Passes buildall w/ toolstash -cmp. Change-Id: I7ae45f2cf2be85013cb71ab00524be53f243e13d Reviewed-on: https://go-review.googlesource.com/c/go/+/274088 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/typecheck.go | 4 +- src/cmd/compile/internal/ir/bitset.go | 12 ++ src/cmd/compile/internal/ir/mini.go | 188 ++++++++++++++++ src/cmd/compile/internal/ir/node.go | 260 +++++++++++++++++++---- 4 files changed, 424 insertions(+), 40 deletions(-) create mode 100644 src/cmd/compile/internal/ir/mini.go diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index ede3778184..9da464e1b6 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1694,8 +1694,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n } op, why := convertop(n.Left().Op() == ir.OLITERAL, t, n.Type()) - n.SetOp(op) - if n.Op() == ir.OXXX { + if op == ir.OXXX { if !n.Diag() && !n.Type().Broke() && !n.Left().Diag() { base.Errorf("cannot convert %L to type %v%s", n.Left(), n.Type(), why) n.SetDiag(true) @@ -1705,6 +1704,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n } + n.SetOp(op) switch n.Op() { case ir.OCONVNOP: if t.Etype == n.Type().Etype { diff --git a/src/cmd/compile/internal/ir/bitset.go b/src/cmd/compile/internal/ir/bitset.go index 29f136296f..0c7bd542f6 100644 --- a/src/cmd/compile/internal/ir/bitset.go +++ b/src/cmd/compile/internal/ir/bitset.go @@ -14,6 +14,18 @@ func (f *bitset8) set(mask uint8, b bool) { } } +func (f bitset8) get2(shift uint8) uint8 { + return uint8(f>>shift) & 3 +} + +// set2 sets two bits in f using the bottom two bits of b. +func (f *bitset8) set2(shift uint8, b uint8) { + // Clear old bits. + *(*uint8)(f) &^= 3 << shift + // Set new bits. + *(*uint8)(f) |= uint8(b&3) << shift +} + type bitset16 uint16 func (f *bitset16) set(mask uint16, b bool) { diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go new file mode 100644 index 0000000000..48dccf6a5f --- /dev/null +++ b/src/cmd/compile/internal/ir/mini.go @@ -0,0 +1,188 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ir + +import ( + "cmd/compile/internal/types" + "cmd/internal/src" + "fmt" + "go/constant" +) + +// A miniNode is a minimal node implementation, +// meant to be embedded as the first field in a larger node implementation, +// at a cost of 8 bytes. +// +// A miniNode is NOT a valid Node by itself: the embedding struct +// must at the least provide: +// +// func (n *MyNode) String() string { return fmt.Sprint(n) } +// func (n *MyNode) RawCopy() Node { c := *n; return &c } +// func (n *MyNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +// +// The embedding struct should also fill in n.op in its constructor, +// for more useful panic messages when invalid methods are called, +// instead of implementing Op itself. +// +type miniNode struct { + pos src.XPos // uint32 + op Op // uint8 + bits bitset8 + esc uint16 +} + +// op can be read, but not written. +// An embedding implementation can provide a SetOp if desired. +// (The panicking SetOp is with the other panics below.) +func (n *miniNode) Op() Op { return n.op } +func (n *miniNode) Pos() src.XPos { return n.pos } +func (n *miniNode) SetPos(x src.XPos) { n.pos = x } +func (n *miniNode) Esc() uint16 { return n.esc } +func (n *miniNode) SetEsc(x uint16) { n.esc = x } + +const ( + miniWalkdefShift = 0 + miniTypecheckShift = 2 + miniInitorderShift = 4 + miniDiag = 1 << 6 + miniHasCall = 1 << 7 // for miniStmt +) + +func (n *miniNode) Walkdef() uint8 { return n.bits.get2(miniWalkdefShift) } +func (n *miniNode) Typecheck() uint8 { return n.bits.get2(miniTypecheckShift) } +func (n *miniNode) Initorder() uint8 { return n.bits.get2(miniInitorderShift) } +func (n *miniNode) SetWalkdef(x uint8) { + if x > 3 { + panic(fmt.Sprintf("cannot SetWalkdef %d", x)) + } + n.bits.set2(miniWalkdefShift, x) +} +func (n *miniNode) SetTypecheck(x uint8) { + if x > 3 { + panic(fmt.Sprintf("cannot SetTypecheck %d", x)) + } + n.bits.set2(miniTypecheckShift, x) +} +func (n *miniNode) SetInitorder(x uint8) { + if x > 3 { + panic(fmt.Sprintf("cannot SetInitorder %d", x)) + } + n.bits.set2(miniInitorderShift, x) +} + +func (n *miniNode) Diag() bool { return n.bits&miniDiag != 0 } +func (n *miniNode) SetDiag(x bool) { n.bits.set(miniDiag, x) } + +// Empty, immutable graph structure. + +func (n *miniNode) Left() Node { return nil } +func (n *miniNode) Right() Node { return nil } +func (n *miniNode) Init() Nodes { return Nodes{} } +func (n *miniNode) PtrInit() *Nodes { return &immutableEmptyNodes } +func (n *miniNode) Body() Nodes { return Nodes{} } +func (n *miniNode) PtrBody() *Nodes { return &immutableEmptyNodes } +func (n *miniNode) List() Nodes { return Nodes{} } +func (n *miniNode) PtrList() *Nodes { return &immutableEmptyNodes } +func (n *miniNode) Rlist() Nodes { return Nodes{} } +func (n *miniNode) PtrRlist() *Nodes { return &immutableEmptyNodes } +func (n *miniNode) SetLeft(x Node) { + if x != nil { + panic(n.no("SetLeft")) + } +} +func (n *miniNode) SetRight(x Node) { + if x != nil { + panic(n.no("SetRight")) + } +} +func (n *miniNode) SetInit(x Nodes) { + if x != (Nodes{}) { + panic(n.no("SetInit")) + } +} +func (n *miniNode) SetBody(x Nodes) { + if x != (Nodes{}) { + panic(n.no("SetBody")) + } +} +func (n *miniNode) SetList(x Nodes) { + if x != (Nodes{}) { + panic(n.no("SetList")) + } +} +func (n *miniNode) SetRlist(x Nodes) { + if x != (Nodes{}) { + panic(n.no("SetRlist")) + } +} + +// Additional functionality unavailable. + +func (n *miniNode) no(name string) string { return "cannot " + name + " on " + n.op.String() } + +func (n *miniNode) SetOp(Op) { panic(n.no("SetOp")) } +func (n *miniNode) SubOp() Op { panic(n.no("SubOp")) } +func (n *miniNode) SetSubOp(Op) { panic(n.no("SetSubOp")) } +func (n *miniNode) Type() *types.Type { return nil } +func (n *miniNode) SetType(*types.Type) { panic(n.no("SetType")) } +func (n *miniNode) Func() *Func { panic(n.no("Func")) } +func (n *miniNode) SetFunc(*Func) { panic(n.no("SetFunc")) } +func (n *miniNode) Name() *Name { return nil } +func (n *miniNode) SetName(*Name) { panic(n.no("SetName")) } +func (n *miniNode) Sym() *types.Sym { return nil } +func (n *miniNode) SetSym(*types.Sym) { panic(n.no("SetSym")) } +func (n *miniNode) Offset() int64 { return types.BADWIDTH } +func (n *miniNode) SetOffset(x int64) { panic(n.no("SetOffset")) } +func (n *miniNode) Class() Class { return Pxxx } +func (n *miniNode) SetClass(Class) { panic(n.no("SetClass")) } +func (n *miniNode) Likely() bool { panic(n.no("Likely")) } +func (n *miniNode) SetLikely(bool) { panic(n.no("SetLikely")) } +func (n *miniNode) SliceBounds() (low, high, max Node) { + panic(n.no("SliceBounds")) +} +func (n *miniNode) SetSliceBounds(low, high, max Node) { + panic(n.no("SetSliceBounds")) +} +func (n *miniNode) Iota() int64 { panic(n.no("Iota")) } +func (n *miniNode) SetIota(int64) { panic(n.no("SetIota")) } +func (n *miniNode) Colas() bool { return false } +func (n *miniNode) SetColas(bool) { panic(n.no("SetColas")) } +func (n *miniNode) NoInline() bool { panic(n.no("NoInline")) } +func (n *miniNode) SetNoInline(bool) { panic(n.no("SetNoInline")) } +func (n *miniNode) Transient() bool { panic(n.no("Transient")) } +func (n *miniNode) SetTransient(bool) { panic(n.no("SetTransient")) } +func (n *miniNode) Implicit() bool { return false } +func (n *miniNode) SetImplicit(bool) { panic(n.no("SetImplicit")) } +func (n *miniNode) IsDDD() bool { return false } +func (n *miniNode) SetIsDDD(bool) { panic(n.no("SetIsDDD")) } +func (n *miniNode) Embedded() bool { return false } +func (n *miniNode) SetEmbedded(bool) { panic(n.no("SetEmbedded")) } +func (n *miniNode) IndexMapLValue() bool { panic(n.no("IndexMapLValue")) } +func (n *miniNode) SetIndexMapLValue(bool) { panic(n.no("SetIndexMapLValue")) } +func (n *miniNode) ResetAux() { panic(n.no("ResetAux")) } +func (n *miniNode) HasBreak() bool { panic(n.no("HasBreak")) } +func (n *miniNode) SetHasBreak(bool) { panic(n.no("SetHasBreak")) } +func (n *miniNode) HasVal() bool { return false } +func (n *miniNode) Val() constant.Value { panic(n.no("Val")) } +func (n *miniNode) SetVal(v constant.Value) { panic(n.no("SetVal")) } +func (n *miniNode) Int64Val() int64 { panic(n.no("Int64Val")) } +func (n *miniNode) Uint64Val() uint64 { panic(n.no("Uint64Val")) } +func (n *miniNode) CanInt64() bool { panic(n.no("CanInt64")) } +func (n *miniNode) BoolVal() bool { panic(n.no("BoolVal")) } +func (n *miniNode) StringVal() string { panic(n.no("StringVal")) } +func (n *miniNode) HasCall() bool { panic(n.no("HasCall")) } +func (n *miniNode) SetHasCall(bool) { panic(n.no("SetHasCall")) } +func (n *miniNode) NonNil() bool { return false } +func (n *miniNode) MarkNonNil() { panic(n.no("MarkNonNil")) } +func (n *miniNode) Bounded() bool { return false } +func (n *miniNode) SetBounded(bool) { panic(n.no("SetBounded")) } +func (n *miniNode) Opt() interface{} { return nil } +func (n *miniNode) SetOpt(interface{}) { panic(n.no("SetOpt")) } +func (n *miniNode) MarkReadonly() { panic(n.no("MarkReadonly")) } +func (n *miniNode) TChanDir() types.ChanDir { panic(n.no("TChanDir")) } +func (n *miniNode) SetTChanDir(types.ChanDir) { panic(n.no("SetTChanDir")) } + +// TODO: Delete when CanBeAnSSASym is removed from Node itself. +func (*miniNode) CanBeAnSSASym() {} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index acfddd2dc7..7a61355858 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -199,7 +199,6 @@ func (n *node) SetOffset(x int64) { n.offset = x } func (n *node) Esc() uint16 { return n.esc } func (n *node) SetEsc(x uint16) { n.esc = x } func (n *node) Op() Op { return n.op } -func (n *node) SetOp(x Op) { n.op = x } func (n *node) Init() Nodes { return n.init } func (n *node) SetInit(x Nodes) { n.init = x } func (n *node) PtrInit() *Nodes { return &n.init } @@ -213,6 +212,13 @@ func (n *node) Rlist() Nodes { return n.rlist } func (n *node) SetRlist(x Nodes) { n.rlist = x } func (n *node) PtrRlist() *Nodes { return &n.rlist } +func (n *node) SetOp(op Op) { + if !okForNod[op] { + panic("cannot node.SetOp " + op.String()) + } + n.op = op +} + func (n *node) ResetAux() { n.aux = 0 } @@ -1109,6 +1115,10 @@ const ( // a slice to save space. type Nodes struct{ slice *[]Node } +// immutableEmptyNodes is an immutable, empty Nodes list. +// The methods that would modify it panic instead. +var immutableEmptyNodes = Nodes{} + // asNodes returns a slice of *Node as a Nodes value. func AsNodes(s []Node) Nodes { return Nodes{&s} @@ -1150,9 +1160,22 @@ func (n Nodes) Second() Node { return (*n.slice)[1] } +func (n *Nodes) mutate() { + if n == &immutableEmptyNodes { + panic("immutable Nodes.Set") + } +} + // Set sets n to a slice. // This takes ownership of the slice. func (n *Nodes) Set(s []Node) { + if n == &immutableEmptyNodes { + if len(s) == 0 { + // Allow immutableEmptyNodes.Set(nil) (a no-op). + return + } + n.mutate() + } if len(s) == 0 { n.slice = nil } else { @@ -1166,21 +1189,25 @@ func (n *Nodes) Set(s []Node) { // Set1 sets n to a slice containing a single node. func (n *Nodes) Set1(n1 Node) { + n.mutate() n.slice = &[]Node{n1} } // Set2 sets n to a slice containing two nodes. func (n *Nodes) Set2(n1, n2 Node) { + n.mutate() n.slice = &[]Node{n1, n2} } // Set3 sets n to a slice containing three nodes. func (n *Nodes) Set3(n1, n2, n3 Node) { + n.mutate() n.slice = &[]Node{n1, n2, n3} } // MoveNodes sets n to the contents of n2, then clears n2. func (n *Nodes) MoveNodes(n2 *Nodes) { + n.mutate() n.slice = n2.slice n2.slice = nil } @@ -1214,6 +1241,7 @@ func (n *Nodes) Append(a ...Node) { if len(a) == 0 { return } + n.mutate() if n.slice == nil { s := make([]Node, len(a)) copy(s, a) @@ -1229,6 +1257,7 @@ func (n *Nodes) Prepend(a ...Node) { if len(a) == 0 { return } + n.mutate() if n.slice == nil { n.slice = &a } else { @@ -1238,6 +1267,7 @@ func (n *Nodes) Prepend(a ...Node) { // AppendNodes appends the contents of *n2 to n, then clears n2. func (n *Nodes) AppendNodes(n2 *Nodes) { + n.mutate() switch { case n2.slice == nil: case n.slice == nil: @@ -1341,43 +1371,7 @@ func (s NodeSet) Sorted(less func(Node, Node) bool) []Node { return res } -func Nod(op Op, nleft, nright Node) Node { - return NodAt(base.Pos, op, nleft, nright) -} - -func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { - var n Node - switch op { - case ODCLFUNC: - var x struct { - n node - f Func - } - n = &x.n - n.SetFunc(&x.f) - n.Func().Decl = n - case ONAME: - base.Fatalf("use newname instead") - case OLABEL, OPACK: - var x struct { - n node - m Name - } - n = &x.n - n.SetName(&x.m) - default: - n = new(node) - } - n.SetOp(op) - n.SetLeft(nleft) - n.SetRight(nright) - n.SetPos(pos) - n.SetOffset(types.BADWIDTH) - n.SetOrig(n) - return n -} - -// newnamel returns a new ONAME Node associated with symbol s at position pos. +// NewNameAt returns a new ONAME Node associated with symbol s at position pos. // The caller is responsible for setting n.Name.Curfn. func NewNameAt(pos src.XPos, s *types.Sym) Node { if s == nil { @@ -1664,3 +1658,193 @@ func IsBlank(n Node) bool { func IsMethod(n Node) bool { return n.Type().Recv() != nil } + +func Nod(op Op, nleft, nright Node) Node { + return NodAt(base.Pos, op, nleft, nright) +} + +func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { + var n Node + switch op { + case ODCLFUNC: + var x struct { + n node + f Func + } + n = &x.n + n.SetFunc(&x.f) + n.Func().Decl = n + case OLABEL, OPACK: + var x struct { + n node + m Name + } + n = &x.n + n.SetName(&x.m) + default: + n = new(node) + } + n.SetOp(op) + n.SetLeft(nleft) + n.SetRight(nright) + n.SetPos(pos) + n.SetOffset(types.BADWIDTH) + n.SetOrig(n) + return n +} + +var okForNod = [OEND]bool{ + OADD: true, + OADDR: true, + OADDSTR: true, + OALIGNOF: true, + OAND: true, + OANDAND: true, + OANDNOT: true, + OAPPEND: true, + OARRAYLIT: true, + OAS: true, + OAS2: true, + OAS2DOTTYPE: true, + OAS2FUNC: true, + OAS2MAPR: true, + OAS2RECV: true, + OASOP: true, + OBITNOT: true, + OBLOCK: true, + OBREAK: true, + OBYTES2STR: true, + OBYTES2STRTMP: true, + OCALL: true, + OCALLFUNC: true, + OCALLINTER: true, + OCALLMETH: true, + OCALLPART: true, + OCAP: true, + OCASE: true, + OCFUNC: true, + OCHECKNIL: true, + OCLOSE: true, + OCLOSURE: true, + OCLOSUREVAR: true, + OCOMPLEX: true, + OCOMPLIT: true, + OCONTINUE: true, + OCONV: true, + OCONVIFACE: true, + OCONVNOP: true, + OCOPY: true, + ODCL: true, + ODCLCONST: true, + ODCLFIELD: true, + ODCLFUNC: true, + ODCLTYPE: true, + ODDD: true, + ODEFER: true, + ODELETE: true, + ODEREF: true, + ODIV: true, + ODOT: true, + ODOTINTER: true, + ODOTMETH: true, + ODOTPTR: true, + ODOTTYPE: true, + ODOTTYPE2: true, + OEFACE: true, + OEMPTY: true, + OEQ: true, + OFALL: true, + OFOR: true, + OFORUNTIL: true, + OGE: true, + OGETG: true, + OGO: true, + OGOTO: true, + OGT: true, + OIDATA: true, + OIF: true, + OIMAG: true, + OINDEX: true, + OINDEXMAP: true, + OINLCALL: true, + OINLMARK: true, + OIOTA: true, + OITAB: true, + OKEY: true, + OLABEL: true, + OLE: true, + OLEN: true, + OLITERAL: true, + OLSH: true, + OLT: true, + OMAKE: true, + OMAKECHAN: true, + OMAKEMAP: true, + OMAKESLICE: true, + OMAKESLICECOPY: true, + OMAPLIT: true, + OMETHEXPR: true, + OMOD: true, + OMUL: true, + ONAME: true, + ONE: true, + ONEG: true, + ONEW: true, + ONEWOBJ: true, + ONIL: true, + ONONAME: true, + ONOT: true, + OOFFSETOF: true, + OOR: true, + OOROR: true, + OPACK: true, + OPANIC: true, + OPAREN: true, + OPLUS: true, + OPRINT: true, + OPRINTN: true, + OPTRLIT: true, + ORANGE: true, + OREAL: true, + ORECOVER: true, + ORECV: true, + ORESULT: true, + ORETJMP: true, + ORETURN: true, + ORSH: true, + ORUNES2STR: true, + ORUNESTR: true, + OSELECT: true, + OSELRECV: true, + OSELRECV2: true, + OSEND: true, + OSIZEOF: true, + OSLICE: true, + OSLICE3: true, + OSLICE3ARR: true, + OSLICEARR: true, + OSLICEHEADER: true, + OSLICELIT: true, + OSLICESTR: true, + OSPTR: true, + OSTR2BYTES: true, + OSTR2BYTESTMP: true, + OSTR2RUNES: true, + OSTRUCTKEY: true, + OSTRUCTLIT: true, + OSUB: true, + OSWITCH: true, + OTARRAY: true, + OTCHAN: true, + OTFUNC: true, + OTINTER: true, + OTMAP: true, + OTSTRUCT: true, + OTYPE: true, + OTYPESW: true, + OVARDEF: true, + OVARKILL: true, + OVARLIVE: true, + OXDOT: true, + OXOR: true, +} From 171787efcd7a59c90f05a191c74bf5844f1c542a Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 00:36:44 -0500 Subject: [PATCH 016/212] [dev.regabi] cmd/compile: remove Orig, SetOrig from Node interface These are only needed for a few opcodes, and we can avoid wasting storage in every implementation by using the extension interface pattern with a helper function for access. Of course, in the current codebase, there is only one Node implementation (*node) and it has these methods, so there is no danger of a functional change in this particular CL. Passes buildall w/ toolstash -cmp. Change-Id: I440c6c232f1fe7b56b852a00dc530f8f49a6b12d Reviewed-on: https://go-review.googlesource.com/c/go/+/274089 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/const.go | 4 +-- src/cmd/compile/internal/gc/escape.go | 2 +- src/cmd/compile/internal/gc/gen.go | 2 +- src/cmd/compile/internal/gc/iexport.go | 4 +-- src/cmd/compile/internal/gc/ssa.go | 2 +- src/cmd/compile/internal/gc/subr.go | 2 +- src/cmd/compile/internal/gc/typecheck.go | 10 +++--- src/cmd/compile/internal/ir/fmt.go | 8 ++--- src/cmd/compile/internal/ir/node.go | 42 ++++++++++++++++++++---- 9 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 4beb85245f..3c161d8e12 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -537,7 +537,7 @@ func evalConst(n ir.Node) ir.Node { } nl := origConst(s[i], constant.MakeString(strings.Join(strs, ""))) - nl.SetOrig(nl) // it's bigger than just s[i] + nl.(ir.OrigNode).SetOrig(nl) // it's bigger than just s[i] newList = append(newList, nl) i = i2 - 1 } else { @@ -642,7 +642,7 @@ func origConst(n ir.Node, v constant.Value) ir.Node { orig := n n = ir.NodAt(orig.Pos(), ir.OLITERAL, nil, nil) - n.SetOrig(orig) + n.(ir.OrigNode).SetOrig(orig) n.SetType(orig.Type()) n.SetVal(v) return n diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 6b6fb44a99..e3ac883e95 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -1871,7 +1871,7 @@ func moveToHeap(n ir.Node) { // temp will add it to the function declaration list automatically. heapaddr := temp(types.NewPtr(n.Type())) heapaddr.SetSym(lookup("&" + n.Sym().Name)) - heapaddr.Orig().SetSym(heapaddr.Sym()) + ir.Orig(heapaddr).SetSym(heapaddr.Sym()) heapaddr.SetPos(n.Pos()) // Unset AutoTemp to persist the &foo variable name through SSA to diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index 44e918f2c1..cb640c7ccf 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -80,7 +80,7 @@ func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) ir.Node { dowidth(t) - return n.Orig() + return ir.Orig(n) } func temp(t *types.Type) ir.Node { diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 7c42e43bee..c2ea599af4 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -1210,8 +1210,8 @@ func (w *exportWriter) expr(n ir.Node) { if !n.Type().HasNil() { base.Fatalf("unexpected type for nil: %v", n.Type()) } - if n.Orig() != nil && n.Orig() != n { - w.expr(n.Orig()) + if orig := ir.Orig(n); orig != nil && orig != n { + w.expr(orig) break } w.op(ir.OLITERAL) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index bcc126f82e..1a13b14376 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -6675,7 +6675,7 @@ func AddAux2(a *obj.Addr, v *ssa.Value, offset int64) { case ir.Node: if n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT { a.Name = obj.NAME_PARAM - a.Sym = n.Orig().Sym().Linksym() + a.Sym = ir.Orig(n).Sym().Linksym() a.Offset += n.Offset() break } diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index d174ebd582..722876abf5 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -559,7 +559,7 @@ func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node { r.SetType(t) r.SetTypecheck(1) r.SetImplicit(true) - r.SetOrig(n.Orig()) + r.(ir.OrigNode).SetOrig(ir.Orig(n)) return r } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 9da464e1b6..7037eddff0 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -851,7 +851,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { checklvalue(n.Left(), "take the address of") r := outervalue(n.Left()) if r.Op() == ir.ONAME { - if r.Orig() != r { + if ir.Orig(r) != r { base.Fatalf("found non-orig name node %v", r) // TODO(mdempsky): What does this mean? } r.Name().SetAddrtaken(true) @@ -2144,8 +2144,8 @@ func typecheckargs(n ir.Node) { // Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...). // Save n as n.Orig for fmt.go. - if n.Orig() == n { - n.SetOrig(ir.SepCopy(n)) + if ir.Orig(n) == n { + n.(ir.OrigNode).SetOrig(ir.SepCopy(n)) } as := ir.Nod(ir.OAS2, nil, nil) @@ -2245,7 +2245,7 @@ func checkdefergo(n ir.Node) { ir.ONEW, ir.OREAL, ir.OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof - if n.Left().Orig() != nil && n.Left().Orig().Op() == ir.OCONV { + if orig := ir.Orig(n.Left()); orig.Op() == ir.OCONV { break } base.ErrorfAt(n.Pos(), "%s discards result of %v", what, n.Left()) @@ -2814,7 +2814,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) { } // Save original node (including n.Right) - n.SetOrig(ir.Copy(n)) + n.(ir.OrigNode).SetOrig(ir.Copy(n)) setlineno(n.Right()) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index f394219c05..24318d501f 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1223,8 +1223,8 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { case OLITERAL: // this is a bit of a mess if mode == FErr { - if n.Orig() != nil && n.Orig() != n { - exprFmt(n.Orig(), s, prec, mode) + if orig := Orig(n); orig != nil && orig != n { + exprFmt(orig, s, prec, mode) return } if n.Sym() != nil { @@ -1561,8 +1561,8 @@ func nodeFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { // We almost always want the original. // TODO(gri) Why the special case for OLITERAL? - if n.Op() != OLITERAL && n.Orig() != nil { - n = n.Orig() + if n.Op() != OLITERAL && Orig(n) != nil { + n = Orig(n) } if flag&FmtLong != 0 && t != nil { diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 7a61355858..7e46673eab 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -35,8 +35,6 @@ type Node interface { // Abstract graph structure, for generic traversals. Op() Op SetOp(x Op) - Orig() Node - SetOrig(x Node) SubOp() Op SetSubOp(x Op) Left() Node @@ -1616,11 +1614,41 @@ func (n *node) RawCopy() Node { return © } +// A Node may implement the Orig and SetOrig method to +// maintain a pointer to the "unrewritten" form of a Node. +// If a Node does not implement OrigNode, it is its own Orig. +// +// Note that both SepCopy and Copy have definitions compatible +// with a Node that does not implement OrigNode: such a Node +// is its own Orig, and in that case, that's what both want to return +// anyway (SepCopy unconditionally, and Copy only when the input +// is its own Orig as well, but if the output does not implement +// OrigNode, then neither does the input, making the condition true). +type OrigNode interface { + Node + Orig() Node + SetOrig(Node) +} + +func Orig(n Node) Node { + if n, ok := n.(OrigNode); ok { + o := n.Orig() + if o == nil { + Dump("Orig nil", n) + base.Fatalf("Orig returned nil") + } + return o + } + return n +} + // sepcopy returns a separate shallow copy of n, with the copy's // Orig pointing to itself. func SepCopy(n Node) Node { n = n.RawCopy() - n.SetOrig(n) + if n, ok := n.(OrigNode); ok { + n.SetOrig(n) + } return n } @@ -1633,8 +1661,8 @@ func SepCopy(n Node) Node { // messages; see issues #26855, #27765). func Copy(n Node) Node { copy := n.RawCopy() - if n.Orig() == n { - copy.SetOrig(copy) + if n, ok := n.(OrigNode); ok && n.Orig() == n { + copy.(OrigNode).SetOrig(copy) } return copy } @@ -1643,7 +1671,7 @@ func Copy(n Node) Node { func IsNil(n Node) bool { // Check n.Orig because constant propagation may produce typed nil constants, // which don't exist in the Go spec. - return n.Orig().Op() == ONIL + return Orig(n).Op() == ONIL } func IsBlank(n Node) bool { @@ -1664,7 +1692,7 @@ func Nod(op Op, nleft, nright Node) Node { } func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { - var n Node + var n *node switch op { case ODCLFUNC: var x struct { From b09dbc69132aeee3571867cd269f5273290a2255 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 00:54:58 -0500 Subject: [PATCH 017/212] [dev.regabi] cmd/compile: remove SetOp(OEMPTY) calls In preparation for OEMPTY being its own Node implementation, remove SetOp(OEMPTY) calls that assume other implementations can be turned into OEMPTY. Passes buildall w/ toolstash -cmp. Change-Id: Icac16d12548f35f52a5efa9d09dacf8260f42075 Reviewed-on: https://go-review.googlesource.com/c/go/+/274090 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/sinit.go | 5 +++-- src/cmd/compile/internal/gc/typecheck.go | 3 +-- src/cmd/compile/internal/gc/walk.go | 9 ++++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index e30663cfbb..fca81763c0 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -959,6 +959,9 @@ func anylit(n ir.Node, var_ ir.Node, init *ir.Nodes) { } } +// oaslit handles special composite literal assignments. +// It returns true if n's effects have been added to init, +// in which case n should be dropped from the program by the caller. func oaslit(n ir.Node, init *ir.Nodes) bool { if n.Left() == nil || n.Right() == nil { // not a special composite literal assignment @@ -990,8 +993,6 @@ func oaslit(n ir.Node, init *ir.Nodes) bool { anylit(n.Right(), n.Left(), init) } - n.SetOp(ir.OEMPTY) - n.SetRight(nil) return true } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 7037eddff0..0c4a3ad833 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1985,8 +1985,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // Empty identifier is valid but useless. // Eliminate now to simplify life later. // See issues 7538, 11589, 11593. - n.SetOp(ir.OEMPTY) - n.SetLeft(nil) + n = ir.NodAt(n.Pos(), ir.OEMPTY, nil, nil) } case ir.ODEFER: diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index db8791ee05..87fe36b08a 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -152,10 +152,12 @@ func walkstmt(n ir.Node) ir.Node { init := n.Init() n.PtrInit().Set(nil) n = walkexpr(n, &init) - n = addinit(n, init.Slice()) - if wascopy && n.Op() == ir.OCONVNOP { - n.SetOp(ir.OEMPTY) // don't leave plain values as statements. + if wascopy && n.Op() == ir.ONAME { + // copy rewrote to a statement list and a temp for the length. + // Throw away the temp to avoid plain values as statements. + n = ir.NodAt(n.Pos(), ir.OEMPTY, nil, nil) } + n = addinit(n, init.Slice()) // special case for a receive where we throw away // the value received. @@ -609,6 +611,7 @@ opswitch: } if oaslit(n, init) { + n = ir.NodAt(n.Pos(), ir.OEMPTY, nil, nil) break } From be3d8b40b5447f787174015260e85b5198e8f7e6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 00:43:50 -0500 Subject: [PATCH 018/212] [dev.regabi] cmd/compile: ir.BranchStmt, add ir.EmptyStmt, ir.LabelStmt These are the first three specific implementations of Node. They are both a bit of a warmup and also working toward removing references to Name from Node types other than the proper named things - ONAME, ONONAME, OTYPE, OLITERAL. (In this case, BranchStmt and LabelStmt.) Passes buildall w/ toolstash -cmp. Change-Id: Ide816b162025ee4c858dd061d7c29ed633fb7baf Reviewed-on: https://go-review.googlesource.com/c/go/+/274091 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/mini.go | 4 +- src/cmd/compile/internal/ir/node.go | 13 ++--- src/cmd/compile/internal/ir/stmt.go | 83 +++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 src/cmd/compile/internal/ir/stmt.go diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index 48dccf6a5f..608c2bed81 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -127,7 +127,7 @@ func (n *miniNode) SubOp() Op { panic(n.no("SubOp")) } func (n *miniNode) SetSubOp(Op) { panic(n.no("SetSubOp")) } func (n *miniNode) Type() *types.Type { return nil } func (n *miniNode) SetType(*types.Type) { panic(n.no("SetType")) } -func (n *miniNode) Func() *Func { panic(n.no("Func")) } +func (n *miniNode) Func() *Func { return nil } func (n *miniNode) SetFunc(*Func) { panic(n.no("SetFunc")) } func (n *miniNode) Name() *Name { return nil } func (n *miniNode) SetName(*Name) { panic(n.no("SetName")) } @@ -172,7 +172,7 @@ func (n *miniNode) Uint64Val() uint64 { panic(n.no("Uint64Val")) } func (n *miniNode) CanInt64() bool { panic(n.no("CanInt64")) } func (n *miniNode) BoolVal() bool { panic(n.no("BoolVal")) } func (n *miniNode) StringVal() string { panic(n.no("StringVal")) } -func (n *miniNode) HasCall() bool { panic(n.no("HasCall")) } +func (n *miniNode) HasCall() bool { return false } func (n *miniNode) SetHasCall(bool) { panic(n.no("SetHasCall")) } func (n *miniNode) NonNil() bool { return false } func (n *miniNode) MarkNonNil() { panic(n.no("MarkNonNil")) } diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 7e46673eab..cafe47493b 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -1702,13 +1702,19 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { n = &x.n n.SetFunc(&x.f) n.Func().Decl = n - case OLABEL, OPACK: + case OPACK: var x struct { n node m Name } n = &x.n n.SetName(&x.m) + case OEMPTY: + return NewEmptyStmt(pos) + case OBREAK, OCONTINUE, OFALL, OGOTO: + return NewBranchStmt(pos, op, nil) + case OLABEL: + return NewLabelStmt(pos, nil) default: n = new(node) } @@ -1740,7 +1746,6 @@ var okForNod = [OEND]bool{ OASOP: true, OBITNOT: true, OBLOCK: true, - OBREAK: true, OBYTES2STR: true, OBYTES2STRTMP: true, OCALL: true, @@ -1757,7 +1762,6 @@ var okForNod = [OEND]bool{ OCLOSUREVAR: true, OCOMPLEX: true, OCOMPLIT: true, - OCONTINUE: true, OCONV: true, OCONVIFACE: true, OCONVNOP: true, @@ -1779,15 +1783,12 @@ var okForNod = [OEND]bool{ ODOTTYPE: true, ODOTTYPE2: true, OEFACE: true, - OEMPTY: true, OEQ: true, - OFALL: true, OFOR: true, OFORUNTIL: true, OGE: true, OGETG: true, OGO: true, - OGOTO: true, OGT: true, OIDATA: true, OIF: true, diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go new file mode 100644 index 0000000000..5b89ff27a4 --- /dev/null +++ b/src/cmd/compile/internal/ir/stmt.go @@ -0,0 +1,83 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ir + +import ( + "cmd/compile/internal/types" + "cmd/internal/src" + "fmt" +) + +// A miniStmt is a miniNode with extra fields common to statements. +type miniStmt struct { + miniNode + init Nodes +} + +func (n *miniStmt) Init() Nodes { return n.init } +func (n *miniStmt) SetInit(x Nodes) { n.init = x } +func (n *miniStmt) PtrInit() *Nodes { return &n.init } +func (n *miniStmt) HasCall() bool { return n.bits&miniHasCall != 0 } +func (n *miniStmt) SetHasCall(b bool) { n.bits.set(miniHasCall, b) } + +// A BranchStmt is a break, continue, fallthrough, or goto statement. +type BranchStmt struct { + miniStmt + Label *types.Sym // label if present +} + +func NewBranchStmt(pos src.XPos, op Op, label *types.Sym) *BranchStmt { + switch op { + case OBREAK, OCONTINUE, OFALL, OGOTO: + // ok + default: + panic("NewBranch " + op.String()) + } + n := &BranchStmt{Label: label} + n.pos = pos + n.op = op + return n +} + +func (n *BranchStmt) String() string { return fmt.Sprint(n) } +func (n *BranchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *BranchStmt) RawCopy() Node { c := *n; return &c } +func (n *BranchStmt) Sym() *types.Sym { return n.Label } +func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym } + +// An EmptyStmt is an empty statement +type EmptyStmt struct { + miniStmt +} + +func NewEmptyStmt(pos src.XPos) *EmptyStmt { + n := &EmptyStmt{} + n.pos = pos + n.op = OEMPTY + return n +} + +func (n *EmptyStmt) String() string { return fmt.Sprint(n) } +func (n *EmptyStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *EmptyStmt) RawCopy() Node { c := *n; return &c } + +// A LabelStmt is a label statement (just the label, not including the statement it labels). +type LabelStmt struct { + miniStmt + Label *types.Sym // "Label:" +} + +func NewLabelStmt(pos src.XPos, label *types.Sym) *LabelStmt { + n := &LabelStmt{Label: label} + n.pos = pos + n.op = OLABEL + return n +} + +func (n *LabelStmt) String() string { return fmt.Sprint(n) } +func (n *LabelStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *LabelStmt) RawCopy() Node { c := *n; return &c } +func (n *LabelStmt) Sym() *types.Sym { return n.Label } +func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x } From 420809ab08d28fbe8dbe0e8fa4159c7dc82d88ae Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 01:03:40 -0500 Subject: [PATCH 019/212] [dev.regabi] cmd/compile: move name code from node.go to name.go No code changes here, only copying of text. This will make the diffs in a future CL readable. Passes buildall w/ toolstash -cmp. Change-Id: I1b8d8b9ec9408859e36af5ff3bef7c6c10eac0d6 Reviewed-on: https://go-review.googlesource.com/c/go/+/274092 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/name.go | 376 ++++++++++++++++++++++++++++ src/cmd/compile/internal/ir/node.go | 364 --------------------------- 2 files changed, 376 insertions(+), 364 deletions(-) create mode 100644 src/cmd/compile/internal/ir/name.go diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go new file mode 100644 index 0000000000..fc7a5049e0 --- /dev/null +++ b/src/cmd/compile/internal/ir/name.go @@ -0,0 +1,376 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ir + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/types" + "cmd/internal/objabi" + "cmd/internal/src" + "go/constant" +) + +// Name holds Node fields used only by named nodes (ONAME, OTYPE, OPACK, OLABEL, some OLITERAL). +type Name struct { + Pack Node // real package for import . names + Pkg *types.Pkg // pkg for OPACK nodes + // 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 + Defn Node + // The ODCLFUNC node (for a static function/method or a closure) in which + // local variable or param is declared. + Curfn Node + Param *Param // additional fields for ONAME, OTYPE + Decldepth int32 // declaration loop depth, increased for every loop or label + // Unique number for ONAME nodes within a function. Function outputs + // (results) are numbered starting at one, followed by function inputs + // (parameters), and then local variables. Vargen is used to distinguish + // local variables/params with the same name. + Vargen int32 + flags bitset16 +} + +type Param struct { + Ntype Node + Heapaddr Node // temp holding heap address of param + + // ONAME PAUTOHEAP + Stackcopy Node // the PPARAM/PPARAMOUT on-stack slot (moved func params only) + + // ONAME closure linkage + // Consider: + // + // func f() { + // x := 1 // x1 + // func() { + // use(x) // x2 + // func() { + // use(x) // x3 + // --- parser is here --- + // }() + // }() + // } + // + // There is an original declaration of x and then a chain of mentions of x + // leading into the current function. Each time x is mentioned in a new closure, + // we create a variable representing x for use in that specific closure, + // since the way you get to x is different in each closure. + // + // Let's number the specific variables as shown in the code: + // x1 is the original x, x2 is when mentioned in the closure, + // and x3 is when mentioned in the closure in the closure. + // + // We keep these linked (assume N > 1): + // + // - x1.Defn = original declaration statement for x (like most variables) + // - x1.Innermost = current innermost closure x (in this case x3), or nil for none + // - x1.IsClosureVar() = false + // + // - xN.Defn = x1, N > 1 + // - xN.IsClosureVar() = true, N > 1 + // - x2.Outer = nil + // - xN.Outer = x(N-1), N > 2 + // + // + // When we look up x in the symbol table, we always get x1. + // Then we can use x1.Innermost (if not nil) to get the x + // for the innermost known closure function, + // but the first reference in a closure will find either no x1.Innermost + // or an x1.Innermost with .Funcdepth < Funcdepth. + // In that case, a new xN must be created, linked in with: + // + // xN.Defn = x1 + // xN.Outer = x1.Innermost + // x1.Innermost = xN + // + // When we finish the function, we'll process its closure variables + // and find xN and pop it off the list using: + // + // x1 := xN.Defn + // x1.Innermost = xN.Outer + // + // We leave x1.Innermost set so that we can still get to the original + // variable quickly. Not shown here, but once we're + // done parsing a function and no longer need xN.Outer for the + // lexical x reference links as described above, funcLit + // recomputes xN.Outer as the semantic x reference link tree, + // even filling in x in intermediate closures that might not + // have mentioned it along the way to inner closures that did. + // See funcLit for details. + // + // During the eventual compilation, then, for closure variables we have: + // + // xN.Defn = original variable + // xN.Outer = variable captured in next outward scope + // to make closure where xN appears + // + // Because of the sharding of pieces of the node, x.Defn means x.Name.Defn + // and x.Innermost/Outer means x.Name.Param.Innermost/Outer. + Innermost Node + Outer Node + + // OTYPE & ONAME //go:embed info, + // sharing storage to reduce gc.Param size. + // Extra is nil, or else *Extra is a *paramType or an *embedFileList. + Extra *interface{} +} + +// NewNameAt returns a new ONAME Node associated with symbol s at position pos. +// The caller is responsible for setting n.Name.Curfn. +func NewNameAt(pos src.XPos, s *types.Sym) Node { + if s == nil { + base.Fatalf("newnamel nil") + } + + var x struct { + n node + m Name + p Param + } + n := &x.n + n.SetName(&x.m) + n.Name().Param = &x.p + + n.SetOp(ONAME) + n.SetPos(pos) + n.SetOrig(n) + + n.SetSym(s) + return n +} + +type paramType struct { + flag PragmaFlag + alias bool +} + +// Pragma returns the PragmaFlag for p, which must be for an OTYPE. +func (p *Param) Pragma() PragmaFlag { + if p.Extra == nil { + return 0 + } + return (*p.Extra).(*paramType).flag +} + +// SetPragma sets the PragmaFlag for p, which must be for an OTYPE. +func (p *Param) SetPragma(flag PragmaFlag) { + if p.Extra == nil { + if flag == 0 { + return + } + p.Extra = new(interface{}) + *p.Extra = ¶mType{flag: flag} + return + } + (*p.Extra).(*paramType).flag = flag +} + +// Alias reports whether p, which must be for an OTYPE, is a type alias. +func (p *Param) Alias() bool { + if p.Extra == nil { + return false + } + t, ok := (*p.Extra).(*paramType) + if !ok { + return false + } + return t.alias +} + +// SetAlias sets whether p, which must be for an OTYPE, is a type alias. +func (p *Param) SetAlias(alias bool) { + if p.Extra == nil { + if !alias { + return + } + p.Extra = new(interface{}) + *p.Extra = ¶mType{alias: alias} + return + } + (*p.Extra).(*paramType).alias = alias +} + +type embedFileList []string + +// EmbedFiles returns the list of embedded files for p, +// which must be for an ONAME var. +func (p *Param) EmbedFiles() []string { + if p.Extra == nil { + return nil + } + return *(*p.Extra).(*embedFileList) +} + +// SetEmbedFiles sets the list of embedded files for p, +// which must be for an ONAME var. +func (p *Param) SetEmbedFiles(list []string) { + if p.Extra == nil { + if len(list) == 0 { + return + } + f := embedFileList(list) + p.Extra = new(interface{}) + *p.Extra = &f + return + } + *(*p.Extra).(*embedFileList) = list +} + +const ( + nameCaptured = 1 << iota // is the variable captured by a closure + nameReadonly + nameByval // is the variable captured by value or by reference + nameNeedzero // if it contains pointers, needs to be zeroed on function entry + nameAutoTemp // is the variable a temporary (implies no dwarf info. reset if escapes to heap) + nameUsed // for variable declared and not used error + nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original at n.Name.Defn + nameIsOutputParamHeapAddr // pointer to a result parameter's heap copy + nameAssigned // is the variable ever assigned to + nameAddrtaken // address taken, even if not moved to heap + nameInlFormal // PAUTO created by inliner, derived from callee formal + nameInlLocal // PAUTO created by inliner, derived from callee local + nameOpenDeferSlot // if temporary var storing info for open-coded defers + nameLibfuzzerExtraCounter // if PEXTERN should be assigned to __libfuzzer_extra_counters section +) + +func (n *Name) Captured() bool { return n.flags&nameCaptured != 0 } +func (n *Name) Readonly() bool { return n.flags&nameReadonly != 0 } +func (n *Name) Byval() bool { return n.flags&nameByval != 0 } +func (n *Name) Needzero() bool { return n.flags&nameNeedzero != 0 } +func (n *Name) AutoTemp() bool { return n.flags&nameAutoTemp != 0 } +func (n *Name) Used() bool { return n.flags&nameUsed != 0 } +func (n *Name) IsClosureVar() bool { return n.flags&nameIsClosureVar != 0 } +func (n *Name) IsOutputParamHeapAddr() bool { return n.flags&nameIsOutputParamHeapAddr != 0 } +func (n *Name) Assigned() bool { return n.flags&nameAssigned != 0 } +func (n *Name) Addrtaken() bool { return n.flags&nameAddrtaken != 0 } +func (n *Name) InlFormal() bool { return n.flags&nameInlFormal != 0 } +func (n *Name) InlLocal() bool { return n.flags&nameInlLocal != 0 } +func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 } +func (n *Name) LibfuzzerExtraCounter() bool { return n.flags&nameLibfuzzerExtraCounter != 0 } + +func (n *Name) SetCaptured(b bool) { n.flags.set(nameCaptured, b) } +func (n *Name) SetReadonly(b bool) { n.flags.set(nameReadonly, b) } +func (n *Name) SetByval(b bool) { n.flags.set(nameByval, b) } +func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) } +func (n *Name) SetAutoTemp(b bool) { n.flags.set(nameAutoTemp, b) } +func (n *Name) SetUsed(b bool) { n.flags.set(nameUsed, b) } +func (n *Name) SetIsClosureVar(b bool) { n.flags.set(nameIsClosureVar, b) } +func (n *Name) SetIsOutputParamHeapAddr(b bool) { n.flags.set(nameIsOutputParamHeapAddr, b) } +func (n *Name) SetAssigned(b bool) { n.flags.set(nameAssigned, b) } +func (n *Name) SetAddrtaken(b bool) { n.flags.set(nameAddrtaken, b) } +func (n *Name) SetInlFormal(b bool) { n.flags.set(nameInlFormal, b) } +func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b) } +func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) } +func (n *Name) SetLibfuzzerExtraCounter(b bool) { n.flags.set(nameLibfuzzerExtraCounter, b) } + +// MarkReadonly indicates that n is an ONAME with readonly contents. +func (n *node) MarkReadonly() { + if n.Op() != ONAME { + base.Fatalf("Node.MarkReadonly %v", n.Op()) + } + n.Name().SetReadonly(true) + // Mark the linksym as readonly immediately + // so that the SSA backend can use this information. + // It will be overridden later during dumpglobls. + n.Sym().Linksym().Type = objabi.SRODATA +} + +// Val returns the constant.Value for the node. +func (n *node) Val() constant.Value { + if !n.HasVal() { + return constant.MakeUnknown() + } + return *n.e.(*constant.Value) +} + +// SetVal sets the constant.Value for the node, +// which must not have been used with SetOpt. +func (n *node) SetVal(v constant.Value) { + if n.hasOpt() { + base.Flag.LowerH = 1 + Dump("have Opt", n) + base.Fatalf("have Opt") + } + if n.Op() == OLITERAL { + AssertValidTypeForConst(n.Type(), v) + } + n.setHasVal(true) + n.e = &v +} + +// Int64Val returns n as an int64. +// n must be an integer or rune constant. +func (n *node) Int64Val() int64 { + if !IsConst(n, constant.Int) { + base.Fatalf("Int64Val(%v)", n) + } + x, ok := constant.Int64Val(n.Val()) + if !ok { + base.Fatalf("Int64Val(%v)", n) + } + return x +} + +// CanInt64 reports whether it is safe to call Int64Val() on n. +func (n *node) CanInt64() bool { + if !IsConst(n, constant.Int) { + return false + } + + // if the value inside n cannot be represented as an int64, the + // return value of Int64 is undefined + _, ok := constant.Int64Val(n.Val()) + return ok +} + +// Uint64Val returns n as an uint64. +// n must be an integer or rune constant. +func (n *node) Uint64Val() uint64 { + if !IsConst(n, constant.Int) { + base.Fatalf("Uint64Val(%v)", n) + } + x, ok := constant.Uint64Val(n.Val()) + if !ok { + base.Fatalf("Uint64Val(%v)", n) + } + return x +} + +// BoolVal returns n as a bool. +// n must be a boolean constant. +func (n *node) BoolVal() bool { + if !IsConst(n, constant.Bool) { + base.Fatalf("BoolVal(%v)", n) + } + return constant.BoolVal(n.Val()) +} + +// StringVal returns the value of a literal string Node as a string. +// n must be a string constant. +func (n *node) StringVal() string { + if !IsConst(n, constant.String) { + base.Fatalf("StringVal(%v)", n) + } + return constant.StringVal(n.Val()) +} + +// The Class of a variable/function describes the "storage class" +// of a variable or function. During parsing, storage classes are +// called declaration contexts. +type Class uint8 + +//go:generate stringer -type=Class +const ( + Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables + PEXTERN // global variables + PAUTO // local variables + PAUTOHEAP // local variables or parameters moved to heap + PPARAM // input arguments + PPARAMOUT // output results + PFUNC // global functions + + // Careful: Class is stored in three bits in Node.flags. + _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3) +) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index cafe47493b..079871879d 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -15,7 +15,6 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/types" "cmd/internal/obj" - "cmd/internal/objabi" "cmd/internal/src" ) @@ -379,41 +378,6 @@ func (n *node) SetBounded(b bool) { n.flags.set(nodeBounded, b) } -// MarkReadonly indicates that n is an ONAME with readonly contents. -func (n *node) MarkReadonly() { - if n.Op() != ONAME { - base.Fatalf("Node.MarkReadonly %v", n.Op()) - } - n.Name().SetReadonly(true) - // Mark the linksym as readonly immediately - // so that the SSA backend can use this information. - // It will be overridden later during dumpglobls. - n.Sym().Linksym().Type = objabi.SRODATA -} - -// Val returns the constant.Value for the node. -func (n *node) Val() constant.Value { - if !n.HasVal() { - return constant.MakeUnknown() - } - return *n.e.(*constant.Value) -} - -// SetVal sets the constant.Value for the node, -// which must not have been used with SetOpt. -func (n *node) SetVal(v constant.Value) { - if n.hasOpt() { - base.Flag.LowerH = 1 - Dump("have Opt", n) - base.Fatalf("have Opt") - } - if n.Op() == OLITERAL { - AssertValidTypeForConst(n.Type(), v) - } - n.setHasVal(true) - n.e = &v -} - // Opt returns the optimizer data for the node. func (n *node) Opt() interface{} { if !n.hasOpt() { @@ -500,235 +464,6 @@ func PkgFuncName(n Node) string { func (n *node) CanBeAnSSASym() { } -// Name holds Node fields used only by named nodes (ONAME, OTYPE, OPACK, OLABEL, some OLITERAL). -type Name struct { - Pack Node // real package for import . names - Pkg *types.Pkg // pkg for OPACK nodes - // 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 - Defn Node - // The ODCLFUNC node (for a static function/method or a closure) in which - // local variable or param is declared. - Curfn Node - Param *Param // additional fields for ONAME, OTYPE - Decldepth int32 // declaration loop depth, increased for every loop or label - // Unique number for ONAME nodes within a function. Function outputs - // (results) are numbered starting at one, followed by function inputs - // (parameters), and then local variables. Vargen is used to distinguish - // local variables/params with the same name. - Vargen int32 - flags bitset16 -} - -const ( - nameCaptured = 1 << iota // is the variable captured by a closure - nameReadonly - nameByval // is the variable captured by value or by reference - nameNeedzero // if it contains pointers, needs to be zeroed on function entry - nameAutoTemp // is the variable a temporary (implies no dwarf info. reset if escapes to heap) - nameUsed // for variable declared and not used error - nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original at n.Name.Defn - nameIsOutputParamHeapAddr // pointer to a result parameter's heap copy - nameAssigned // is the variable ever assigned to - nameAddrtaken // address taken, even if not moved to heap - nameInlFormal // PAUTO created by inliner, derived from callee formal - nameInlLocal // PAUTO created by inliner, derived from callee local - nameOpenDeferSlot // if temporary var storing info for open-coded defers - nameLibfuzzerExtraCounter // if PEXTERN should be assigned to __libfuzzer_extra_counters section -) - -func (n *Name) Captured() bool { return n.flags&nameCaptured != 0 } -func (n *Name) Readonly() bool { return n.flags&nameReadonly != 0 } -func (n *Name) Byval() bool { return n.flags&nameByval != 0 } -func (n *Name) Needzero() bool { return n.flags&nameNeedzero != 0 } -func (n *Name) AutoTemp() bool { return n.flags&nameAutoTemp != 0 } -func (n *Name) Used() bool { return n.flags&nameUsed != 0 } -func (n *Name) IsClosureVar() bool { return n.flags&nameIsClosureVar != 0 } -func (n *Name) IsOutputParamHeapAddr() bool { return n.flags&nameIsOutputParamHeapAddr != 0 } -func (n *Name) Assigned() bool { return n.flags&nameAssigned != 0 } -func (n *Name) Addrtaken() bool { return n.flags&nameAddrtaken != 0 } -func (n *Name) InlFormal() bool { return n.flags&nameInlFormal != 0 } -func (n *Name) InlLocal() bool { return n.flags&nameInlLocal != 0 } -func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 } -func (n *Name) LibfuzzerExtraCounter() bool { return n.flags&nameLibfuzzerExtraCounter != 0 } - -func (n *Name) SetCaptured(b bool) { n.flags.set(nameCaptured, b) } -func (n *Name) SetReadonly(b bool) { n.flags.set(nameReadonly, b) } -func (n *Name) SetByval(b bool) { n.flags.set(nameByval, b) } -func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) } -func (n *Name) SetAutoTemp(b bool) { n.flags.set(nameAutoTemp, b) } -func (n *Name) SetUsed(b bool) { n.flags.set(nameUsed, b) } -func (n *Name) SetIsClosureVar(b bool) { n.flags.set(nameIsClosureVar, b) } -func (n *Name) SetIsOutputParamHeapAddr(b bool) { n.flags.set(nameIsOutputParamHeapAddr, b) } -func (n *Name) SetAssigned(b bool) { n.flags.set(nameAssigned, b) } -func (n *Name) SetAddrtaken(b bool) { n.flags.set(nameAddrtaken, b) } -func (n *Name) SetInlFormal(b bool) { n.flags.set(nameInlFormal, b) } -func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b) } -func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) } -func (n *Name) SetLibfuzzerExtraCounter(b bool) { n.flags.set(nameLibfuzzerExtraCounter, b) } - -type Param struct { - Ntype Node - Heapaddr Node // temp holding heap address of param - - // ONAME PAUTOHEAP - Stackcopy Node // the PPARAM/PPARAMOUT on-stack slot (moved func params only) - - // ONAME closure linkage - // Consider: - // - // func f() { - // x := 1 // x1 - // func() { - // use(x) // x2 - // func() { - // use(x) // x3 - // --- parser is here --- - // }() - // }() - // } - // - // There is an original declaration of x and then a chain of mentions of x - // leading into the current function. Each time x is mentioned in a new closure, - // we create a variable representing x for use in that specific closure, - // since the way you get to x is different in each closure. - // - // Let's number the specific variables as shown in the code: - // x1 is the original x, x2 is when mentioned in the closure, - // and x3 is when mentioned in the closure in the closure. - // - // We keep these linked (assume N > 1): - // - // - x1.Defn = original declaration statement for x (like most variables) - // - x1.Innermost = current innermost closure x (in this case x3), or nil for none - // - x1.IsClosureVar() = false - // - // - xN.Defn = x1, N > 1 - // - xN.IsClosureVar() = true, N > 1 - // - x2.Outer = nil - // - xN.Outer = x(N-1), N > 2 - // - // - // When we look up x in the symbol table, we always get x1. - // Then we can use x1.Innermost (if not nil) to get the x - // for the innermost known closure function, - // but the first reference in a closure will find either no x1.Innermost - // or an x1.Innermost with .Funcdepth < Funcdepth. - // In that case, a new xN must be created, linked in with: - // - // xN.Defn = x1 - // xN.Outer = x1.Innermost - // x1.Innermost = xN - // - // When we finish the function, we'll process its closure variables - // and find xN and pop it off the list using: - // - // x1 := xN.Defn - // x1.Innermost = xN.Outer - // - // We leave x1.Innermost set so that we can still get to the original - // variable quickly. Not shown here, but once we're - // done parsing a function and no longer need xN.Outer for the - // lexical x reference links as described above, funcLit - // recomputes xN.Outer as the semantic x reference link tree, - // even filling in x in intermediate closures that might not - // have mentioned it along the way to inner closures that did. - // See funcLit for details. - // - // During the eventual compilation, then, for closure variables we have: - // - // xN.Defn = original variable - // xN.Outer = variable captured in next outward scope - // to make closure where xN appears - // - // Because of the sharding of pieces of the node, x.Defn means x.Name.Defn - // and x.Innermost/Outer means x.Name.Param.Innermost/Outer. - Innermost Node - Outer Node - - // OTYPE & ONAME //go:embed info, - // sharing storage to reduce gc.Param size. - // Extra is nil, or else *Extra is a *paramType or an *embedFileList. - Extra *interface{} -} - -type paramType struct { - flag PragmaFlag - alias bool -} - -type embedFileList []string - -// Pragma returns the PragmaFlag for p, which must be for an OTYPE. -func (p *Param) Pragma() PragmaFlag { - if p.Extra == nil { - return 0 - } - return (*p.Extra).(*paramType).flag -} - -// SetPragma sets the PragmaFlag for p, which must be for an OTYPE. -func (p *Param) SetPragma(flag PragmaFlag) { - if p.Extra == nil { - if flag == 0 { - return - } - p.Extra = new(interface{}) - *p.Extra = ¶mType{flag: flag} - return - } - (*p.Extra).(*paramType).flag = flag -} - -// Alias reports whether p, which must be for an OTYPE, is a type alias. -func (p *Param) Alias() bool { - if p.Extra == nil { - return false - } - t, ok := (*p.Extra).(*paramType) - if !ok { - return false - } - return t.alias -} - -// SetAlias sets whether p, which must be for an OTYPE, is a type alias. -func (p *Param) SetAlias(alias bool) { - if p.Extra == nil { - if !alias { - return - } - p.Extra = new(interface{}) - *p.Extra = ¶mType{alias: alias} - return - } - (*p.Extra).(*paramType).alias = alias -} - -// EmbedFiles returns the list of embedded files for p, -// which must be for an ONAME var. -func (p *Param) EmbedFiles() []string { - if p.Extra == nil { - return nil - } - return *(*p.Extra).(*embedFileList) -} - -// SetEmbedFiles sets the list of embedded files for p, -// which must be for an ONAME var. -func (p *Param) SetEmbedFiles(list []string) { - if p.Extra == nil { - if len(list) == 0 { - return - } - f := embedFileList(list) - p.Extra = new(interface{}) - *p.Extra = &f - return - } - *(*p.Extra).(*embedFileList) = list -} - // A Func corresponds to a single function in a Go program // (and vice versa: each function is denoted by exactly one *Func). // @@ -1369,49 +1104,6 @@ func (s NodeSet) Sorted(less func(Node, Node) bool) []Node { return res } -// NewNameAt returns a new ONAME Node associated with symbol s at position pos. -// The caller is responsible for setting n.Name.Curfn. -func NewNameAt(pos src.XPos, s *types.Sym) Node { - if s == nil { - base.Fatalf("newnamel nil") - } - - var x struct { - n node - m Name - p Param - } - n := &x.n - n.SetName(&x.m) - n.Name().Param = &x.p - - n.SetOp(ONAME) - n.SetPos(pos) - n.SetOrig(n) - - n.SetSym(s) - return n -} - -// The Class of a variable/function describes the "storage class" -// of a variable or function. During parsing, storage classes are -// called declaration contexts. -type Class uint8 - -//go:generate stringer -type=Class -const ( - Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables - PEXTERN // global variables - PAUTO // local variables - PAUTOHEAP // local variables or parameters moved to heap - PPARAM // input arguments - PPARAMOUT // output results - PFUNC // global functions - - // Careful: Class is stored in three bits in Node.flags. - _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3) -) - type PragmaFlag int16 const ( @@ -1550,62 +1242,6 @@ func IsConst(n Node, ct constant.Kind) bool { return ConstType(n) == ct } -// Int64Val returns n as an int64. -// n must be an integer or rune constant. -func (n *node) Int64Val() int64 { - if !IsConst(n, constant.Int) { - base.Fatalf("Int64Val(%v)", n) - } - x, ok := constant.Int64Val(n.Val()) - if !ok { - base.Fatalf("Int64Val(%v)", n) - } - return x -} - -// CanInt64 reports whether it is safe to call Int64Val() on n. -func (n *node) CanInt64() bool { - if !IsConst(n, constant.Int) { - return false - } - - // if the value inside n cannot be represented as an int64, the - // return value of Int64 is undefined - _, ok := constant.Int64Val(n.Val()) - return ok -} - -// Uint64Val returns n as an uint64. -// n must be an integer or rune constant. -func (n *node) Uint64Val() uint64 { - if !IsConst(n, constant.Int) { - base.Fatalf("Uint64Val(%v)", n) - } - x, ok := constant.Uint64Val(n.Val()) - if !ok { - base.Fatalf("Uint64Val(%v)", n) - } - return x -} - -// BoolVal returns n as a bool. -// n must be a boolean constant. -func (n *node) BoolVal() bool { - if !IsConst(n, constant.Bool) { - base.Fatalf("BoolVal(%v)", n) - } - return constant.BoolVal(n.Val()) -} - -// StringVal returns the value of a literal string Node as a string. -// n must be a string constant. -func (n *node) StringVal() string { - if !IsConst(n, constant.String) { - base.Fatalf("StringVal(%v)", n) - } - return constant.StringVal(n.Val()) -} - // rawcopy returns a shallow copy of n. // Note: copy or sepcopy (rather than rawcopy) is usually the // correct choice (see comment with Node.copy, below). From f6106d195db8bd7ef268e621f4a0d9ddbe9c58f6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 01:11:49 -0500 Subject: [PATCH 020/212] [dev.regabi] cmd/compile: add ir.PkgName OPACK was using a whole Node and Name and Param to hold about three fields. Give it its own implementation. Passes buildall w/ toolstash -cmp. Change-Id: I85a28b43d37183b2062d337b0b1b2eea52884e8c Reviewed-on: https://go-review.googlesource.com/c/go/+/274093 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/main.go | 11 ++++----- src/cmd/compile/internal/gc/noder.go | 22 +++++++++--------- src/cmd/compile/internal/gc/subr.go | 4 ++-- src/cmd/compile/internal/ir/name.go | 26 +++++++++++++++++++--- src/cmd/compile/internal/ir/node.go | 8 +------ src/cmd/compile/internal/ir/sizeof_test.go | 2 +- 6 files changed, 44 insertions(+), 29 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 30ee57c02d..7d2933f360 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -955,8 +955,9 @@ func clearImports() { // leave s->block set to cause redeclaration // errors if a conflicting top-level name is // introduced by a different file. - if !n.Name().Used() && base.SyntaxErrors() == 0 { - unused = append(unused, importedPkg{n.Pos(), n.Name().Pkg.Path, s.Name}) + p := n.(*ir.PkgName) + if !p.Used && base.SyntaxErrors() == 0 { + unused = append(unused, importedPkg{p.Pos(), p.Pkg.Path, s.Name}) } s.Def = nil continue @@ -964,9 +965,9 @@ func clearImports() { if IsAlias(s) { // throw away top-level name left over // from previous import . "x" - if n.Name() != nil && n.Name().Pack != nil && !n.Name().Pack.Name().Used() && base.SyntaxErrors() == 0 { - unused = append(unused, importedPkg{n.Name().Pack.Pos(), n.Name().Pack.Name().Pkg.Path, ""}) - n.Name().Pack.Name().SetUsed(true) + if name := n.Name(); name != nil && name.PkgName != nil && !name.PkgName.Used && base.SyntaxErrors() == 0 { + unused = append(unused, importedPkg{name.PkgName.Pos(), name.PkgName.Pkg.Path, ""}) + name.PkgName.Used = true } s.Def = nil continue diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index ecd50b87f6..54915d7693 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -356,9 +356,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) { my = lookup(ipkg.Name) } - pack := p.nod(imp, ir.OPACK, nil, nil) - pack.SetSym(my) - pack.Name().Pkg = ipkg + pack := ir.NewPkgName(p.pos(imp), my, ipkg) switch my.Name { case ".": @@ -685,8 +683,9 @@ func (p *noder) expr(expr syntax.Expr) ir.Node { // parser.new_dotname obj := p.expr(expr.X) if obj.Op() == ir.OPACK { - obj.Name().SetUsed(true) - return importName(obj.Name().Pkg.Lookup(expr.Sel.Value)) + pack := obj.(*ir.PkgName) + pack.Used = true + return importName(pack.Pkg.Lookup(expr.Sel.Value)) } n := nodSym(ir.OXDOT, obj, p.name(expr.Sel)) n.SetPos(p.pos(expr)) // lineno may have been changed by p.expr(expr.X) @@ -910,8 +909,8 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym { switch expr := expr.(type) { case *syntax.Name: name := p.name(expr) - if n := oldname(name); n.Name() != nil && n.Name().Pack != nil { - n.Name().Pack.Name().SetUsed(true) + if n := oldname(name); n.Name() != nil && n.Name().PkgName != nil { + n.Name().PkgName.Used = true } return name case *syntax.SelectorExpr: @@ -926,8 +925,9 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym { base.Errorf("%v is not a package", name) pkg = ir.LocalPkg } else { - def.Name().SetUsed(true) - pkg = def.Name().Pkg + def := def.(*ir.PkgName) + def.Used = true + pkg = def.Pkg } return pkg.Lookup(expr.Sel.Value) } @@ -1675,8 +1675,8 @@ func safeArg(name string) bool { func mkname(sym *types.Sym) ir.Node { n := oldname(sym) - if n.Name() != nil && n.Name().Pack != nil { - n.Name().Pack.Name().SetUsed(true) + if n.Name() != nil && n.Name().PkgName != nil { + n.Name().PkgName.Used = true } return n } diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 722876abf5..5c410ce3ba 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -102,7 +102,7 @@ func autolabel(prefix string) *types.Sym { // find all the exported symbols in package opkg // and make them available in the current package -func importdot(opkg *types.Pkg, pack ir.Node) { +func importdot(opkg *types.Pkg, pack *ir.PkgName) { n := 0 for _, s := range opkg.Syms { if s.Def == nil { @@ -124,7 +124,7 @@ func importdot(opkg *types.Pkg, pack ir.Node) { ir.Dump("s1def", ir.AsNode(s1.Def)) base.Fatalf("missing Name") } - ir.AsNode(s1.Def).Name().Pack = pack + ir.AsNode(s1.Def).Name().PkgName = pack s1.Origpkg = opkg n++ } diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index fc7a5049e0..64d5d2a2ed 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -9,13 +9,13 @@ import ( "cmd/compile/internal/types" "cmd/internal/objabi" "cmd/internal/src" + "fmt" "go/constant" ) -// Name holds Node fields used only by named nodes (ONAME, OTYPE, OPACK, OLABEL, some OLITERAL). +// Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL). type Name struct { - Pack Node // real package for import . names - Pkg *types.Pkg // pkg for OPACK nodes + PkgName *PkgName // real package for import . names // 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 Defn Node @@ -374,3 +374,23 @@ const ( // Careful: Class is stored in three bits in Node.flags. _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3) ) + +// A Pack is an identifier referring to an imported package. +type PkgName struct { + miniNode + sym *types.Sym + Pkg *types.Pkg + Used bool +} + +func (p *PkgName) String() string { return fmt.Sprint(p) } +func (p *PkgName) Format(s fmt.State, verb rune) { FmtNode(p, s, verb) } +func (p *PkgName) RawCopy() Node { c := *p; return &c } +func (p *PkgName) Sym() *types.Sym { return p.sym } + +func NewPkgName(pos src.XPos, sym *types.Sym, pkg *types.Pkg) *PkgName { + p := &PkgName{sym: sym, Pkg: pkg} + p.op = OPACK + p.pos = pos + return p +} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 079871879d..0023df97a8 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -1339,12 +1339,7 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { n.SetFunc(&x.f) n.Func().Decl = n case OPACK: - var x struct { - n node - m Name - } - n = &x.n - n.SetName(&x.m) + return NewPkgName(pos, nil, nil) case OEMPTY: return NewEmptyStmt(pos) case OBREAK, OCONTINUE, OFALL, OGOTO: @@ -1462,7 +1457,6 @@ var okForNod = [OEND]bool{ OOFFSETOF: true, OOR: true, OOROR: true, - OPACK: true, OPANIC: true, OPAREN: true, OPLUS: true, diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go index 0a9542fa44..a025cb5986 100644 --- a/src/cmd/compile/internal/ir/sizeof_test.go +++ b/src/cmd/compile/internal/ir/sizeof_test.go @@ -21,7 +21,7 @@ func TestSizeof(t *testing.T) { _64bit uintptr // size on 64bit platforms }{ {Func{}, 152, 280}, - {Name{}, 44, 80}, + {Name{}, 36, 64}, {Param{}, 44, 88}, {node{}, 88, 152}, } From 862f638a89c5ec721a53446fb1a74f9ad15893d5 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 01:41:13 -0500 Subject: [PATCH 021/212] [dev.regabi] cmd/compile: make ir.Name the ONAME Node implementation Before this CL, an ONAME Node was represented by three structs linked together: a node, a Name, and a Param. Previous CLs removed OLABEL and OPACK from the set of nodes that knew about Name. Now Name can be repurposed to *be* the ONAME Node implementation, replacing three linked structs totaling 152+64+88 = 304 bytes (64-bit) with a single 232-byte struct. Many expressions in the code become simpler as well, without having to use .Param. and sometimes even .Name(). (For a node n where n.Name() != nil, n.Name() == n.(*Name) now.) Passes buildall w/ toolstash -cmp. Change-Id: Ie719f1285c05623b9fd2faaa059e5b360a64b3be Reviewed-on: https://go-review.googlesource.com/c/go/+/274094 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/fmtmap_test.go | 1 + src/cmd/compile/internal/gc/alg.go | 2 +- src/cmd/compile/internal/gc/align.go | 10 +- src/cmd/compile/internal/gc/closure.go | 13 +- src/cmd/compile/internal/gc/dcl.go | 39 ++-- src/cmd/compile/internal/gc/embed.go | 6 +- src/cmd/compile/internal/gc/escape.go | 6 +- src/cmd/compile/internal/gc/gen.go | 10 +- src/cmd/compile/internal/gc/iexport.go | 2 +- src/cmd/compile/internal/gc/inl.go | 2 +- src/cmd/compile/internal/gc/main.go | 4 +- src/cmd/compile/internal/gc/noder.go | 17 +- src/cmd/compile/internal/gc/pgen.go | 2 +- src/cmd/compile/internal/gc/plive.go | 2 +- src/cmd/compile/internal/gc/subr.go | 2 +- src/cmd/compile/internal/gc/typecheck.go | 52 +++--- src/cmd/compile/internal/gc/universe.go | 9 - src/cmd/compile/internal/gc/walk.go | 24 +-- src/cmd/compile/internal/ir/expr.go | 47 +++++ src/cmd/compile/internal/ir/fmt.go | 8 +- src/cmd/compile/internal/ir/mini.go | 2 - src/cmd/compile/internal/ir/name.go | 200 ++++++++++----------- src/cmd/compile/internal/ir/node.go | 56 ++---- src/cmd/compile/internal/ir/sizeof_test.go | 5 +- 24 files changed, 256 insertions(+), 265 deletions(-) create mode 100644 src/cmd/compile/internal/ir/expr.go diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index 7a375604fd..978c83e5c2 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -22,6 +22,7 @@ package main_test var knownFormats = map[string]string{ "*bytes.Buffer %s": "", "*cmd/compile/internal/gc.EscLocation %v": "", + "*cmd/compile/internal/ir.Name %v": "", "*cmd/compile/internal/ir.node %v": "", "*cmd/compile/internal/ssa.Block %s": "", "*cmd/compile/internal/ssa.Block %v": "", diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go index d2762126ad..356f0eada7 100644 --- a/src/cmd/compile/internal/gc/alg.go +++ b/src/cmd/compile/internal/gc/alg.go @@ -311,7 +311,7 @@ func genhash(t *types.Type) *obj.LSym { hashel := hashfor(t.Elem()) n := ir.Nod(ir.ORANGE, nil, ir.Nod(ir.ODEREF, np, nil)) - ni := NewName(lookup("i")) + ni := ir.Node(NewName(lookup("i"))) ni.SetType(types.Types[types.TINT]) n.PtrList().Set1(ni) n.SetColas(true) diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index edf7d263a3..4f8f04d73d 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -126,8 +126,8 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 { // NOTE(rsc): This comment may be stale. // It's possible the ordering has changed and this is // now the common case. I'm not sure. - if n.Name().Param.Stackcopy != nil { - n.Name().Param.Stackcopy.SetOffset(o) + if n.Name().Stackcopy != nil { + n.Name().Stackcopy.SetOffset(o) n.SetOffset(0) } else { n.SetOffset(o) @@ -198,8 +198,10 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { } *path = append(*path, t) - if p := ir.AsNode(t.Nod).Name().Param; p != nil && findTypeLoop(p.Ntype.Type(), path) { - return true + if n := ir.AsNode(t.Nod); n != nil { + if name := n.Name(); name != nil && name.Ntype != nil && findTypeLoop(name.Ntype.Type(), path) { + return true + } } *path = (*path)[:len(*path)-1] } else { diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 2901ae41d6..7a1078326d 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -21,7 +21,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { fn := dcl.Func() fn.SetIsHiddenClosure(Curfn != nil) fn.Nname = newfuncnamel(p.pos(expr), ir.BlankNode.Sym(), fn) // filled in by typecheckclosure - fn.Nname.Name().Param.Ntype = xtype + fn.Nname.Name().Ntype = xtype fn.Nname.Name().Defn = dcl clo := p.nod(expr, ir.OCLOSURE, nil, nil) @@ -38,7 +38,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { for _, v := range fn.ClosureVars.Slice() { // Unlink from v1; see comment in syntax.go type Param for these fields. v1 := v.Name().Defn - v1.Name().Param.Innermost = v.Name().Param.Outer + v1.Name().Innermost = v.Name().Outer // If the closure usage of v is not dense, // we need to make it dense; now that we're out @@ -68,7 +68,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { // obtains f3's v, creating it if necessary (as it is in the example). // // capturevars will decide whether to use v directly or &v. - v.Name().Param.Outer = oldname(v.Sym()) + v.Name().Outer = oldname(v.Sym()).(*ir.Name) } return clo @@ -194,7 +194,8 @@ func capturevars(dcl ir.Node) { // so that the outer frame also grabs them and knows they escape. dowidth(v.Type()) - outer := v.Name().Param.Outer + var outer ir.Node + outer = v.Name().Outer outermost := v.Name().Defn // out parameters will be assigned to implicitly upon return. @@ -262,7 +263,7 @@ func transformclosure(dcl ir.Node) { // (accesses will implicitly deref &v). addr := NewName(lookup("&" + v.Sym().Name)) addr.SetType(types.NewPtr(v.Type())) - v.Name().Param.Heapaddr = addr + v.Name().Heapaddr = addr v = addr } @@ -312,7 +313,7 @@ func transformclosure(dcl ir.Node) { addr.Name().SetUsed(true) addr.Name().Curfn = dcl fn.Dcl = append(fn.Dcl, addr) - v.Name().Param.Heapaddr = addr + v.Name().Heapaddr = addr if v.Name().Byval() { cv = ir.Nod(ir.OADDR, cv, nil) } diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 2a7be137c0..04e6e7a596 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -12,7 +12,6 @@ import ( "cmd/internal/obj" "cmd/internal/src" "fmt" - "go/constant" "strings" ) @@ -64,11 +63,6 @@ func declare(n ir.Node, ctxt ir.Class) { return } - if n.Name() == nil { - // named OLITERAL needs Name; most OLITERALs don't. - n.SetName(new(ir.Name)) - } - s := n.Sym() // kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later. @@ -152,7 +146,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node { for _, v := range vl { v.SetOp(ir.ONAME) declare(v, dclcontext) - v.Name().Param.Ntype = t + v.Name().Ntype = t v.Name().Defn = as2 if Curfn != nil { init = append(init, ir.Nod(ir.ODCL, v, nil)) @@ -176,7 +170,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node { v.SetOp(ir.ONAME) declare(v, dclcontext) - v.Name().Param.Ntype = t + v.Name().Ntype = t if e != nil || Curfn != nil || ir.IsBlank(v) { if Curfn != nil { @@ -201,9 +195,8 @@ func newnoname(s *types.Sym) ir.Node { if s == nil { base.Fatalf("newnoname nil") } - n := ir.Nod(ir.ONONAME, nil, nil) - n.SetSym(s) - n.SetOffset(0) + n := ir.NewNameAt(base.Pos, s) + n.SetOp(ir.ONONAME) return n } @@ -220,7 +213,7 @@ func newfuncnamel(pos src.XPos, s *types.Sym, fn *ir.Func) ir.Node { // this generates a new name node for a name // being declared. -func dclname(s *types.Sym) ir.Node { +func dclname(s *types.Sym) *ir.Name { n := NewName(s) n.SetOp(ir.ONONAME) // caller will correct it return n @@ -277,7 +270,7 @@ func oldname(s *types.Sym) ir.Node { // are parsing x := 5 inside the closure, until we get to // the := it looks like a reference to the outer x so we'll // make x a closure variable unnecessarily. - c := n.Name().Param.Innermost + c := n.Name().Innermost if c == nil || c.Name().Curfn != Curfn { // Do not have a closure var for the active closure yet; make one. c = NewName(s) @@ -288,8 +281,8 @@ func oldname(s *types.Sym) ir.Node { // Link into list of active closure variables. // Popped from list in func funcLit. - c.Name().Param.Outer = n.Name().Param.Innermost - n.Name().Param.Innermost = c + c.Name().Outer = n.Name().Innermost + n.Name().Innermost = c Curfn.Func().ClosureVars.Append(c) } @@ -392,8 +385,8 @@ func funchdr(n ir.Node) { types.Markdcl() - if n.Func().Nname != nil && n.Func().Nname.Name().Param.Ntype != nil { - funcargs(n.Func().Nname.Name().Param.Ntype) + if n.Func().Nname != nil && n.Func().Nname.Name().Ntype != nil { + funcargs(n.Func().Nname.Name().Ntype) } else { funcargs2(n.Type()) } @@ -458,7 +451,7 @@ func funcarg(n ir.Node, ctxt ir.Class) { } n.SetRight(ir.NewNameAt(n.Pos(), n.Sym())) - n.Right().Name().Param.Ntype = n.Left() + n.Right().Name().Ntype = n.Left() n.Right().SetIsDDD(n.IsDDD()) declare(n.Right(), ctxt) @@ -554,8 +547,8 @@ func structfield(n ir.Node) *types.Field { checkembeddedtype(n.Type()) f.Embedded = 1 } - if n.HasVal() { - f.Note = constant.StringVal(n.Val()) + if n.Opt() != nil { + f.Note = n.Opt().(string) } base.Pos = lno @@ -640,7 +633,7 @@ func interfacefield(n ir.Node) *types.Field { base.Fatalf("interfacefield: oops %v\n", n) } - if n.HasVal() { + if n.Opt() != nil { base.Errorf("interface method cannot have annotation") } @@ -952,10 +945,10 @@ func dclfunc(sym *types.Sym, tfn ir.Node) ir.Node { fn := ir.Nod(ir.ODCLFUNC, nil, nil) fn.Func().Nname = newfuncnamel(base.Pos, sym, fn.Func()) fn.Func().Nname.Name().Defn = fn - fn.Func().Nname.Name().Param.Ntype = tfn + fn.Func().Nname.Name().Ntype = tfn setNodeNameFunc(fn.Func().Nname) funchdr(fn) - fn.Func().Nname.Name().Param.Ntype = typecheck(fn.Func().Nname.Name().Param.Ntype, ctxType) + fn.Func().Nname.Name().Ntype = typecheck(fn.Func().Nname.Name().Ntype, ctxType) return fn } diff --git a/src/cmd/compile/internal/gc/embed.go b/src/cmd/compile/internal/gc/embed.go index 33b05a5bf0..1c8ccdadef 100644 --- a/src/cmd/compile/internal/gc/embed.go +++ b/src/cmd/compile/internal/gc/embed.go @@ -115,13 +115,13 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Node, exprs []ir.Node, embeds [] numLocalEmbed++ v = ir.NewNameAt(v.Pos(), lookupN("embed.", numLocalEmbed)) v.Sym().Def = v - v.Name().Param.Ntype = typ + v.Name().Ntype = typ v.SetClass(ir.PEXTERN) externdcl = append(externdcl, v) exprs = []ir.Node{v} } - v.Name().Param.SetEmbedFiles(list) + v.Name().SetEmbedFiles(list) embedlist = append(embedlist, v) return exprs } @@ -193,7 +193,7 @@ func dumpembeds() { // initEmbed emits the init data for a //go:embed variable, // which is either a string, a []byte, or an embed.FS. func initEmbed(v ir.Node) { - files := v.Name().Param.EmbedFiles() + files := v.Name().EmbedFiles() switch kind := embedKind(v.Type()); kind { case embedUnknown: base.ErrorfAt(v.Pos(), "go:embed cannot apply to var of type %v", v.Type()) diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index e3ac883e95..351643ef5d 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -1895,7 +1895,7 @@ func moveToHeap(n ir.Node) { stackcopy.SetType(n.Type()) stackcopy.SetOffset(n.Offset()) stackcopy.SetClass(n.Class()) - stackcopy.Name().Param.Heapaddr = heapaddr + stackcopy.Name().Heapaddr = heapaddr if n.Class() == ir.PPARAMOUT { // Make sure the pointer to the heap copy is kept live throughout the function. // The function could panic at any point, and then a defer could recover. @@ -1904,7 +1904,7 @@ func moveToHeap(n ir.Node) { // See issue 16095. heapaddr.Name().SetIsOutputParamHeapAddr(true) } - n.Name().Param.Stackcopy = stackcopy + n.Name().Stackcopy = stackcopy // Substitute the stackcopy into the function variable list so that // liveness and other analyses use the underlying stack slot @@ -1931,7 +1931,7 @@ func moveToHeap(n ir.Node) { // Modify n in place so that uses of n now mean indirection of the heapaddr. n.SetClass(ir.PAUTOHEAP) n.SetOffset(0) - n.Name().Param.Heapaddr = heapaddr + n.Name().Heapaddr = heapaddr n.SetEsc(EscHeap) if base.Flag.LowerM != 0 { base.WarnfAt(n.Pos(), "moved to heap: %v", n) diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index cb640c7ccf..cf9e0d58bf 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -31,13 +31,13 @@ func sysvar(name string) *obj.LSym { // isParamStackCopy reports whether this is the on-stack copy of a // function parameter that moved to the heap. func isParamStackCopy(n ir.Node) bool { - return n.Op() == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name().Param.Heapaddr != nil + return n.Op() == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name().Heapaddr != nil } // isParamHeapCopy reports whether this is the on-heap copy of // a function parameter that moved to the heap. func isParamHeapCopy(n ir.Node) bool { - return n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name().Param.Stackcopy != nil + return n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name().Stackcopy != nil } // autotmpname returns the name for an autotmp variable numbered n. @@ -52,7 +52,7 @@ func autotmpname(n int) string { } // make a new Node off the books -func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) ir.Node { +func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) *ir.Name { if curfn == nil { base.Fatalf("no curfn for tempAt") } @@ -80,9 +80,9 @@ func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) ir.Node { dowidth(t) - return ir.Orig(n) + return n } -func temp(t *types.Type) ir.Node { +func temp(t *types.Type) *ir.Name { return tempAt(base.Pos, Curfn, t) } diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index c2ea599af4..88d3a6477c 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -1463,7 +1463,7 @@ func (w *exportWriter) localName(n ir.Node) { // PPARAM/PPARAMOUT, because we only want to include vargen in // non-param names. var v int32 - if n.Class() == ir.PAUTO || (n.Class() == ir.PAUTOHEAP && n.Name().Param.Stackcopy == nil) { + if n.Class() == ir.PAUTO || (n.Class() == ir.PAUTOHEAP && n.Name().Stackcopy == nil) { v = n.Name().Vargen } diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index d43d0d06af..102144aedf 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -982,7 +982,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { continue } - o := v.Name().Param.Outer + o := v.Name().Outer // make sure the outer param matches the inlining location // NB: if we enabled inlining of functions containing OCLOSURE or refined // the reassigned check via some sort of copy propagation this would most diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 7d2933f360..931626159d 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -253,7 +253,7 @@ func Main(archInit func(*Arch)) { timings.Start("fe", "typecheck", "top1") for i := 0; i < len(xtop); i++ { n := xtop[i] - if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left().Name().Param.Alias()) { + if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left().Name().Alias()) { xtop[i] = typecheck(n, ctxStmt) } } @@ -265,7 +265,7 @@ func Main(archInit func(*Arch)) { timings.Start("fe", "typecheck", "top2") for i := 0; i < len(xtop); i++ { n := xtop[i] - if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left().Name().Param.Alias() { + if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left().Name().Alias() { xtop[i] = typecheck(n, ctxStmt) } } diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 54915d7693..cbe8a24051 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -456,7 +456,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node { n.SetOp(ir.OLITERAL) declare(n, dclcontext) - n.Name().Param.Ntype = typ + n.Name().Ntype = typ n.Name().Defn = v n.SetIota(cs.iota) @@ -480,19 +480,18 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node { // decl.Type may be nil but in that case we got a syntax error during parsing typ := p.typeExprOrNil(decl.Type) - param := n.Name().Param - param.Ntype = typ - param.SetAlias(decl.Alias) + n.Ntype = typ + n.SetAlias(decl.Alias) if pragma, ok := decl.Pragma.(*Pragma); ok { if !decl.Alias { - param.SetPragma(pragma.Flag & TypePragmas) + n.SetPragma(pragma.Flag & TypePragmas) pragma.Flag &^= TypePragmas } p.checkUnused(pragma) } nod := p.nod(decl, ir.ODCLTYPE, n, nil) - if param.Alias() && !langSupported(1, 9, ir.LocalPkg) { + if n.Alias() && !langSupported(1, 9, ir.LocalPkg) { base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9") } return nod @@ -506,7 +505,7 @@ func (p *noder) declNames(names []*syntax.Name) []ir.Node { return nodes } -func (p *noder) declName(name *syntax.Name) ir.Node { +func (p *noder) declName(name *syntax.Name) *ir.Name { n := dclname(p.name(name)) n.SetPos(p.pos(name)) return n @@ -537,7 +536,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node { f.Func().Nname = newfuncnamel(p.pos(fun.Name), name, f.Func()) f.Func().Nname.Name().Defn = f - f.Func().Nname.Name().Param.Ntype = t + f.Func().Nname.Name().Ntype = t if pragma, ok := fun.Pragma.(*Pragma); ok { f.Func().Pragma = pragma.Flag & FuncPragmas @@ -872,7 +871,7 @@ func (p *noder) structType(expr *syntax.StructType) ir.Node { n = p.nodSym(field, ir.ODCLFIELD, p.typeExpr(field.Type), p.name(field.Name)) } if i < len(expr.TagList) && expr.TagList[i] != nil { - n.SetVal(p.basicLit(expr.TagList[i])) + n.SetOpt(constant.StringVal(p.basicLit(expr.TagList[i]))) } l = append(l, n) } diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index 221b733a07..b74b132632 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -667,7 +667,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []ir. // misleading location for the param (we want pointer-to-heap // and not stack). // TODO(thanm): generate a better location expression - stackcopy := n.Name().Param.Stackcopy + stackcopy := n.Name().Stackcopy if stackcopy != nil && (stackcopy.Class() == ir.PPARAM || stackcopy.Class() == ir.PPARAMOUT) { abbrev = dwarf.DW_ABRV_PARAM_LOCLIST isReturnValue = (stackcopy.Class() == ir.PPARAMOUT) diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index bd7696d859..e3a9b2a198 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -795,7 +795,7 @@ func (lv *Liveness) epilogue() { // Just to be paranoid. Heap addresses are PAUTOs. base.Fatalf("variable %v both output param and heap output param", n) } - if n.Name().Param.Heapaddr != nil { + if n.Name().Heapaddr != nil { // If this variable moved to the heap, then // its stack copy is not live. continue diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 5c410ce3ba..28703205d6 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -136,7 +136,7 @@ func importdot(opkg *types.Pkg, pack *ir.PkgName) { } // newname returns a new ONAME Node associated with symbol s. -func NewName(s *types.Sym) ir.Node { +func NewName(s *types.Sym) *ir.Name { n := ir.NewNameAt(base.Pos, s) n.Name().Curfn = Curfn return n diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 0c4a3ad833..4ab47fb406 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -259,12 +259,12 @@ func typecheck(n ir.Node, top int) (res ir.Node) { // are substituted. cycle := cycleFor(n) for _, n1 := range cycle { - if n1.Name() != nil && !n1.Name().Param.Alias() { + if n1.Name() != nil && !n1.Name().Alias() { // Cycle is ok. But if n is an alias type and doesn't // have a type yet, we have a recursive type declaration // with aliases that we can't handle properly yet. // Report an error rather than crashing later. - if n.Name() != nil && n.Name().Param.Alias() && n.Type() == nil { + if n.Name() != nil && n.Name().Alias() && n.Type() == nil { base.Pos = n.Pos() base.Fatalf("cannot handle alias type declaration (issue #25838): %v", n) } @@ -2412,9 +2412,6 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) { } n.SetOp(ir.OMETHEXPR) - if n.Name() == nil { - n.SetName(new(ir.Name)) - } n.SetRight(NewName(n.Sym())) n.SetSym(methodSym(t, n.Sym())) n.SetType(methodfunc(m.Type, n.Left().Type())) @@ -3228,7 +3225,7 @@ func typecheckas(n ir.Node) { // so that the conversion below happens). n.SetLeft(resolve(n.Left())) - if n.Left().Name() == nil || n.Left().Name().Defn != n || n.Left().Name().Param.Ntype != nil { + if n.Left().Name() == nil || n.Left().Name().Defn != n || n.Left().Name().Ntype != nil { n.SetLeft(typecheck(n.Left(), ctxExpr|ctxAssign)) } @@ -3247,7 +3244,7 @@ func typecheckas(n ir.Node) { } } - if n.Left().Name() != nil && n.Left().Name().Defn == n && n.Left().Name().Param.Ntype == nil { + if n.Left().Name() != nil && n.Left().Name().Defn == n && n.Left().Name().Ntype == nil { n.SetRight(defaultlit(n.Right(), nil)) n.Left().SetType(n.Right().Type()) } @@ -3283,7 +3280,7 @@ func typecheckas2(n ir.Node) { n1 = resolve(n1) ls[i1] = n1 - if n1.Name() == nil || n1.Name().Defn != n || n1.Name().Param.Ntype != nil { + if n1.Name() == nil || n1.Name().Defn != n || n1.Name().Ntype != nil { ls[i1] = typecheck(ls[i1], ctxExpr|ctxAssign) } } @@ -3308,7 +3305,7 @@ func typecheckas2(n ir.Node) { if nl.Type() != nil && nr.Type() != nil { rs[il] = assignconv(nr, nl.Type(), "assignment") } - if nl.Name() != nil && nl.Name().Defn == n && nl.Name().Param.Ntype == nil { + if nl.Name() != nil && nl.Name().Defn == n && nl.Name().Ntype == nil { rs[il] = defaultlit(rs[il], nil) nl.SetType(rs[il].Type()) } @@ -3342,7 +3339,7 @@ func typecheckas2(n ir.Node) { if f.Type != nil && l.Type() != nil { checkassignto(f.Type, l) } - if l.Name() != nil && l.Name().Defn == n && l.Name().Param.Ntype == nil { + if l.Name() != nil && l.Name().Defn == n && l.Name().Ntype == nil { l.SetType(f.Type) } } @@ -3378,7 +3375,7 @@ func typecheckas2(n ir.Node) { if l.Type() != nil && !l.Type().IsBoolean() { checkassignto(types.Types[types.TBOOL], l) } - if l.Name() != nil && l.Name().Defn == n && l.Name().Param.Ntype == nil { + if l.Name() != nil && l.Name().Defn == n && l.Name().Ntype == nil { l.SetType(types.Types[types.TBOOL]) } goto out @@ -3502,7 +3499,7 @@ func setUnderlying(t, underlying *types.Type) { } // Propagate go:notinheap pragma from the Name to the Type. - if n.Name() != nil && n.Name().Param != nil && n.Name().Param.Pragma()&ir.NotInHeap != 0 { + if n.Name() != nil && n.Name().Pragma()&ir.NotInHeap != 0 { t.SetNotInHeap(true) } @@ -3525,8 +3522,8 @@ func typecheckdeftype(n ir.Node) { } n.SetTypecheck(1) - n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType) - t := n.Name().Param.Ntype.Type() + n.Name().Ntype = typecheck(n.Name().Ntype, ctxType) + t := n.Name().Ntype.Type() if t == nil { n.SetDiag(true) n.SetType(nil) @@ -3586,10 +3583,10 @@ func typecheckdef(n ir.Node) { base.Fatalf("typecheckdef %v", n.Op()) case ir.OLITERAL: - if n.Name().Param.Ntype != nil { - n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType) - n.SetType(n.Name().Param.Ntype.Type()) - n.Name().Param.Ntype = nil + if n.Name().Ntype != nil { + n.Name().Ntype = typecheck(n.Name().Ntype, ctxType) + n.SetType(n.Name().Ntype.Type()) + n.Name().Ntype = nil if n.Type() == nil { n.SetDiag(true) goto ret @@ -3640,9 +3637,9 @@ func typecheckdef(n ir.Node) { } case ir.ONAME: - if n.Name().Param.Ntype != nil { - n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType) - n.SetType(n.Name().Param.Ntype.Type()) + if n.Name().Ntype != nil { + n.Name().Ntype = typecheck(n.Name().Ntype, ctxType) + n.SetType(n.Name().Ntype.Type()) if n.Type() == nil { n.SetDiag(true) goto ret @@ -3676,21 +3673,22 @@ func typecheckdef(n ir.Node) { n.Name().Defn = typecheck(n.Name().Defn, ctxStmt) // fills in n.Type case ir.OTYPE: - if p := n.Name().Param; p.Alias() { + n := n.(*ir.Name) + if n.Alias() { // Type alias declaration: Simply use the rhs type - no need // to create a new type. // If we have a syntax error, p.Ntype may be nil. - if p.Ntype != nil { - p.Ntype = typecheck(p.Ntype, ctxType) - n.SetType(p.Ntype.Type()) + if n.Ntype != nil { + n.Ntype = typecheck(n.Ntype, ctxType) + n.SetType(n.Ntype.Type()) if n.Type() == nil { n.SetDiag(true) goto ret } // For package-level type aliases, set n.Sym.Def so we can identify // it as a type alias during export. See also #31959. - if n.Name().Curfn == nil { - n.Sym().Def = p.Ntype + if n.Curfn == nil { + n.Sym().Def = n.Ntype } } break diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 978e53ac15..1068720748 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -110,7 +110,6 @@ func lexinit() { types.Types[etype] = t } s2.Def = typenod(t) - ir.AsNode(s2.Def).SetName(new(ir.Name)) } for _, s := range &builtinFuncs { @@ -132,13 +131,11 @@ func lexinit() { s := ir.BuiltinPkg.Lookup("true") s.Def = nodbool(true) ir.AsNode(s.Def).SetSym(lookup("true")) - ir.AsNode(s.Def).SetName(new(ir.Name)) ir.AsNode(s.Def).SetType(types.UntypedBool) s = ir.BuiltinPkg.Lookup("false") s.Def = nodbool(false) ir.AsNode(s.Def).SetSym(lookup("false")) - ir.AsNode(s.Def).SetName(new(ir.Name)) ir.AsNode(s.Def).SetType(types.UntypedBool) s = lookup("_") @@ -158,12 +155,10 @@ func lexinit() { s = ir.BuiltinPkg.Lookup("nil") s.Def = nodnil() ir.AsNode(s.Def).SetSym(s) - ir.AsNode(s.Def).SetName(new(ir.Name)) s = ir.BuiltinPkg.Lookup("iota") s.Def = ir.Nod(ir.OIOTA, nil, nil) ir.AsNode(s.Def).SetSym(s) - ir.AsNode(s.Def).SetName(new(ir.Name)) } func typeinit() { @@ -182,7 +177,6 @@ func typeinit() { types.Types[types.TUNSAFEPTR] = t t.Sym = unsafepkg.Lookup("Pointer") t.Sym.Def = typenod(t) - ir.AsNode(t.Sym.Def).SetName(new(ir.Name)) dowidth(types.Types[types.TUNSAFEPTR]) for et := types.TINT8; et <= types.TUINT64; et++ { @@ -359,7 +353,6 @@ func lexinit1() { types.Bytetype = types.New(types.TUINT8) types.Bytetype.Sym = s s.Def = typenod(types.Bytetype) - ir.AsNode(s.Def).SetName(new(ir.Name)) dowidth(types.Bytetype) // rune alias @@ -367,7 +360,6 @@ func lexinit1() { types.Runetype = types.New(types.TINT32) types.Runetype.Sym = s s.Def = typenod(types.Runetype) - ir.AsNode(s.Def).SetName(new(ir.Name)) dowidth(types.Runetype) // backend-dependent builtin types (e.g. int). @@ -385,7 +377,6 @@ func lexinit1() { t.Sym = s1 types.Types[s.etype] = t s1.Def = typenod(t) - ir.AsNode(s1.Def).SetName(new(ir.Name)) s1.Origpkg = ir.BuiltinPkg dowidth(t) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 87fe36b08a..c05aa0c372 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -196,7 +196,7 @@ func walkstmt(n ir.Node) ir.Node { if prealloc[v] == nil { prealloc[v] = callnew(v.Type()) } - nn := ir.Nod(ir.OAS, v.Name().Param.Heapaddr, prealloc[v]) + nn := ir.Nod(ir.OAS, v.Name().Heapaddr, prealloc[v]) nn.SetColas(true) nn = typecheck(nn, ctxStmt) return walkstmt(nn) @@ -286,7 +286,7 @@ func walkstmt(n ir.Node) ir.Node { } if cl == ir.PPARAMOUT { if isParamStackCopy(ln) { - ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name().Param.Heapaddr, nil), ctxExpr), nil) + ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name().Heapaddr, nil), ctxExpr), nil) } rl = append(rl, ln) } @@ -314,7 +314,7 @@ func walkstmt(n ir.Node) ir.Node { for i, nl := range lhs.FieldSlice() { nname := ir.AsNode(nl.Nname) if isParamHeapCopy(nname) { - nname = nname.Name().Param.Stackcopy + nname = nname.Name().Stackcopy } a := ir.Nod(ir.OAS, nname, rhs[i]) res[i] = convas(a, n.PtrInit()) @@ -456,7 +456,7 @@ func walkexpr(n ir.Node, init *ir.Nodes) ir.Node { } if n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP { - nn := ir.Nod(ir.ODEREF, n.Name().Param.Heapaddr, nil) + nn := ir.Nod(ir.ODEREF, n.Name().Heapaddr, nil) nn = typecheck(nn, ctxExpr) nn = walkexpr(nn, init) nn.Left().MarkNonNil() @@ -1160,7 +1160,7 @@ opswitch: if n.Type().Elem().Width >= maxImplicitStackVarSize { base.Fatalf("large ONEW with EscNone: %v", n) } - r := temp(n.Type().Elem()) + r := ir.Node(temp(n.Type().Elem())) r = ir.Nod(ir.OAS, r, nil) // zero temp r = typecheck(r, ctxStmt) init.Append(r) @@ -1776,7 +1776,7 @@ func ascompatet(nl ir.Nodes, nr *types.Type) []ir.Node { // Any assignment to an lvalue that might cause a function call must be // deferred until all the returned values have been read. if fncall(l, r.Type) { - tmp := temp(r.Type) + tmp := ir.Node(temp(r.Type)) tmp = typecheck(tmp, ctxExpr) a := ir.Nod(ir.OAS, l, tmp) a = convas(a, &mm) @@ -2174,7 +2174,7 @@ func reorder3save(n ir.Node, all []ir.Node, i int, early *[]ir.Node) ir.Node { return n } - q := temp(n.Type()) + q := ir.Node(temp(n.Type())) q = ir.Nod(ir.OAS, q, n) q = typecheck(q, ctxStmt) *early = append(*early, q) @@ -2411,7 +2411,7 @@ func paramstoheap(params *types.Type) []ir.Node { continue } - if stackcopy := v.Name().Param.Stackcopy; stackcopy != nil { + if stackcopy := v.Name().Stackcopy; stackcopy != nil { nn = append(nn, walkstmt(ir.Nod(ir.ODCL, v, nil))) if stackcopy.Class() == ir.PPARAM { nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, v, stackcopy), ctxStmt))) @@ -2432,7 +2432,7 @@ func paramstoheap(params *types.Type) []ir.Node { func zeroResults() { for _, f := range Curfn.Type().Results().Fields().Slice() { v := ir.AsNode(f.Nname) - if v != nil && v.Name().Param.Heapaddr != nil { + if v != nil && v.Name().Heapaddr != nil { // The local which points to the return value is the // thing that needs zeroing. This is already handled // by a Needzero annotation in plive.go:livenessepilogue. @@ -2445,7 +2445,7 @@ func zeroResults() { // I don't think the zeroing below matters. // The stack return value will never be marked as live anywhere in the function. // It is not written to until deferreturn returns. - v = v.Name().Param.Stackcopy + v = v.Name().Stackcopy } // Zero the stack location containing f. Curfn.Func().Enter.Append(ir.NodAt(Curfn.Pos(), ir.OAS, v, nil)) @@ -2461,7 +2461,7 @@ func returnsfromheap(params *types.Type) []ir.Node { if v == nil { continue } - if stackcopy := v.Name().Param.Stackcopy; stackcopy != nil && stackcopy.Class() == ir.PPARAMOUT { + if stackcopy := v.Name().Stackcopy; stackcopy != nil && stackcopy.Class() == ir.PPARAMOUT { nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, stackcopy, v), ctxStmt))) } } @@ -3155,7 +3155,7 @@ func copyany(n ir.Node, init *ir.Nodes, runtimecall bool) ir.Node { fn := syslook("memmove") fn = substArgTypes(fn, nl.Type().Elem(), nl.Type().Elem()) - nwid := temp(types.Types[types.TUINTPTR]) + nwid := ir.Node(temp(types.Types[types.TUINTPTR])) setwid := ir.Nod(ir.OAS, nwid, conv(nlen, types.Types[types.TUINTPTR])) ne.PtrBody().Append(setwid) nwid = ir.Nod(ir.OMUL, nwid, nodintconst(nl.Type().Elem().Width)) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go new file mode 100644 index 0000000000..418351742e --- /dev/null +++ b/src/cmd/compile/internal/ir/expr.go @@ -0,0 +1,47 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ir + +import ( + "cmd/compile/internal/types" +) + +// A miniStmt is a miniNode with extra fields common to expressions. +// TODO(rsc): Once we are sure about the contents, compact the bools +// into a bit field and leave extra bits available for implementations +// embedding miniExpr. Right now there are ~60 unused bits sitting here. +type miniExpr struct { + miniNode + typ *types.Type + init Nodes // TODO(rsc): Don't require every Node to have an init + opt interface{} // TODO(rsc): Don't require every Node to have an opt? + flags bitset8 +} + +const ( + miniExprHasCall = 1 << iota + miniExprImplicit + miniExprNonNil + miniExprTransient + miniExprBounded +) + +func (n *miniExpr) Type() *types.Type { return n.typ } +func (n *miniExpr) SetType(x *types.Type) { n.typ = x } +func (n *miniExpr) Opt() interface{} { return n.opt } +func (n *miniExpr) SetOpt(x interface{}) { n.opt = x } +func (n *miniExpr) HasCall() bool { return n.flags&miniExprHasCall != 0 } +func (n *miniExpr) SetHasCall(b bool) { n.flags.set(miniExprHasCall, b) } +func (n *miniExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } +func (n *miniExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } +func (n *miniExpr) NonNil() bool { return n.flags&miniExprNonNil != 0 } +func (n *miniExpr) MarkNonNil() { n.flags |= miniExprNonNil } +func (n *miniExpr) Transient() bool { return n.flags&miniExprTransient != 0 } +func (n *miniExpr) SetTransient(b bool) { n.flags.set(miniExprTransient, b) } +func (n *miniExpr) Bounded() bool { return n.flags&miniExprBounded != 0 } +func (n *miniExpr) SetBounded(b bool) { n.flags.set(miniExprBounded, b) } +func (n *miniExpr) Init() Nodes { return n.init } +func (n *miniExpr) PtrInit() *Nodes { return &n.init } +func (n *miniExpr) SetInit(x Nodes) { n.init = x } diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 24318d501f..e749778030 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1615,9 +1615,9 @@ func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { } else { mode.Fprintf(s, "%v%j", n.Op(), n) } - if recur && n.Type() == nil && n.Name() != nil && n.Name().Param != nil && n.Name().Param.Ntype != nil { + if recur && n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil { indent(s) - mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Param.Ntype) + mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Ntype) } case OASOP: @@ -1625,9 +1625,9 @@ func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { case OTYPE: mode.Fprintf(s, "%v %v%j type=%v", n.Op(), n.Sym(), n, n.Type()) - if recur && n.Type() == nil && n.Name() != nil && n.Name().Param != nil && n.Name().Param.Ntype != nil { + if recur && n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil { indent(s) - mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Param.Ntype) + mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Ntype) } } diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index 608c2bed81..248fe232cb 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -130,7 +130,6 @@ func (n *miniNode) SetType(*types.Type) { panic(n.no("SetType")) } func (n *miniNode) Func() *Func { return nil } func (n *miniNode) SetFunc(*Func) { panic(n.no("SetFunc")) } func (n *miniNode) Name() *Name { return nil } -func (n *miniNode) SetName(*Name) { panic(n.no("SetName")) } func (n *miniNode) Sym() *types.Sym { return nil } func (n *miniNode) SetSym(*types.Sym) { panic(n.no("SetSym")) } func (n *miniNode) Offset() int64 { return types.BADWIDTH } @@ -164,7 +163,6 @@ func (n *miniNode) SetIndexMapLValue(bool) { panic(n.no("SetIndexMapLValue")) func (n *miniNode) ResetAux() { panic(n.no("ResetAux")) } func (n *miniNode) HasBreak() bool { panic(n.no("HasBreak")) } func (n *miniNode) SetHasBreak(bool) { panic(n.no("SetHasBreak")) } -func (n *miniNode) HasVal() bool { return false } func (n *miniNode) Val() constant.Value { panic(n.no("Val")) } func (n *miniNode) SetVal(v constant.Value) { panic(n.no("SetVal")) } func (n *miniNode) Int64Val() int64 { panic(n.no("Int64Val")) } diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 64d5d2a2ed..d330745cfb 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -15,29 +15,38 @@ import ( // Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL). type Name struct { + miniExpr + subOp Op // uint8 + class Class // uint8 + flags bitset16 + pragma PragmaFlag // int16 + sym *types.Sym + typ *types.Type + fn *Func + offset int64 + val constant.Value + orig Node + embedFiles *[]string // list of embedded files, for ONAME var + PkgName *PkgName // real package for import . names // 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 Defn Node // The ODCLFUNC node (for a static function/method or a closure) in which // local variable or param is declared. - Curfn Node - Param *Param // additional fields for ONAME, OTYPE - Decldepth int32 // declaration loop depth, increased for every loop or label + Curfn Node // Unique number for ONAME nodes within a function. Function outputs // (results) are numbered starting at one, followed by function inputs // (parameters), and then local variables. Vargen is used to distinguish // local variables/params with the same name. - Vargen int32 - flags bitset16 -} + Vargen int32 + Decldepth int32 // declaration loop depth, increased for every loop or label -type Param struct { Ntype Node - Heapaddr Node // temp holding heap address of param + Heapaddr *Name // temp holding heap address of param // ONAME PAUTOHEAP - Stackcopy Node // the PPARAM/PPARAMOUT on-stack slot (moved func params only) + Stackcopy *Name // the PPARAM/PPARAMOUT on-stack slot (moved func params only) // ONAME closure linkage // Consider: @@ -108,114 +117,88 @@ type Param struct { // // Because of the sharding of pieces of the node, x.Defn means x.Name.Defn // and x.Innermost/Outer means x.Name.Param.Innermost/Outer. - Innermost Node - Outer Node - - // OTYPE & ONAME //go:embed info, - // sharing storage to reduce gc.Param size. - // Extra is nil, or else *Extra is a *paramType or an *embedFileList. - Extra *interface{} + Innermost *Name + Outer *Name } // NewNameAt returns a new ONAME Node associated with symbol s at position pos. // The caller is responsible for setting n.Name.Curfn. -func NewNameAt(pos src.XPos, s *types.Sym) Node { - if s == nil { - base.Fatalf("newnamel nil") +func NewNameAt(pos src.XPos, sym *types.Sym) *Name { + if sym == nil { + base.Fatalf("NewNameAt nil") } + return newNameAt(pos, sym) +} - var x struct { - n node - m Name - p Param - } - n := &x.n - n.SetName(&x.m) - n.Name().Param = &x.p - - n.SetOp(ONAME) - n.SetPos(pos) - n.SetOrig(n) - - n.SetSym(s) +// newNameAt is like NewNameAt but allows sym == nil. +func newNameAt(pos src.XPos, sym *types.Sym) *Name { + n := new(Name) + n.op = ONAME + n.pos = pos + n.orig = n + n.sym = sym return n } -type paramType struct { - flag PragmaFlag - alias bool +func (n *Name) String() string { return fmt.Sprint(n) } +func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *Name) RawCopy() Node { c := *n; return &c } +func (n *Name) Name() *Name { return n } +func (n *Name) Sym() *types.Sym { return n.sym } +func (n *Name) SetSym(x *types.Sym) { n.sym = x } +func (n *Name) Orig() Node { return n.orig } +func (n *Name) SetOrig(x Node) { n.orig = x } +func (n *Name) SubOp() Op { return n.subOp } +func (n *Name) SetSubOp(x Op) { n.subOp = x } +func (n *Name) Class() Class { return n.class } +func (n *Name) SetClass(x Class) { n.class = x } +func (n *Name) Func() *Func { return n.fn } +func (n *Name) SetFunc(x *Func) { n.fn = x } +func (n *Name) Offset() int64 { return n.offset } +func (n *Name) SetOffset(x int64) { n.offset = x } +func (n *Name) Iota() int64 { return n.offset } +func (n *Name) SetIota(x int64) { n.offset = x } + +func (n *Name) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OLITERAL, ONONAME, ONAME, OTYPE, OIOTA: + n.op = op + } } // Pragma returns the PragmaFlag for p, which must be for an OTYPE. -func (p *Param) Pragma() PragmaFlag { - if p.Extra == nil { - return 0 - } - return (*p.Extra).(*paramType).flag -} +func (n *Name) Pragma() PragmaFlag { return n.pragma } // SetPragma sets the PragmaFlag for p, which must be for an OTYPE. -func (p *Param) SetPragma(flag PragmaFlag) { - if p.Extra == nil { - if flag == 0 { - return - } - p.Extra = new(interface{}) - *p.Extra = ¶mType{flag: flag} - return - } - (*p.Extra).(*paramType).flag = flag -} +func (n *Name) SetPragma(flag PragmaFlag) { n.pragma = flag } // Alias reports whether p, which must be for an OTYPE, is a type alias. -func (p *Param) Alias() bool { - if p.Extra == nil { - return false - } - t, ok := (*p.Extra).(*paramType) - if !ok { - return false - } - return t.alias -} +func (n *Name) Alias() bool { return n.flags&nameAlias != 0 } // SetAlias sets whether p, which must be for an OTYPE, is a type alias. -func (p *Param) SetAlias(alias bool) { - if p.Extra == nil { - if !alias { - return - } - p.Extra = new(interface{}) - *p.Extra = ¶mType{alias: alias} - return - } - (*p.Extra).(*paramType).alias = alias -} - -type embedFileList []string +func (n *Name) SetAlias(alias bool) { n.flags.set(nameAlias, alias) } // EmbedFiles returns the list of embedded files for p, // which must be for an ONAME var. -func (p *Param) EmbedFiles() []string { - if p.Extra == nil { +func (n *Name) EmbedFiles() []string { + if n.embedFiles == nil { return nil } - return *(*p.Extra).(*embedFileList) + return *n.embedFiles } // SetEmbedFiles sets the list of embedded files for p, // which must be for an ONAME var. -func (p *Param) SetEmbedFiles(list []string) { - if p.Extra == nil { - if len(list) == 0 { - return - } - f := embedFileList(list) - p.Extra = new(interface{}) - *p.Extra = &f +func (n *Name) SetEmbedFiles(list []string) { + if n.embedFiles == nil && list == nil { return } - *(*p.Extra).(*embedFileList) = list + if n.embedFiles == nil { + n.embedFiles = new([]string) + } + *n.embedFiles = list } const ( @@ -233,6 +216,8 @@ const ( nameInlLocal // PAUTO created by inliner, derived from callee local nameOpenDeferSlot // if temporary var storing info for open-coded defers nameLibfuzzerExtraCounter // if PEXTERN should be assigned to __libfuzzer_extra_counters section + nameIsDDD // is function argument a ... + nameAlias // is type name an alias ) func (n *Name) Captured() bool { return n.flags&nameCaptured != 0 } @@ -249,9 +234,10 @@ func (n *Name) InlFormal() bool { return n.flags&nameInlFormal != 0 func (n *Name) InlLocal() bool { return n.flags&nameInlLocal != 0 } func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 } func (n *Name) LibfuzzerExtraCounter() bool { return n.flags&nameLibfuzzerExtraCounter != 0 } +func (n *Name) IsDDD() bool { return n.flags&nameIsDDD != 0 } func (n *Name) SetCaptured(b bool) { n.flags.set(nameCaptured, b) } -func (n *Name) SetReadonly(b bool) { n.flags.set(nameReadonly, b) } +func (n *Name) setReadonly(b bool) { n.flags.set(nameReadonly, b) } func (n *Name) SetByval(b bool) { n.flags.set(nameByval, b) } func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) } func (n *Name) SetAutoTemp(b bool) { n.flags.set(nameAutoTemp, b) } @@ -264,13 +250,14 @@ func (n *Name) SetInlFormal(b bool) { n.flags.set(nameInlFormal, b) func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b) } func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) } func (n *Name) SetLibfuzzerExtraCounter(b bool) { n.flags.set(nameLibfuzzerExtraCounter, b) } +func (n *Name) SetIsDDD(b bool) { n.flags.set(nameIsDDD, b) } // MarkReadonly indicates that n is an ONAME with readonly contents. -func (n *node) MarkReadonly() { +func (n *Name) MarkReadonly() { if n.Op() != ONAME { base.Fatalf("Node.MarkReadonly %v", n.Op()) } - n.Name().SetReadonly(true) + n.Name().setReadonly(true) // Mark the linksym as readonly immediately // so that the SSA backend can use this information. // It will be overridden later during dumpglobls. @@ -278,31 +265,26 @@ func (n *node) MarkReadonly() { } // Val returns the constant.Value for the node. -func (n *node) Val() constant.Value { - if !n.HasVal() { +func (n *Name) Val() constant.Value { + if n.val == nil { return constant.MakeUnknown() } - return *n.e.(*constant.Value) + return n.val } // SetVal sets the constant.Value for the node, // which must not have been used with SetOpt. -func (n *node) SetVal(v constant.Value) { - if n.hasOpt() { - base.Flag.LowerH = 1 - Dump("have Opt", n) - base.Fatalf("have Opt") +func (n *Name) SetVal(v constant.Value) { + if n.op != OLITERAL { + panic(n.no("SetVal")) } - if n.Op() == OLITERAL { - AssertValidTypeForConst(n.Type(), v) - } - n.setHasVal(true) - n.e = &v + AssertValidTypeForConst(n.Type(), v) + n.val = v } // Int64Val returns n as an int64. // n must be an integer or rune constant. -func (n *node) Int64Val() int64 { +func (n *Name) Int64Val() int64 { if !IsConst(n, constant.Int) { base.Fatalf("Int64Val(%v)", n) } @@ -314,7 +296,7 @@ func (n *node) Int64Val() int64 { } // CanInt64 reports whether it is safe to call Int64Val() on n. -func (n *node) CanInt64() bool { +func (n *Name) CanInt64() bool { if !IsConst(n, constant.Int) { return false } @@ -327,7 +309,7 @@ func (n *node) CanInt64() bool { // Uint64Val returns n as an uint64. // n must be an integer or rune constant. -func (n *node) Uint64Val() uint64 { +func (n *Name) Uint64Val() uint64 { if !IsConst(n, constant.Int) { base.Fatalf("Uint64Val(%v)", n) } @@ -340,7 +322,7 @@ func (n *node) Uint64Val() uint64 { // BoolVal returns n as a bool. // n must be a boolean constant. -func (n *node) BoolVal() bool { +func (n *Name) BoolVal() bool { if !IsConst(n, constant.Bool) { base.Fatalf("BoolVal(%v)", n) } @@ -349,7 +331,7 @@ func (n *node) BoolVal() bool { // StringVal returns the value of a literal string Node as a string. // n must be a string constant. -func (n *node) StringVal() string { +func (n *Name) StringVal() string { if !IsConst(n, constant.String) { base.Fatalf("StringVal(%v)", n) } diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 0023df97a8..a6a24774b5 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -59,7 +59,6 @@ type Node interface { Func() *Func SetFunc(x *Func) Name() *Name - SetName(x *Name) Sym() *types.Sym SetSym(x *types.Sym) Offset() int64 @@ -93,7 +92,6 @@ type Node interface { SetHasBreak(x bool) MarkReadonly() Val() constant.Value - HasVal() bool SetVal(v constant.Value) Int64Val() int64 Uint64Val() uint64 @@ -149,11 +147,8 @@ type node struct { // func fn *Func - // ONAME, OTYPE, OPACK, OLABEL, some OLITERAL - name *Name - - sym *types.Sym // various - e interface{} // Opt or Val, see methods below + sym *types.Sym // various + opt interface{} // Various. Usually an offset into a struct. For example: // - ONAME nodes that refer to local variables use it to identify their stack frame position. @@ -185,8 +180,7 @@ func (n *node) Type() *types.Type { return n.typ } func (n *node) SetType(x *types.Type) { n.typ = x } func (n *node) Func() *Func { return n.fn } func (n *node) SetFunc(x *Func) { n.fn = x } -func (n *node) Name() *Name { return n.name } -func (n *node) SetName(x *Name) { n.name = x } +func (n *node) Name() *Name { return nil } func (n *node) Sym() *types.Sym { return n.sym } func (n *node) SetSym(x *types.Sym) { n.sym = x } func (n *node) Pos() src.XPos { return n.pos } @@ -208,6 +202,14 @@ func (n *node) PtrList() *Nodes { return &n.list } func (n *node) Rlist() Nodes { return n.rlist } func (n *node) SetRlist(x Nodes) { n.rlist = x } func (n *node) PtrRlist() *Nodes { return &n.rlist } +func (n *node) MarkReadonly() { panic("node.MarkReadOnly") } +func (n *node) Val() constant.Value { panic("node.Val") } +func (n *node) SetVal(constant.Value) { panic("node.SetVal") } +func (n *node) Int64Val() int64 { panic("node.Int64Val") } +func (n *node) CanInt64() bool { return false } +func (n *node) Uint64Val() uint64 { panic("node.Uint64Val") } +func (n *node) BoolVal() bool { panic("node.BoolVal") } +func (n *node) StringVal() string { panic("node.StringVal") } func (n *node) SetOp(op Op) { if !okForNod[op] { @@ -305,8 +307,6 @@ const ( _, nodeBounded // bounds check unnecessary _, nodeHasCall // expression contains a function call _, nodeLikely // if statement condition likely - _, nodeHasVal // node.E contains a Val - _, nodeHasOpt // node.E contains an Opt _, nodeEmbedded // ODCLFIELD embedded type ) @@ -326,8 +326,6 @@ func (n *node) Transient() bool { return n.flags&nodeTransient != 0 } func (n *node) Bounded() bool { return n.flags&nodeBounded != 0 } func (n *node) HasCall() bool { return n.flags&nodeHasCall != 0 } func (n *node) Likely() bool { return n.flags&nodeLikely != 0 } -func (n *node) HasVal() bool { return n.flags&nodeHasVal != 0 } -func (n *node) hasOpt() bool { return n.flags&nodeHasOpt != 0 } func (n *node) Embedded() bool { return n.flags&nodeEmbedded != 0 } func (n *node) SetClass(b Class) { n.flags.set3(nodeClass, uint8(b)) } @@ -344,8 +342,6 @@ func (n *node) SetColas(b bool) { n.flags.set(nodeColas, b) } func (n *node) SetTransient(b bool) { n.flags.set(nodeTransient, b) } func (n *node) SetHasCall(b bool) { n.flags.set(nodeHasCall, b) } func (n *node) SetLikely(b bool) { n.flags.set(nodeLikely, b) } -func (n *node) setHasVal(b bool) { n.flags.set(nodeHasVal, b) } -func (n *node) setHasOpt(b bool) { n.flags.set(nodeHasOpt, b) } func (n *node) SetEmbedded(b bool) { n.flags.set(nodeEmbedded, b) } // MarkNonNil marks a pointer n as being guaranteed non-nil, @@ -380,29 +376,13 @@ func (n *node) SetBounded(b bool) { // Opt returns the optimizer data for the node. func (n *node) Opt() interface{} { - if !n.hasOpt() { - return nil - } - return n.e + return n.opt } // SetOpt sets the optimizer data for the node, which must not have been used with SetVal. // SetOpt(nil) is ignored for Vals to simplify call sites that are clearing Opts. func (n *node) SetOpt(x interface{}) { - if x == nil { - if n.hasOpt() { - n.setHasOpt(false) - n.e = nil - } - return - } - if n.HasVal() { - base.Flag.LowerH = 1 - Dump("have Val", n) - base.Fatalf("have Val") - } - n.setHasOpt(true) - n.e = x + n.opt = x } func (n *node) Iota() int64 { @@ -1344,6 +1324,10 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { return NewEmptyStmt(pos) case OBREAK, OCONTINUE, OFALL, OGOTO: return NewBranchStmt(pos, op, nil) + case OLITERAL, OTYPE, OIOTA: + n := newNameAt(pos, nil) + n.SetOp(op) + return n case OLABEL: return NewLabelStmt(pos, nil) default: @@ -1428,13 +1412,11 @@ var okForNod = [OEND]bool{ OINDEXMAP: true, OINLCALL: true, OINLMARK: true, - OIOTA: true, OITAB: true, OKEY: true, OLABEL: true, OLE: true, OLEN: true, - OLITERAL: true, OLSH: true, OLT: true, OMAKE: true, @@ -1446,13 +1428,11 @@ var okForNod = [OEND]bool{ OMETHEXPR: true, OMOD: true, OMUL: true, - ONAME: true, ONE: true, ONEG: true, ONEW: true, ONEWOBJ: true, ONIL: true, - ONONAME: true, ONOT: true, OOFFSETOF: true, OOR: true, @@ -1499,7 +1479,7 @@ var okForNod = [OEND]bool{ OTINTER: true, OTMAP: true, OTSTRUCT: true, - OTYPE: true, + OTYPE: true, // TODO: Remove once setTypeNode is gone. OTYPESW: true, OVARDEF: true, OVARKILL: true, diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go index a025cb5986..8a0b078b9b 100644 --- a/src/cmd/compile/internal/ir/sizeof_test.go +++ b/src/cmd/compile/internal/ir/sizeof_test.go @@ -21,9 +21,8 @@ func TestSizeof(t *testing.T) { _64bit uintptr // size on 64bit platforms }{ {Func{}, 152, 280}, - {Name{}, 36, 64}, - {Param{}, 44, 88}, - {node{}, 88, 152}, + {Name{}, 132, 232}, + {node{}, 84, 144}, } for _, tt := range tests { From 65ae15ac5d43ad82f664e5a914d74c7549568c93 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 07:13:54 -0500 Subject: [PATCH 022/212] [dev.regabi] cmd/compile: move func code from node.go to func.go No code changes here, only copying of text. This will make the diffs in a future CL readable. Passes buildall w/ toolstash -cmp. Change-Id: I325a62e79edd82f1437769891ea63a32f51c0170 Reviewed-on: https://go-review.googlesource.com/c/go/+/274095 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/func.go | 216 ++++++++++++++++++++++++++++ src/cmd/compile/internal/ir/node.go | 205 -------------------------- 2 files changed, 216 insertions(+), 205 deletions(-) create mode 100644 src/cmd/compile/internal/ir/func.go diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go new file mode 100644 index 0000000000..1566125955 --- /dev/null +++ b/src/cmd/compile/internal/ir/func.go @@ -0,0 +1,216 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ir + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/types" + "cmd/internal/obj" + "cmd/internal/src" +) + +// A Func corresponds to a single function in a Go program +// (and vice versa: each function is denoted by exactly one *Func). +// +// There are multiple nodes that represent a Func in the IR. +// +// The ONAME node (Func.Name) is used for plain references to it. +// The ODCLFUNC node (Func.Decl) is used for its declaration code. +// The OCLOSURE node (Func.Closure) is used for a reference to a +// function literal. +// +// A Func for an imported function will have only an ONAME node. +// A declared function or method has an ONAME and an ODCLFUNC. +// A function literal is represented directly by an OCLOSURE, but it also +// has an ODCLFUNC (and a matching ONAME) representing the compiled +// underlying form of the closure, which accesses the captured variables +// using a special data structure passed in a register. +// +// A method declaration is represented like functions, except f.Sym +// will be the qualified method name (e.g., "T.m") and +// f.Func.Shortname is the bare method name (e.g., "m"). +// +// A method expression (T.M) is represented as an OMETHEXPR node, +// in which n.Left and n.Right point to the type and method, respectively. +// Each distinct mention of a method expression in the source code +// constructs a fresh node. +// +// A method value (t.M) is represented by ODOTMETH/ODOTINTER +// when it is called directly and by OCALLPART otherwise. +// These are like method expressions, except that for ODOTMETH/ODOTINTER, +// the method name is stored in Sym instead of Right. +// Each OCALLPART ends up being implemented as a new +// function, a bit like a closure, with its own ODCLFUNC. +// The OCALLPART has uses n.Func to record the linkage to +// the generated ODCLFUNC (as n.Func.Decl), but there is no +// pointer from the Func back to the OCALLPART. +type Func struct { + Nname Node // ONAME node + Decl Node // ODCLFUNC node + OClosure Node // OCLOSURE node + + Shortname *types.Sym + + // Extra entry code for the function. For example, allocate and initialize + // memory for escaping parameters. + Enter Nodes + Exit Nodes + // ONAME nodes for all params/locals for this func/closure, does NOT + // include closurevars until transformclosure runs. + Dcl []Node + + ClosureEnter Nodes // list of ONAME nodes of captured variables + ClosureType Node // closure representation type + ClosureCalled bool // closure is only immediately called + ClosureVars Nodes // closure params; each has closurevar set + + // Parents records the parent scope of each scope within a + // function. The root scope (0) has no parent, so the i'th + // scope's parent is stored at Parents[i-1]. + Parents []ScopeID + + // Marks records scope boundary changes. + Marks []Mark + + // Closgen tracks how many closures have been generated within + // this function. Used by closurename for creating unique + // function names. + Closgen int + + FieldTrack map[*types.Sym]struct{} + DebugInfo interface{} + LSym *obj.LSym + + Inl *Inline + + Label int32 // largest auto-generated label in this function + + Endlineno src.XPos + WBPos src.XPos // position of first write barrier; see SetWBPos + + Pragma PragmaFlag // go:xxx function annotations + + flags bitset16 + NumDefers int // number of defer calls in the function + NumReturns int // number of explicit returns in the function + + // nwbrCalls records the LSyms of functions called by this + // function for go:nowritebarrierrec analysis. Only filled in + // if nowritebarrierrecCheck != nil. + NWBRCalls *[]SymAndPos +} + +// An Inline holds fields used for function bodies that can be inlined. +type Inline struct { + Cost int32 // heuristic cost of inlining this function + + // Copies of Func.Dcl and Nbody for use during inlining. + Dcl []Node + Body []Node +} + +// A Mark represents a scope boundary. +type Mark struct { + // Pos is the position of the token that marks the scope + // change. + Pos src.XPos + + // Scope identifies the innermost scope to the right of Pos. + Scope ScopeID +} + +// A ScopeID represents a lexical scope within a function. +type ScopeID int32 + +const ( + funcDupok = 1 << iota // duplicate definitions ok + funcWrapper // is method wrapper + funcNeedctxt // function uses context register (has closure variables) + funcReflectMethod // function calls reflect.Type.Method or MethodByName + // true if closure inside a function; false if a simple function or a + // closure in a global variable initialization + funcIsHiddenClosure + funcHasDefer // contains a defer statement + funcNilCheckDisabled // disable nil checks when compiling this function + funcInlinabilityChecked // inliner has already determined whether the function is inlinable + funcExportInline // include inline body in export data + funcInstrumentBody // add race/msan instrumentation during SSA construction + funcOpenCodedDeferDisallowed // can't do open-coded defers +) + +type SymAndPos struct { + Sym *obj.LSym // LSym of callee + Pos src.XPos // line of call +} + +func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 } +func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 } +func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 } +func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 } +func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 } +func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 } +func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 } +func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 0 } +func (f *Func) ExportInline() bool { return f.flags&funcExportInline != 0 } +func (f *Func) InstrumentBody() bool { return f.flags&funcInstrumentBody != 0 } +func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 } + +func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) } +func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, 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) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) } +func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) } +func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) } +func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) } +func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInline, b) } +func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) } +func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) } + +func (f *Func) SetWBPos(pos src.XPos) { + if base.Debug.WB != 0 { + base.WarnfAt(pos, "write barrier") + } + if !f.WBPos.IsKnown() { + f.WBPos = pos + } +} + +// funcname returns the name (without the package) of the function n. +func FuncName(n Node) string { + if n == nil || n.Func() == nil || n.Func().Nname == nil { + return "" + } + return n.Func().Nname.Sym().Name +} + +// pkgFuncName returns the name of the function referenced by n, with package prepended. +// This differs from the compiler's internal convention where local functions lack a package +// because the ultimate consumer of this is a human looking at an IDE; package is only empty +// if the compilation package is actually the empty string. +func PkgFuncName(n Node) string { + var s *types.Sym + if n == nil { + return "" + } + if n.Op() == ONAME { + s = n.Sym() + } else { + if n.Func() == nil || n.Func().Nname == nil { + return "" + } + s = n.Func().Nname.Sym() + } + pkg := s.Pkg + + p := base.Ctxt.Pkgpath + if pkg != nil && pkg.Path != "" { + p = pkg.Path + } + if p == "" { + return s.Name + } + return p + "." + s.Name +} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index a6a24774b5..1b01032c9b 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -14,7 +14,6 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/types" - "cmd/internal/obj" "cmd/internal/src" ) @@ -403,209 +402,10 @@ func MayBeShared(n Node) bool { return false } -// funcname returns the name (without the package) of the function n. -func FuncName(n Node) string { - if n == nil || n.Func() == nil || n.Func().Nname == nil { - return "" - } - return n.Func().Nname.Sym().Name -} - -// pkgFuncName returns the name of the function referenced by n, with package prepended. -// This differs from the compiler's internal convention where local functions lack a package -// because the ultimate consumer of this is a human looking at an IDE; package is only empty -// if the compilation package is actually the empty string. -func PkgFuncName(n Node) string { - var s *types.Sym - if n == nil { - return "" - } - if n.Op() == ONAME { - s = n.Sym() - } else { - if n.Func() == nil || n.Func().Nname == nil { - return "" - } - s = n.Func().Nname.Sym() - } - pkg := s.Pkg - - p := base.Ctxt.Pkgpath - if pkg != nil && pkg.Path != "" { - p = pkg.Path - } - if p == "" { - return s.Name - } - return p + "." + s.Name -} - // The compiler needs *Node to be assignable to cmd/compile/internal/ssa.Sym. func (n *node) CanBeAnSSASym() { } -// A Func corresponds to a single function in a Go program -// (and vice versa: each function is denoted by exactly one *Func). -// -// There are multiple nodes that represent a Func in the IR. -// -// The ONAME node (Func.Name) is used for plain references to it. -// The ODCLFUNC node (Func.Decl) is used for its declaration code. -// The OCLOSURE node (Func.Closure) is used for a reference to a -// function literal. -// -// A Func for an imported function will have only an ONAME node. -// A declared function or method has an ONAME and an ODCLFUNC. -// A function literal is represented directly by an OCLOSURE, but it also -// has an ODCLFUNC (and a matching ONAME) representing the compiled -// underlying form of the closure, which accesses the captured variables -// using a special data structure passed in a register. -// -// A method declaration is represented like functions, except f.Sym -// will be the qualified method name (e.g., "T.m") and -// f.Func.Shortname is the bare method name (e.g., "m"). -// -// A method expression (T.M) is represented as an OMETHEXPR node, -// in which n.Left and n.Right point to the type and method, respectively. -// Each distinct mention of a method expression in the source code -// constructs a fresh node. -// -// A method value (t.M) is represented by ODOTMETH/ODOTINTER -// when it is called directly and by OCALLPART otherwise. -// These are like method expressions, except that for ODOTMETH/ODOTINTER, -// the method name is stored in Sym instead of Right. -// Each OCALLPART ends up being implemented as a new -// function, a bit like a closure, with its own ODCLFUNC. -// The OCALLPART has uses n.Func to record the linkage to -// the generated ODCLFUNC (as n.Func.Decl), but there is no -// pointer from the Func back to the OCALLPART. -type Func struct { - Nname Node // ONAME node - Decl Node // ODCLFUNC node - OClosure Node // OCLOSURE node - - Shortname *types.Sym - - // Extra entry code for the function. For example, allocate and initialize - // memory for escaping parameters. - Enter Nodes - Exit Nodes - // ONAME nodes for all params/locals for this func/closure, does NOT - // include closurevars until transformclosure runs. - Dcl []Node - - ClosureEnter Nodes // list of ONAME nodes of captured variables - ClosureType Node // closure representation type - ClosureCalled bool // closure is only immediately called - ClosureVars Nodes // closure params; each has closurevar set - - // Parents records the parent scope of each scope within a - // function. The root scope (0) has no parent, so the i'th - // scope's parent is stored at Parents[i-1]. - Parents []ScopeID - - // Marks records scope boundary changes. - Marks []Mark - - // Closgen tracks how many closures have been generated within - // this function. Used by closurename for creating unique - // function names. - Closgen int - - FieldTrack map[*types.Sym]struct{} - DebugInfo interface{} - LSym *obj.LSym - - Inl *Inline - - Label int32 // largest auto-generated label in this function - - Endlineno src.XPos - WBPos src.XPos // position of first write barrier; see SetWBPos - - Pragma PragmaFlag // go:xxx function annotations - - flags bitset16 - NumDefers int // number of defer calls in the function - NumReturns int // number of explicit returns in the function - - // nwbrCalls records the LSyms of functions called by this - // function for go:nowritebarrierrec analysis. Only filled in - // if nowritebarrierrecCheck != nil. - NWBRCalls *[]SymAndPos -} - -// An Inline holds fields used for function bodies that can be inlined. -type Inline struct { - Cost int32 // heuristic cost of inlining this function - - // Copies of Func.Dcl and Nbody for use during inlining. - Dcl []Node - Body []Node -} - -// A Mark represents a scope boundary. -type Mark struct { - // Pos is the position of the token that marks the scope - // change. - Pos src.XPos - - // Scope identifies the innermost scope to the right of Pos. - Scope ScopeID -} - -// A ScopeID represents a lexical scope within a function. -type ScopeID int32 - -const ( - funcDupok = 1 << iota // duplicate definitions ok - funcWrapper // is method wrapper - funcNeedctxt // function uses context register (has closure variables) - funcReflectMethod // function calls reflect.Type.Method or MethodByName - // true if closure inside a function; false if a simple function or a - // closure in a global variable initialization - funcIsHiddenClosure - funcHasDefer // contains a defer statement - funcNilCheckDisabled // disable nil checks when compiling this function - funcInlinabilityChecked // inliner has already determined whether the function is inlinable - funcExportInline // include inline body in export data - funcInstrumentBody // add race/msan instrumentation during SSA construction - funcOpenCodedDeferDisallowed // can't do open-coded defers -) - -func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 } -func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 } -func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 } -func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 } -func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 } -func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 } -func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 } -func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 0 } -func (f *Func) ExportInline() bool { return f.flags&funcExportInline != 0 } -func (f *Func) InstrumentBody() bool { return f.flags&funcInstrumentBody != 0 } -func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 } - -func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) } -func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, 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) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) } -func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) } -func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) } -func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) } -func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInline, b) } -func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) } -func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) } - -func (f *Func) SetWBPos(pos src.XPos) { - if base.Debug.WB != 0 { - base.WarnfAt(pos, "write barrier") - } - if !f.WBPos.IsKnown() { - f.WBPos = pos - } -} - //go:generate stringer -type=Op -trimprefix=O type Op uint8 @@ -1111,11 +911,6 @@ const ( GoBuildPragma ) -type SymAndPos struct { - Sym *obj.LSym // LSym of callee - Pos src.XPos // line of call -} - func AsNode(n types.IRNode) Node { if n == nil { return nil From c4bd0b7474f169a60acf66306a4a721f790e36c9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 07:23:50 -0500 Subject: [PATCH 023/212] [dev.regabi] cmd/compile: make ir.Func the ODCLFUNC Node implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this CL, an ODCLFUNC Node was represented by both a node struct and a Func struct (and a Name for the ONAME, which isn't changing here). Now Func can be repurposed as the ODCLFUNC implementation, replacing the two structs totaling 280+144 = 424 bytes (64-bit) with a single 320-byte struct. Using the *Func as the node also gives us a clear, typed answer to “which node should we use to represent functions?” The next CL will clean up uses. This CL is just the trivial change in representation. Passes buildall w/ toolstash -cmp. Change-Id: Ie6d670da91d6eb8d67a85f8f83630b9586dc7443 Reviewed-on: https://go-review.googlesource.com/c/go/+/274096 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/fmt.go | 7 +++++ src/cmd/compile/internal/ir/func.go | 34 ++++++++++++++++++++++ src/cmd/compile/internal/ir/node.go | 9 +----- src/cmd/compile/internal/ir/sizeof_test.go | 2 +- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index e749778030..3822c4c73b 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1269,6 +1269,13 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { mode.Fprintf(s, ")") } + case ODCLFUNC: + if sym := n.Sym(); sym != nil { + fmt.Fprint(s, smodeString(sym, mode)) + return + } + mode.Fprintf(s, "") + case ONAME: // Special case: name used as local variable in export. // _ becomes ~b%d internally; print as _ for export diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 1566125955..57ec0707e9 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -9,6 +9,7 @@ import ( "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/src" + "fmt" ) // A Func corresponds to a single function in a Go program @@ -47,6 +48,11 @@ import ( // the generated ODCLFUNC (as n.Func.Decl), but there is no // pointer from the Func back to the OCALLPART. type Func struct { + miniNode + typ *types.Type + body Nodes + iota int64 + Nname Node // ONAME node Decl Node // ODCLFUNC node OClosure Node // OCLOSURE node @@ -102,6 +108,34 @@ type Func struct { NWBRCalls *[]SymAndPos } +func NewFunc(pos src.XPos) *Func { + f := new(Func) + f.pos = pos + f.op = ODCLFUNC + f.Decl = f + f.iota = -1 + return f +} + +func (f *Func) String() string { return fmt.Sprint(f) } +func (f *Func) Format(s fmt.State, verb rune) { FmtNode(f, s, verb) } +func (f *Func) RawCopy() Node { panic(f.no("RawCopy")) } +func (f *Func) Func() *Func { return f } +func (f *Func) Body() Nodes { return f.body } +func (f *Func) PtrBody() *Nodes { return &f.body } +func (f *Func) SetBody(x Nodes) { f.body = x } +func (f *Func) Type() *types.Type { return f.typ } +func (f *Func) SetType(x *types.Type) { f.typ = x } +func (f *Func) Iota() int64 { return f.iota } +func (f *Func) SetIota(x int64) { f.iota = x } + +func (f *Func) Sym() *types.Sym { + if f.Nname != nil { + return f.Nname.Sym() + } + return nil +} + // An Inline holds fields used for function bodies that can be inlined. type Inline struct { Cost int32 // heuristic cost of inlining this function diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 1b01032c9b..02a5d7769a 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -1106,13 +1106,7 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { var n *node switch op { case ODCLFUNC: - var x struct { - n node - f Func - } - n = &x.n - n.SetFunc(&x.f) - n.Func().Decl = n + return NewFunc(pos) case OPACK: return NewPkgName(pos, nil, nil) case OEMPTY: @@ -1179,7 +1173,6 @@ var okForNod = [OEND]bool{ ODCL: true, ODCLCONST: true, ODCLFIELD: true, - ODCLFUNC: true, ODCLTYPE: true, ODDD: true, ODEFER: true, diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go index 8a0b078b9b..8597ad492a 100644 --- a/src/cmd/compile/internal/ir/sizeof_test.go +++ b/src/cmd/compile/internal/ir/sizeof_test.go @@ -20,7 +20,7 @@ func TestSizeof(t *testing.T) { _32bit uintptr // size on 32bit platforms _64bit uintptr // size on 64bit platforms }{ - {Func{}, 152, 280}, + {Func{}, 180, 320}, {Name{}, 132, 232}, {node{}, 84, 144}, } From e84b27bec587e4393533e83e3ea1cbf1ed548425 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 07:31:18 -0500 Subject: [PATCH 024/212] [dev.regabi] cmd/compile: clean up Name and Func uses Now that we have specific types for ONAME and ODCLFUNC nodes (*Name and *Func), use them throughout the compiler to be more precise about what data is being operated on. This is a somewhat large CL, but once you start applying the types in a few places, you end up needing to apply them to many other places to keep everything type-checking. A lot of code also melts away as types are added. Passes buildall w/ toolstash -cmp. Change-Id: I21dd9b945d701c470332bac5394fca744a5b232d Reviewed-on: https://go-review.googlesource.com/c/go/+/274097 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/fmtmap_test.go | 8 +- src/cmd/compile/internal/gc/alg.go | 12 +- src/cmd/compile/internal/gc/bexport.go | 2 +- src/cmd/compile/internal/gc/closure.go | 142 +++++++------ src/cmd/compile/internal/gc/dcl.go | 121 ++++++----- src/cmd/compile/internal/gc/dwinl.go | 2 + src/cmd/compile/internal/gc/escape.go | 80 ++++--- src/cmd/compile/internal/gc/export.go | 6 +- src/cmd/compile/internal/gc/gen.go | 12 +- src/cmd/compile/internal/gc/go.go | 6 +- src/cmd/compile/internal/gc/gsubr.go | 12 +- src/cmd/compile/internal/gc/iexport.go | 16 +- src/cmd/compile/internal/gc/iimport.go | 34 +-- src/cmd/compile/internal/gc/init.go | 12 +- src/cmd/compile/internal/gc/initorder.go | 10 +- src/cmd/compile/internal/gc/inl.go | 229 ++++++++++----------- src/cmd/compile/internal/gc/main.go | 26 +-- src/cmd/compile/internal/gc/noder.go | 63 +++--- src/cmd/compile/internal/gc/obj.go | 2 +- src/cmd/compile/internal/gc/order.go | 6 +- src/cmd/compile/internal/gc/pgen.go | 72 ++++--- src/cmd/compile/internal/gc/pgen_test.go | 18 +- src/cmd/compile/internal/gc/plive.go | 22 +- src/cmd/compile/internal/gc/racewalk.go | 18 +- src/cmd/compile/internal/gc/range.go | 2 +- src/cmd/compile/internal/gc/scc.go | 30 +-- src/cmd/compile/internal/gc/ssa.go | 82 ++++---- src/cmd/compile/internal/gc/subr.go | 15 +- src/cmd/compile/internal/gc/typecheck.go | 56 ++--- src/cmd/compile/internal/gc/walk.go | 79 +++---- src/cmd/compile/internal/ir/fmt.go | 20 +- src/cmd/compile/internal/ir/func.go | 34 +-- src/cmd/compile/internal/ir/name.go | 7 +- src/cmd/compile/internal/ir/sizeof_test.go | 4 +- 34 files changed, 627 insertions(+), 633 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index 978c83e5c2..e949a89d93 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -22,6 +22,12 @@ package main_test var knownFormats = map[string]string{ "*bytes.Buffer %s": "", "*cmd/compile/internal/gc.EscLocation %v": "", + "*cmd/compile/internal/ir.Func %+v": "", + "*cmd/compile/internal/ir.Func %L": "", + "*cmd/compile/internal/ir.Func %v": "", + "*cmd/compile/internal/ir.Name %#v": "", + "*cmd/compile/internal/ir.Name %+v": "", + "*cmd/compile/internal/ir.Name %L": "", "*cmd/compile/internal/ir.Name %v": "", "*cmd/compile/internal/ir.node %v": "", "*cmd/compile/internal/ssa.Block %s": "", @@ -54,6 +60,7 @@ var knownFormats = map[string]string{ "*math/big.Float %f": "", "*math/big.Int %s": "", "[16]byte %x": "", + "[]*cmd/compile/internal/ir.Name %v": "", "[]*cmd/compile/internal/ssa.Block %v": "", "[]*cmd/compile/internal/ssa.Value %v": "", "[][]string %q": "", @@ -77,7 +84,6 @@ var knownFormats = map[string]string{ "cmd/compile/internal/ir.Class %d": "", "cmd/compile/internal/ir.Class %v": "", "cmd/compile/internal/ir.FmtMode %d": "", - "cmd/compile/internal/ir.Node %#v": "", "cmd/compile/internal/ir.Node %+S": "", "cmd/compile/internal/ir.Node %+v": "", "cmd/compile/internal/ir.Node %L": "", diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go index 356f0eada7..b40a56fe39 100644 --- a/src/cmd/compile/internal/gc/alg.go +++ b/src/cmd/compile/internal/gc/alg.go @@ -382,8 +382,8 @@ func genhash(t *types.Type) *obj.LSym { funcbody() - fn.Func().SetDupok(true) - fn = typecheck(fn, ctxStmt) + fn.SetDupok(true) + typecheckFunc(fn) Curfn = fn typecheckslice(fn.Body().Slice(), ctxStmt) @@ -393,7 +393,7 @@ func genhash(t *types.Type) *obj.LSym { testdclstack() } - fn.Func().SetNilCheckDisabled(true) + fn.SetNilCheckDisabled(true) xtop = append(xtop, fn) // Build closure. It doesn't close over any variables, so @@ -761,8 +761,8 @@ func geneq(t *types.Type) *obj.LSym { funcbody() - fn.Func().SetDupok(true) - fn = typecheck(fn, ctxStmt) + fn.SetDupok(true) + typecheckFunc(fn) Curfn = fn typecheckslice(fn.Body().Slice(), ctxStmt) @@ -776,7 +776,7 @@ func geneq(t *types.Type) *obj.LSym { // We are comparing a struct or an array, // neither of which can be nil, and our comparisons // are shallow. - fn.Func().SetNilCheckDisabled(true) + fn.SetNilCheckDisabled(true) xtop = append(xtop, fn) // Generate a closure which points at the function we just generated. diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index a470b842ff..dbbac559ae 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -16,7 +16,7 @@ type exporter struct { // markObject visits a reachable object. func (p *exporter) markObject(n ir.Node) { if n.Op() == ir.ONAME && n.Class() == ir.PFUNC { - inlFlood(n) + inlFlood(n.(*ir.Name)) } p.markType(n.Type()) diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 7a1078326d..0cf59ee0eb 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -17,28 +17,27 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { xtype := p.typeExpr(expr.Type) ntype := p.typeExpr(expr.Type) - dcl := p.nod(expr, ir.ODCLFUNC, nil, nil) - fn := dcl.Func() + fn := ir.NewFunc(p.pos(expr)) fn.SetIsHiddenClosure(Curfn != nil) - fn.Nname = newfuncnamel(p.pos(expr), ir.BlankNode.Sym(), fn) // filled in by typecheckclosure - fn.Nname.Name().Ntype = xtype - fn.Nname.Name().Defn = dcl + fn.Nname = newFuncNameAt(p.pos(expr), ir.BlankNode.Sym(), fn) // filled in by typecheckclosure + fn.Nname.Ntype = xtype + fn.Nname.Defn = fn clo := p.nod(expr, ir.OCLOSURE, nil, nil) clo.SetFunc(fn) fn.ClosureType = ntype fn.OClosure = clo - p.funcBody(dcl, expr.Body) + p.funcBody(fn, expr.Body) // closure-specific variables are hanging off the // ordinary ones in the symbol table; see oldname. // unhook them. // make the list of pointers for the closure call. - for _, v := range fn.ClosureVars.Slice() { + for _, v := range fn.ClosureVars { // Unlink from v1; see comment in syntax.go type Param for these fields. - v1 := v.Name().Defn - v1.Name().Innermost = v.Name().Outer + v1 := v.Defn + v1.Name().Innermost = v.Outer // If the closure usage of v is not dense, // we need to make it dense; now that we're out @@ -68,7 +67,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { // obtains f3's v, creating it if necessary (as it is in the example). // // capturevars will decide whether to use v directly or &v. - v.Name().Outer = oldname(v.Sym()).(*ir.Name) + v.Outer = oldname(v.Sym()).(*ir.Name) } return clo @@ -80,26 +79,25 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { // separate pass from type-checking. func typecheckclosure(clo ir.Node, top int) { fn := clo.Func() - dcl := fn.Decl // Set current associated iota value, so iota can be used inside // function in ConstSpec, see issue #22344 if x := getIotaValue(); x >= 0 { - dcl.SetIota(x) + fn.SetIota(x) } fn.ClosureType = typecheck(fn.ClosureType, ctxType) clo.SetType(fn.ClosureType.Type()) - fn.ClosureCalled = top&ctxCallee != 0 + fn.SetClosureCalled(top&ctxCallee != 0) - // Do not typecheck dcl twice, otherwise, we will end up pushing - // dcl to xtop multiple times, causing initLSym called twice. + // Do not typecheck fn twice, otherwise, we will end up pushing + // fn to xtop multiple times, causing initLSym called twice. // See #30709 - if dcl.Typecheck() == 1 { + if fn.Typecheck() == 1 { return } - for _, ln := range fn.ClosureVars.Slice() { - n := ln.Name().Defn + for _, ln := range fn.ClosureVars { + n := ln.Defn if !n.Name().Captured() { n.Name().SetCaptured(true) if n.Name().Decldepth == 0 { @@ -116,7 +114,7 @@ func typecheckclosure(clo ir.Node, top int) { fn.Nname.SetSym(closurename(Curfn)) setNodeNameFunc(fn.Nname) - dcl = typecheck(dcl, ctxStmt) + typecheckFunc(fn) // Type check the body now, but only if we're inside a function. // At top level (in a variable initialization: curfn==nil) we're not @@ -124,29 +122,29 @@ func typecheckclosure(clo ir.Node, top int) { // underlying closure function we create is added to xtop. if Curfn != nil && clo.Type() != nil { oldfn := Curfn - Curfn = dcl + Curfn = fn olddd := decldepth decldepth = 1 - typecheckslice(dcl.Body().Slice(), ctxStmt) + typecheckslice(fn.Body().Slice(), ctxStmt) decldepth = olddd Curfn = oldfn } - xtop = append(xtop, dcl) + xtop = append(xtop, fn) } // globClosgen is like Func.Closgen, but for the global scope. -var globClosgen int +var globClosgen int32 // closurename generates a new unique name for a closure within // outerfunc. -func closurename(outerfunc ir.Node) *types.Sym { +func closurename(outerfunc *ir.Func) *types.Sym { outer := "glob." prefix := "func" gen := &globClosgen if outerfunc != nil { - if outerfunc.Func().OClosure != nil { + if outerfunc.OClosure != nil { prefix = "" } @@ -155,8 +153,8 @@ func closurename(outerfunc ir.Node) *types.Sym { // There may be multiple functions named "_". In those // cases, we can't use their individual Closgens as it // would lead to name clashes. - if !ir.IsBlank(outerfunc.Func().Nname) { - gen = &outerfunc.Func().Closgen + if !ir.IsBlank(outerfunc.Nname) { + gen = &outerfunc.Closgen } } @@ -172,11 +170,10 @@ var capturevarscomplete bool // by value or by reference. // We use value capturing for values <= 128 bytes that are never reassigned // after capturing (effectively constant). -func capturevars(dcl ir.Node) { +func capturevars(fn *ir.Func) { lno := base.Pos - base.Pos = dcl.Pos() - fn := dcl.Func() - cvars := fn.ClosureVars.Slice() + base.Pos = fn.Pos() + cvars := fn.ClosureVars out := cvars[:0] for _, v := range cvars { if v.Type() == nil { @@ -195,12 +192,12 @@ func capturevars(dcl ir.Node) { dowidth(v.Type()) var outer ir.Node - outer = v.Name().Outer - outermost := v.Name().Defn + outer = v.Outer + outermost := v.Defn // out parameters will be assigned to implicitly upon return. if outermost.Class() != ir.PPARAMOUT && !outermost.Name().Addrtaken() && !outermost.Name().Assigned() && v.Type().Width <= 128 { - v.Name().SetByval(true) + v.SetByval(true) } else { outermost.Name().SetAddrtaken(true) outer = ir.Nod(ir.OADDR, outer, nil) @@ -208,11 +205,11 @@ func capturevars(dcl ir.Node) { if base.Flag.LowerM > 1 { var name *types.Sym - if v.Name().Curfn != nil && v.Name().Curfn.Func().Nname != nil { - name = v.Name().Curfn.Func().Nname.Sym() + if v.Curfn != nil && v.Curfn.Nname != nil { + name = v.Curfn.Sym() } how := "ref" - if v.Name().Byval() { + if v.Byval() { how = "value" } base.WarnfAt(v.Pos(), "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym(), outermost.Name().Addrtaken(), outermost.Name().Assigned(), int32(v.Type().Width)) @@ -222,18 +219,17 @@ func capturevars(dcl ir.Node) { fn.ClosureEnter.Append(outer) } - fn.ClosureVars.Set(out) + fn.ClosureVars = out base.Pos = lno } // transformclosure is called in a separate phase after escape analysis. // It transform closure bodies to properly reference captured variables. -func transformclosure(dcl ir.Node) { +func transformclosure(fn *ir.Func) { lno := base.Pos - base.Pos = dcl.Pos() - fn := dcl.Func() + base.Pos = fn.Pos() - if fn.ClosureCalled { + if fn.ClosureCalled() { // If the closure is directly called, we transform it to a plain function call // with variables passed as args. This avoids allocation of a closure object. // Here we do only a part of the transformation. Walk of OCALLFUNC(OCLOSURE) @@ -254,16 +250,16 @@ func transformclosure(dcl ir.Node) { // We are going to insert captured variables before input args. var params []*types.Field - var decls []ir.Node - for _, v := range fn.ClosureVars.Slice() { - if !v.Name().Byval() { + var decls []*ir.Name + for _, v := range fn.ClosureVars { + if !v.Byval() { // If v of type T is captured by reference, // we introduce function param &v *T // and v remains PAUTOHEAP with &v heapaddr // (accesses will implicitly deref &v). addr := NewName(lookup("&" + v.Sym().Name)) addr.SetType(types.NewPtr(v.Type())) - v.Name().Heapaddr = addr + v.Heapaddr = addr v = addr } @@ -282,24 +278,24 @@ func transformclosure(dcl ir.Node) { } dowidth(f.Type()) - dcl.SetType(f.Type()) // update type of ODCLFUNC + fn.SetType(f.Type()) // update type of ODCLFUNC } else { // The closure is not called, so it is going to stay as closure. var body []ir.Node offset := int64(Widthptr) - for _, v := range fn.ClosureVars.Slice() { + for _, v := range fn.ClosureVars { // cv refers to the field inside of closure OSTRUCTLIT. cv := ir.Nod(ir.OCLOSUREVAR, nil, nil) cv.SetType(v.Type()) - if !v.Name().Byval() { + if !v.Byval() { cv.SetType(types.NewPtr(v.Type())) } offset = Rnd(offset, int64(cv.Type().Align)) cv.SetOffset(offset) offset += cv.Type().Width - if v.Name().Byval() && v.Type().Width <= int64(2*Widthptr) { + if v.Byval() && v.Type().Width <= int64(2*Widthptr) { // If it is a small variable captured by value, downgrade it to PAUTO. v.SetClass(ir.PAUTO) fn.Dcl = append(fn.Dcl, v) @@ -310,11 +306,11 @@ func transformclosure(dcl ir.Node) { addr := NewName(lookup("&" + v.Sym().Name)) addr.SetType(types.NewPtr(v.Type())) addr.SetClass(ir.PAUTO) - addr.Name().SetUsed(true) - addr.Name().Curfn = dcl + addr.SetUsed(true) + addr.Curfn = fn fn.Dcl = append(fn.Dcl, addr) - v.Name().Heapaddr = addr - if v.Name().Byval() { + v.Heapaddr = addr + if v.Byval() { cv = ir.Nod(ir.OADDR, cv, nil) } body = append(body, ir.Nod(ir.OAS, addr, cv)) @@ -334,7 +330,7 @@ func transformclosure(dcl ir.Node) { // hasemptycvars reports whether closure clo has an // empty list of captured vars. func hasemptycvars(clo ir.Node) bool { - return clo.Func().ClosureVars.Len() == 0 + return len(clo.Func().ClosureVars) == 0 } // closuredebugruntimecheck applies boilerplate checks for debug flags @@ -372,9 +368,9 @@ func closureType(clo ir.Node) *types.Type { fields := []ir.Node{ namedfield(".F", types.Types[types.TUINTPTR]), } - for _, v := range clo.Func().ClosureVars.Slice() { + for _, v := range clo.Func().ClosureVars { typ := v.Type() - if !v.Name().Byval() { + if !v.Byval() { typ = types.NewPtr(typ) } fields = append(fields, symfield(v.Sym(), typ)) @@ -430,23 +426,24 @@ func typecheckpartialcall(dot ir.Node, sym *types.Sym) { } // Create top-level function. - dcl := makepartialcall(dot, dot.Type(), sym) - dcl.Func().SetWrapper(true) + fn := makepartialcall(dot, dot.Type(), sym) + fn.SetWrapper(true) + dot.SetOp(ir.OCALLPART) dot.SetRight(NewName(sym)) - dot.SetType(dcl.Type()) - dot.SetFunc(dcl.Func()) + dot.SetType(fn.Type()) + dot.SetFunc(fn) dot.SetOpt(nil) // clear types.Field from ODOTMETH } // makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed // for partial calls. -func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) ir.Node { +func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) *ir.Func { rcvrtype := dot.Left().Type() sym := methodSymSuffix(rcvrtype, meth, "-fm") if sym.Uniq() { - return ir.AsNode(sym.Def) + return ir.AsNode(sym.Def).(*ir.Func) } sym.SetUniq(true) @@ -469,8 +466,7 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) ir.Node { tfn.PtrList().Set(structargs(t0.Params(), true)) tfn.PtrRlist().Set(structargs(t0.Results(), false)) - dcl := dclfunc(sym, tfn) - fn := dcl.Func() + fn := dclfunc(sym, tfn) fn.SetDupok(true) fn.SetNeedctxt(true) @@ -484,7 +480,7 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) ir.Node { ptr := NewName(lookup(".this")) declare(ptr, ir.PAUTO) - ptr.Name().SetUsed(true) + ptr.SetUsed(true) var body []ir.Node if rcvrtype.IsPtr() || rcvrtype.IsInterface() { ptr.SetType(rcvrtype) @@ -504,20 +500,20 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) ir.Node { } body = append(body, call) - dcl.PtrBody().Set(body) + fn.PtrBody().Set(body) funcbody() - dcl = typecheck(dcl, ctxStmt) + typecheckFunc(fn) // Need to typecheck the body of the just-generated wrapper. // typecheckslice() requires that Curfn is set when processing an ORETURN. - Curfn = dcl - typecheckslice(dcl.Body().Slice(), ctxStmt) - sym.Def = dcl - xtop = append(xtop, dcl) + Curfn = fn + typecheckslice(fn.Body().Slice(), ctxStmt) + sym.Def = fn + xtop = append(xtop, fn) Curfn = savecurfn base.Pos = saveLineNo - return dcl + return fn } // partialCallType returns the struct type used to hold all the information diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 04e6e7a596..2bcee269d9 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -58,7 +58,7 @@ var declare_typegen int // declare records that Node n declares symbol n.Sym in the specified // declaration context. -func declare(n ir.Node, ctxt ir.Class) { +func declare(n *ir.Name, ctxt ir.Class) { if ir.IsBlank(n) { return } @@ -85,7 +85,7 @@ func declare(n ir.Node, ctxt ir.Class) { base.Fatalf("automatic outside function") } if Curfn != nil && ctxt != ir.PFUNC { - Curfn.Func().Dcl = append(Curfn.Func().Dcl, n) + Curfn.Dcl = append(Curfn.Dcl, n) } if n.Op() == ir.OTYPE { declare_typegen++ @@ -122,7 +122,7 @@ func declare(n ir.Node, ctxt ir.Class) { autoexport(n, ctxt) } -func addvar(n ir.Node, t *types.Type, ctxt ir.Class) { +func addvar(n *ir.Name, t *types.Type, ctxt ir.Class) { if n == nil || n.Sym() == nil || (n.Op() != ir.ONAME && n.Op() != ir.ONONAME) || t == nil { base.Fatalf("addvar: n=%v t=%v nil", n, t) } @@ -144,10 +144,11 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node { as2.PtrList().Set(vl) as2.PtrRlist().Set1(e) for _, v := range vl { + v := v.(*ir.Name) v.SetOp(ir.ONAME) declare(v, dclcontext) - v.Name().Ntype = t - v.Name().Defn = as2 + v.Ntype = t + v.Defn = as2 if Curfn != nil { init = append(init, ir.Nod(ir.ODCL, v, nil)) } @@ -158,6 +159,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node { nel := len(el) for _, v := range vl { + v := v.(*ir.Name) var e ir.Node if doexpr { if len(el) == 0 { @@ -170,7 +172,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node { v.SetOp(ir.ONAME) declare(v, dclcontext) - v.Name().Ntype = t + v.Ntype = t if e != nil || Curfn != nil || ir.IsBlank(v) { if Curfn != nil { @@ -179,7 +181,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node { e = ir.Nod(ir.OAS, v, e) init = append(init, e) if e.Right() != nil { - v.Name().Defn = e + v.Defn = e } } } @@ -200,10 +202,10 @@ func newnoname(s *types.Sym) ir.Node { return n } -// newfuncnamel generates a new name node for a function or method. -func newfuncnamel(pos src.XPos, s *types.Sym, fn *ir.Func) ir.Node { +// newFuncNameAt generates a new name node for a function or method. +func newFuncNameAt(pos src.XPos, s *types.Sym, fn *ir.Func) *ir.Name { if fn.Nname != nil { - base.Fatalf("newfuncnamel - already have name") + base.Fatalf("newFuncName - already have name") } n := ir.NewNameAt(pos, s) n.SetFunc(fn) @@ -271,20 +273,20 @@ func oldname(s *types.Sym) ir.Node { // the := it looks like a reference to the outer x so we'll // make x a closure variable unnecessarily. c := n.Name().Innermost - if c == nil || c.Name().Curfn != Curfn { + if c == nil || c.Curfn != Curfn { // Do not have a closure var for the active closure yet; make one. c = NewName(s) c.SetClass(ir.PAUTOHEAP) - c.Name().SetIsClosureVar(true) + c.SetIsClosureVar(true) c.SetIsDDD(n.IsDDD()) - c.Name().Defn = n + c.Defn = n // Link into list of active closure variables. // Popped from list in func funcLit. - c.Name().Outer = n.Name().Innermost + c.Outer = n.Name().Innermost n.Name().Innermost = c - Curfn.Func().ClosureVars.Append(c) + Curfn.ClosureVars = append(Curfn.ClosureVars, c) } // return ref to closure var, not original @@ -349,7 +351,7 @@ func colasdefn(left []ir.Node, defn ir.Node) { } nnew++ - n = NewName(n.Sym()) + n := NewName(n.Sym()) declare(n, dclcontext) n.Name().Defn = defn defn.PtrInit().Append(ir.Nod(ir.ODCL, n, nil)) @@ -377,18 +379,18 @@ func ifacedcl(n ir.Node) { // and declare the arguments. // called in extern-declaration context // returns in auto-declaration context. -func funchdr(n ir.Node) { +func funchdr(fn *ir.Func) { // change the declaration context from extern to auto funcStack = append(funcStack, funcStackEnt{Curfn, dclcontext}) - Curfn = n + Curfn = fn dclcontext = ir.PAUTO types.Markdcl() - if n.Func().Nname != nil && n.Func().Nname.Name().Ntype != nil { - funcargs(n.Func().Nname.Name().Ntype) + if fn.Nname != nil && fn.Nname.Ntype != nil { + funcargs(fn.Nname.Ntype) } else { - funcargs2(n.Type()) + funcargs2(fn.Type()) } } @@ -450,10 +452,11 @@ func funcarg(n ir.Node, ctxt ir.Class) { return } - n.SetRight(ir.NewNameAt(n.Pos(), n.Sym())) - n.Right().Name().Ntype = n.Left() - n.Right().SetIsDDD(n.IsDDD()) - declare(n.Right(), ctxt) + name := ir.NewNameAt(n.Pos(), n.Sym()) + n.SetRight(name) + name.Ntype = n.Left() + name.SetIsDDD(n.IsDDD()) + declare(name, ctxt) vargen++ n.Right().Name().Vargen = int32(vargen) @@ -492,7 +495,7 @@ func funcarg2(f *types.Field, ctxt ir.Class) { var funcStack []funcStackEnt // stack of previous values of Curfn/dclcontext type funcStackEnt struct { - curfn ir.Node + curfn *ir.Func dclcontext ir.Class } @@ -937,18 +940,18 @@ func setNodeNameFunc(n ir.Node) { n.Sym().SetFunc(true) } -func dclfunc(sym *types.Sym, tfn ir.Node) ir.Node { +func dclfunc(sym *types.Sym, tfn ir.Node) *ir.Func { if tfn.Op() != ir.OTFUNC { base.Fatalf("expected OTFUNC node, got %v", tfn) } - fn := ir.Nod(ir.ODCLFUNC, nil, nil) - fn.Func().Nname = newfuncnamel(base.Pos, sym, fn.Func()) - fn.Func().Nname.Name().Defn = fn - fn.Func().Nname.Name().Ntype = tfn - setNodeNameFunc(fn.Func().Nname) + fn := ir.NewFunc(base.Pos) + fn.Nname = newFuncNameAt(base.Pos, sym, fn) + fn.Nname.Defn = fn + fn.Nname.Ntype = tfn + setNodeNameFunc(fn.Nname) funchdr(fn) - fn.Func().Nname.Name().Ntype = typecheck(fn.Func().Nname.Name().Ntype, ctxType) + fn.Nname.Ntype = typecheck(fn.Nname.Ntype, ctxType) return fn } @@ -959,11 +962,11 @@ type nowritebarrierrecChecker struct { extraCalls map[ir.Node][]nowritebarrierrecCall // curfn is the current function during AST walks. - curfn ir.Node + curfn *ir.Func } type nowritebarrierrecCall struct { - target ir.Node // ODCLFUNC of caller or callee + target *ir.Func // caller or callee lineno src.XPos // line of call } @@ -983,7 +986,7 @@ func newNowritebarrierrecChecker() *nowritebarrierrecChecker { if n.Op() != ir.ODCLFUNC { continue } - c.curfn = n + c.curfn = n.(*ir.Func) ir.Inspect(n, c.findExtraCalls) } c.curfn = nil @@ -1002,13 +1005,13 @@ func (c *nowritebarrierrecChecker) findExtraCalls(n ir.Node) bool { return true } - var callee ir.Node + var callee *ir.Func arg := n.List().First() switch arg.Op() { case ir.ONAME: - callee = arg.Name().Defn + callee = arg.Name().Defn.(*ir.Func) case ir.OCLOSURE: - callee = arg.Func().Decl + callee = arg.Func() default: base.Fatalf("expected ONAME or OCLOSURE node, got %+v", arg) } @@ -1027,13 +1030,8 @@ func (c *nowritebarrierrecChecker) findExtraCalls(n ir.Node) bool { // because that's all we know after we start SSA. // // This can be called concurrently for different from Nodes. -func (c *nowritebarrierrecChecker) recordCall(from ir.Node, to *obj.LSym, pos src.XPos) { - if from.Op() != ir.ODCLFUNC { - base.Fatalf("expected ODCLFUNC, got %v", from) - } - // We record this information on the *Func so this is - // concurrent-safe. - fn := from.Func() +func (c *nowritebarrierrecChecker) recordCall(fn *ir.Func, to *obj.LSym, pos src.XPos) { + // We record this information on the *Func so this is concurrent-safe. if fn.NWBRCalls == nil { fn.NWBRCalls = new([]ir.SymAndPos) } @@ -1045,7 +1043,7 @@ func (c *nowritebarrierrecChecker) check() { // capture all calls created by lowering, but this means we // only get to see the obj.LSyms of calls. symToFunc lets us // get back to the ODCLFUNCs. - symToFunc := make(map[*obj.LSym]ir.Node) + symToFunc := make(map[*obj.LSym]*ir.Func) // funcs records the back-edges of the BFS call graph walk. It // maps from the ODCLFUNC of each function that must not have // write barriers to the call that inhibits them. Functions @@ -1060,24 +1058,25 @@ func (c *nowritebarrierrecChecker) check() { if n.Op() != ir.ODCLFUNC { continue } + fn := n.(*ir.Func) - symToFunc[n.Func().LSym] = n + symToFunc[fn.LSym] = fn // Make nowritebarrierrec functions BFS roots. - if n.Func().Pragma&ir.Nowritebarrierrec != 0 { - funcs[n] = nowritebarrierrecCall{} - q.PushRight(n) + if fn.Pragma&ir.Nowritebarrierrec != 0 { + funcs[fn] = nowritebarrierrecCall{} + q.PushRight(fn) } // Check go:nowritebarrier functions. - if n.Func().Pragma&ir.Nowritebarrier != 0 && n.Func().WBPos.IsKnown() { - base.ErrorfAt(n.Func().WBPos, "write barrier prohibited") + if fn.Pragma&ir.Nowritebarrier != 0 && fn.WBPos.IsKnown() { + base.ErrorfAt(fn.WBPos, "write barrier prohibited") } } // Perform a BFS of the call graph from all // go:nowritebarrierrec functions. - enqueue := func(src, target ir.Node, pos src.XPos) { - if target.Func().Pragma&ir.Yeswritebarrierrec != 0 { + enqueue := func(src, target *ir.Func, pos src.XPos) { + if target.Pragma&ir.Yeswritebarrierrec != 0 { // Don't flow into this function. return } @@ -1091,17 +1090,17 @@ func (c *nowritebarrierrecChecker) check() { q.PushRight(target) } for !q.Empty() { - fn := q.PopLeft() + fn := q.PopLeft().(*ir.Func) // Check fn. - if fn.Func().WBPos.IsKnown() { + if fn.WBPos.IsKnown() { var err bytes.Buffer call := funcs[fn] for call.target != nil { - fmt.Fprintf(&err, "\n\t%v: called by %v", base.FmtPos(call.lineno), call.target.Func().Nname) + fmt.Fprintf(&err, "\n\t%v: called by %v", base.FmtPos(call.lineno), call.target.Nname) call = funcs[call.target] } - base.ErrorfAt(fn.Func().WBPos, "write barrier prohibited by caller; %v%s", fn.Func().Nname, err.String()) + base.ErrorfAt(fn.WBPos, "write barrier prohibited by caller; %v%s", fn.Nname, err.String()) continue } @@ -1109,10 +1108,10 @@ func (c *nowritebarrierrecChecker) check() { for _, callee := range c.extraCalls[fn] { enqueue(fn, callee.target, callee.lineno) } - if fn.Func().NWBRCalls == nil { + if fn.NWBRCalls == nil { continue } - for _, callee := range *fn.Func().NWBRCalls { + for _, callee := range *fn.NWBRCalls { target := symToFunc[callee.Sym] if target != nil { enqueue(fn, target, callee.Pos) diff --git a/src/cmd/compile/internal/gc/dwinl.go b/src/cmd/compile/internal/gc/dwinl.go index 1e4e43caad..d9eb930037 100644 --- a/src/cmd/compile/internal/gc/dwinl.go +++ b/src/cmd/compile/internal/gc/dwinl.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/internal/dwarf" "cmd/internal/obj" "cmd/internal/src" @@ -211,6 +212,7 @@ func genAbstractFunc(fn *obj.LSym) { base.Ctxt.Diag("failed to locate precursor fn for %v", fn) return } + _ = ifn.(*ir.Func) if base.Debug.DwarfInl != 0 { base.Ctxt.Logf("DwarfAbstractFunc(%v)\n", fn.Name) } diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 351643ef5d..4bddb7f0f4 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -87,7 +87,7 @@ type Escape struct { allLocs []*EscLocation labels map[*types.Sym]labelState // known labels - curfn ir.Node + curfn *ir.Func // loopDepth counts the current loop nesting depth within // curfn. It increments within each "for" loop and at each @@ -103,7 +103,7 @@ type Escape struct { // variable. type EscLocation struct { n ir.Node // represented variable or expression, if any - curfn ir.Node // enclosing function + curfn *ir.Func // enclosing function edges []EscEdge // incoming edges loopDepth int // loopDepth at declaration @@ -180,7 +180,7 @@ func escFmt(n ir.Node, short bool) string { // escapeFuncs performs escape analysis on a minimal batch of // functions. -func escapeFuncs(fns []ir.Node, recursive bool) { +func escapeFuncs(fns []*ir.Func, recursive bool) { for _, fn := range fns { if fn.Op() != ir.ODCLFUNC { base.Fatalf("unexpected node: %v", fn) @@ -203,8 +203,8 @@ func escapeFuncs(fns []ir.Node, recursive bool) { e.finish(fns) } -func (e *Escape) initFunc(fn ir.Node) { - if fn.Op() != ir.ODCLFUNC || fn.Esc() != EscFuncUnknown { +func (e *Escape) initFunc(fn *ir.Func) { + if fn.Esc() != EscFuncUnknown { base.Fatalf("unexpected node: %v", fn) } fn.SetEsc(EscFuncPlanned) @@ -216,14 +216,14 @@ func (e *Escape) initFunc(fn ir.Node) { e.loopDepth = 1 // Allocate locations for local variables. - for _, dcl := range fn.Func().Dcl { + for _, dcl := range fn.Dcl { if dcl.Op() == ir.ONAME { e.newLoc(dcl, false) } } } -func (e *Escape) walkFunc(fn ir.Node) { +func (e *Escape) walkFunc(fn *ir.Func) { fn.SetEsc(EscFuncStarted) // Identify labels that mark the head of an unstructured loop. @@ -589,7 +589,8 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) { for i := m.Type.NumResults(); i > 0; i-- { ks = append(ks, e.heapHole()) } - paramK := e.tagHole(ks, ir.AsNode(m.Nname), m.Type.Recv()) + name, _ := m.Nname.(*ir.Name) + paramK := e.tagHole(ks, name, m.Type.Recv()) e.expr(e.teeHole(paramK, closureK), n.Left()) @@ -633,17 +634,13 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) { k = e.spill(k, n) // Link addresses of captured variables to closure. - for _, v := range n.Func().ClosureVars.Slice() { - if v.Op() == ir.OXXX { // unnamed out argument; see dcl.go:/^funcargs - continue - } - + for _, v := range n.Func().ClosureVars { k := k - if !v.Name().Byval() { + if !v.Byval() { k = k.addr(v, "reference") } - e.expr(k.note(n, "captured by a closure"), v.Name().Defn) + e.expr(k.note(n, "captured by a closure"), v.Defn) } case ir.ORUNES2STR, ir.OBYTES2STR, ir.OSTR2RUNES, ir.OSTR2BYTES, ir.ORUNESTR: @@ -813,12 +810,12 @@ func (e *Escape) call(ks []EscHole, call, where ir.Node) { fixVariadicCall(call) // Pick out the function callee, if statically known. - var fn ir.Node + var fn *ir.Name switch call.Op() { case ir.OCALLFUNC: switch v := staticValue(call.Left()); { case v.Op() == ir.ONAME && v.Class() == ir.PFUNC: - fn = v + fn = v.(*ir.Name) case v.Op() == ir.OCLOSURE: fn = v.Func().Nname } @@ -902,7 +899,7 @@ func (e *Escape) call(ks []EscHole, call, where ir.Node) { // 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 []EscHole, fn ir.Node, param *types.Field) EscHole { +func (e *Escape) tagHole(ks []EscHole, fn *ir.Name, param *types.Field) EscHole { // If this is a dynamic call, we can't rely on param.Note. if fn == nil { return e.heapHole() @@ -943,9 +940,9 @@ func (e *Escape) tagHole(ks []EscHole, fn ir.Node, param *types.Field) EscHole { // fn has not yet been analyzed, so its parameters and results // should be incorporated directly into the flow graph instead of // relying on its escape analysis tagging. -func (e *Escape) inMutualBatch(fn ir.Node) bool { - if fn.Name().Defn != nil && fn.Name().Defn.Esc() < EscFuncTagged { - if fn.Name().Defn.Esc() == EscFuncUnknown { +func (e *Escape) inMutualBatch(fn *ir.Name) bool { + if fn.Defn != nil && fn.Defn.Esc() < EscFuncTagged { + if fn.Defn.Esc() == EscFuncUnknown { base.Fatalf("graph inconsistency") } return true @@ -1368,7 +1365,7 @@ func (e *Escape) outlives(l, other *EscLocation) bool { // // var u int // okay to stack allocate // *(func() *int { return &u }()) = 42 - if containsClosure(other.curfn, l.curfn) && l.curfn.Func().ClosureCalled { + if containsClosure(other.curfn, l.curfn) && l.curfn.ClosureCalled() { return false } @@ -1402,11 +1399,7 @@ func (e *Escape) outlives(l, other *EscLocation) bool { } // containsClosure reports whether c is a closure contained within f. -func containsClosure(f, c ir.Node) bool { - if f.Op() != ir.ODCLFUNC || c.Op() != ir.ODCLFUNC { - base.Fatalf("bad containsClosure: %v, %v", f, c) - } - +func containsClosure(f, c *ir.Func) bool { // Common case. if f == c { return false @@ -1414,8 +1407,8 @@ func containsClosure(f, c ir.Node) bool { // Closures within function Foo are named like "Foo.funcN..." // TODO(mdempsky): Better way to recognize this. - fn := f.Func().Nname.Sym().Name - cn := c.Func().Nname.Sym().Name + fn := f.Sym().Name + cn := c.Sym().Name return len(cn) > len(fn) && cn[:len(fn)] == fn && cn[len(fn)] == '.' } @@ -1437,7 +1430,7 @@ func (l *EscLocation) leakTo(sink *EscLocation, derefs int) { l.paramEsc.AddHeap(derefs) } -func (e *Escape) finish(fns []ir.Node) { +func (e *Escape) finish(fns []*ir.Func) { // Record parameter tags for package export data. for _, fn := range fns { fn.SetEsc(EscFuncTagged) @@ -1614,12 +1607,12 @@ const ( EscNever // By construction will not escape. ) -// funcSym returns fn.Func.Nname.Sym if no nils are encountered along the way. -func funcSym(fn ir.Node) *types.Sym { - if fn == nil || fn.Func().Nname == nil { +// funcSym returns fn.Nname.Sym if no nils are encountered along the way. +func funcSym(fn *ir.Func) *types.Sym { + if fn == nil || fn.Nname == nil { return nil } - return fn.Func().Nname.Sym() + return fn.Sym() } // Mark labels that have no backjumps to them as not increasing e.loopdepth. @@ -1798,6 +1791,7 @@ func addrescapes(n ir.Node) { // Nothing to do. case ir.ONAME: + n := n.(*ir.Name) if n == nodfp { break } @@ -1832,10 +1826,6 @@ func addrescapes(n ir.Node) { // heap in f, not in the inner closure. Flip over to f before calling moveToHeap. oldfn := Curfn Curfn = n.Name().Curfn - if Curfn.Op() == ir.OCLOSURE { - Curfn = Curfn.Func().Decl - panic("can't happen") - } ln := base.Pos base.Pos = Curfn.Pos() moveToHeap(n) @@ -1855,7 +1845,7 @@ func addrescapes(n ir.Node) { } // moveToHeap records the parameter or local variable n as moved to the heap. -func moveToHeap(n ir.Node) { +func moveToHeap(n *ir.Name) { if base.Flag.LowerR != 0 { ir.Dump("MOVE", n) } @@ -1877,7 +1867,7 @@ func moveToHeap(n ir.Node) { // Unset AutoTemp to persist the &foo variable name through SSA to // liveness analysis. // TODO(mdempsky/drchase): Cleaner solution? - heapaddr.Name().SetAutoTemp(false) + heapaddr.SetAutoTemp(false) // Parameters have a local stack copy used at function start/end // in addition to the copy in the heap that may live longer than @@ -1895,14 +1885,14 @@ func moveToHeap(n ir.Node) { stackcopy.SetType(n.Type()) stackcopy.SetOffset(n.Offset()) stackcopy.SetClass(n.Class()) - stackcopy.Name().Heapaddr = heapaddr + stackcopy.Heapaddr = heapaddr if n.Class() == ir.PPARAMOUT { // Make sure the pointer to the heap copy is kept live throughout the function. // The function could panic at any point, and then a defer could recover. // Thus, we need the pointer to the heap copy always available so the // post-deferreturn code can copy the return value back to the stack. // See issue 16095. - heapaddr.Name().SetIsOutputParamHeapAddr(true) + heapaddr.SetIsOutputParamHeapAddr(true) } n.Name().Stackcopy = stackcopy @@ -1910,9 +1900,9 @@ func moveToHeap(n ir.Node) { // liveness and other analyses use the underlying stack slot // and not the now-pseudo-variable n. found := false - for i, d := range Curfn.Func().Dcl { + for i, d := range Curfn.Dcl { if d == n { - Curfn.Func().Dcl[i] = stackcopy + Curfn.Dcl[i] = stackcopy found = true break } @@ -1925,7 +1915,7 @@ func moveToHeap(n ir.Node) { if !found { base.Fatalf("cannot find %v in local variable list", n) } - Curfn.Func().Dcl = append(Curfn.Func().Dcl, n) + Curfn.Dcl = append(Curfn.Dcl, n) } // Modify n in place so that uses of n now mean indirection of the heapaddr. diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 10033793bf..5cd379a7d3 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -161,8 +161,12 @@ func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) { if n == nil { return } + name := n.(*ir.Name) - n.SetFunc(new(ir.Func)) + fn := ir.NewFunc(pos) + fn.SetType(t) + name.SetFunc(fn) + fn.Nname = name if base.Flag.E != 0 { fmt.Printf("import func %v%S\n", s, t) diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index cf9e0d58bf..0d3f9392fb 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -52,7 +52,7 @@ func autotmpname(n int) string { } // make a new Node off the books -func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) *ir.Name { +func tempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name { if curfn == nil { base.Fatalf("no curfn for tempAt") } @@ -65,7 +65,7 @@ func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) *ir.Name { } s := &types.Sym{ - Name: autotmpname(len(curfn.Func().Dcl)), + Name: autotmpname(len(curfn.Dcl)), Pkg: ir.LocalPkg, } n := ir.NewNameAt(pos, s) @@ -73,10 +73,10 @@ func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) *ir.Name { n.SetType(t) n.SetClass(ir.PAUTO) n.SetEsc(EscNever) - n.Name().Curfn = curfn - n.Name().SetUsed(true) - n.Name().SetAutoTemp(true) - curfn.Func().Dcl = append(curfn.Func().Dcl, n) + n.Curfn = curfn + n.SetUsed(true) + n.SetAutoTemp(true) + curfn.Dcl = append(curfn.Dcl, n) dowidth(t) diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index 84e6bc5faf..24393de53d 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -132,7 +132,7 @@ var xtop []ir.Node var exportlist []ir.Node -var importlist []ir.Node // imported functions and methods with inlinable bodies +var importlist []*ir.Func // imported functions and methods with inlinable bodies var ( funcsymsmu sync.Mutex // protects funcsyms and associated package lookups (see func funcsym) @@ -141,7 +141,7 @@ var ( var dclcontext ir.Class // PEXTERN/PAUTO -var Curfn ir.Node +var Curfn *ir.Func var Widthptr int @@ -156,7 +156,7 @@ var instrumenting bool // Whether we are tracking lexical scopes for DWARF. var trackScopes bool -var nodfp ir.Node +var nodfp *ir.Name var autogeneratedPos src.XPos diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go index 950033a8a3..79ca669dfb 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -47,7 +47,7 @@ type Progs struct { next *obj.Prog // next Prog pc int64 // virtual PC; count of Progs pos src.XPos // position to use for new Progs - curfn ir.Node // fn these Progs are for + curfn *ir.Func // fn these Progs are for progcache []obj.Prog // local progcache cacheidx int // first free element of progcache @@ -57,7 +57,7 @@ type Progs struct { // newProgs returns a new Progs for fn. // worker indicates which of the backend workers will use the Progs. -func newProgs(fn ir.Node, worker int) *Progs { +func newProgs(fn *ir.Func, worker int) *Progs { pp := new(Progs) if base.Ctxt.CanReuseProgs() { sz := len(sharedProgArray) / base.Flag.LowerC @@ -174,17 +174,17 @@ func (pp *Progs) Appendpp(p *obj.Prog, as obj.As, ftype obj.AddrType, freg int16 return q } -func (pp *Progs) settext(fn ir.Node) { +func (pp *Progs) settext(fn *ir.Func) { if pp.Text != nil { base.Fatalf("Progs.settext called twice") } ptxt := pp.Prog(obj.ATEXT) pp.Text = ptxt - fn.Func().LSym.Func().Text = ptxt + fn.LSym.Func().Text = ptxt ptxt.From.Type = obj.TYPE_MEM ptxt.From.Name = obj.NAME_EXTERN - ptxt.From.Sym = fn.Func().LSym + ptxt.From.Sym = fn.LSym } // initLSym defines f's obj.LSym and initializes it based on the @@ -281,7 +281,7 @@ func initLSym(f *ir.Func, hasBody bool) { // See test/recover.go for test cases and src/reflect/value.go // for the actual functions being considered. if base.Ctxt.Pkgpath == "reflect" { - switch f.Nname.Sym().Name { + switch f.Sym().Name { case "callReflect", "callMethod": flag |= obj.WRAPPER } diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 88d3a6477c..3f5ec2e4dd 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -429,6 +429,7 @@ func (p *iexporter) doDecl(n ir.Node) { switch n.Op() { case ir.ONAME: + n := n.(*ir.Name) switch n.Class() { case ir.PEXTERN: // Variable. @@ -515,7 +516,7 @@ func (w *exportWriter) tag(tag byte) { w.data.WriteByte(tag) } -func (p *iexporter) doInline(f ir.Node) { +func (p *iexporter) doInline(f *ir.Name) { w := p.newWriter() w.setPkg(fnpkg(f), false) @@ -960,7 +961,7 @@ func (w *exportWriter) varExt(n ir.Node) { w.symIdx(n.Sym()) } -func (w *exportWriter) funcExt(n ir.Node) { +func (w *exportWriter) funcExt(n *ir.Name) { w.linkname(n.Sym()) w.symIdx(n.Sym()) @@ -979,14 +980,7 @@ func (w *exportWriter) funcExt(n ir.Node) { } // Endlineno for inlined function. - if n.Name().Defn != nil { - w.pos(n.Name().Defn.Func().Endlineno) - } else { - // When the exported node was defined externally, - // e.g. io exports atomic.(*Value).Load or bytes exports errors.New. - // Keep it as we don't distinguish this case in iimport.go. - w.pos(n.Func().Endlineno) - } + w.pos(n.Func().Endlineno) } else { w.uint64(0) } @@ -994,7 +988,7 @@ func (w *exportWriter) funcExt(n ir.Node) { func (w *exportWriter) methExt(m *types.Field) { w.bool(m.Nointerface()) - w.funcExt(ir.AsNode(m.Nname)) + w.funcExt(ir.AsNode(m.Nname).(*ir.Name)) } func (w *exportWriter) linkname(s *types.Sym) { diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 066d956b93..5a50682ab2 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -41,7 +41,7 @@ var ( inlineImporter = map[*types.Sym]iimporterAndOffset{} ) -func expandDecl(n ir.Node) { +func expandDecl(n *ir.Name) { if n.Op() != ir.ONONAME { return } @@ -55,12 +55,12 @@ func expandDecl(n ir.Node) { r.doDecl(n) } -func expandInline(fn ir.Node) { - if fn.Func().Inl.Body != nil { +func expandInline(fn *ir.Func) { + if fn.Inl.Body != nil { return } - r := importReaderFor(fn, inlineImporter) + r := importReaderFor(fn.Nname, inlineImporter) if r == nil { base.Fatalf("missing import reader for %v", fn) } @@ -68,7 +68,7 @@ func expandInline(fn ir.Node) { r.doInline(fn) } -func importReaderFor(n ir.Node, importers map[*types.Sym]iimporterAndOffset) *importReader { +func importReaderFor(n *ir.Name, importers map[*types.Sym]iimporterAndOffset) *importReader { x, ok := importers[n.Sym()] if !ok { return nil @@ -331,7 +331,9 @@ func (r *importReader) doDecl(n ir.Node) { recv := r.param() mtyp := r.signature(recv) - m := newfuncnamel(mpos, methodSym(recv.Type, msym), new(ir.Func)) + fn := ir.NewFunc(mpos) + fn.SetType(mtyp) + m := newFuncNameAt(mpos, methodSym(recv.Type, msym), fn) m.SetType(mtyp) m.SetClass(ir.PFUNC) // methodSym already marked m.Sym as a function. @@ -501,7 +503,7 @@ func (r *importReader) typ1() *types.Type { // type. n := ir.AsNode(r.qualifiedIdent().PkgDef()) if n.Op() == ir.ONONAME { - expandDecl(n) + expandDecl(n.(*ir.Name)) } if n.Op() != ir.OTYPE { base.Fatalf("expected OTYPE, got %v: %v, %v", n.Op(), n.Sym(), n) @@ -695,12 +697,12 @@ func (r *importReader) typeExt(t *types.Type) { // so we can use index to reference the symbol. var typeSymIdx = make(map[*types.Type][2]int64) -func (r *importReader) doInline(n ir.Node) { - if len(n.Func().Inl.Body) != 0 { - base.Fatalf("%v already has inline body", n) +func (r *importReader) doInline(fn *ir.Func) { + if len(fn.Inl.Body) != 0 { + base.Fatalf("%v already has inline body", fn) } - funchdr(n) + funchdr(fn) body := r.stmtList() funcbody() if body == nil { @@ -712,15 +714,15 @@ func (r *importReader) doInline(n ir.Node) { // functions). body = []ir.Node{} } - n.Func().Inl.Body = body + fn.Inl.Body = body - importlist = append(importlist, n) + importlist = append(importlist, fn) if base.Flag.E > 0 && base.Flag.LowerM > 2 { if base.Flag.LowerM > 3 { - fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type(), ir.AsNodes(n.Func().Inl.Body)) + fmt.Printf("inl body for %v %#v: %+v\n", fn, fn.Type(), ir.AsNodes(fn.Inl.Body)) } else { - fmt.Printf("inl body for %v %#v: %v\n", n, n.Type(), ir.AsNodes(n.Func().Inl.Body)) + fmt.Printf("inl body for %v %#v: %v\n", fn, fn.Type(), ir.AsNodes(fn.Inl.Body)) } } } @@ -772,7 +774,7 @@ func (r *importReader) caseList(sw ir.Node) []ir.Node { caseVar := ir.NewNameAt(cas.Pos(), r.ident()) declare(caseVar, dclcontext) cas.PtrRlist().Set1(caseVar) - caseVar.Name().Defn = sw.Left() + caseVar.Defn = sw.Left() } cas.PtrBody().Set(r.stmtList()) cases[i] = cas diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go index 2b7ecd1d05..7f2a39ff46 100644 --- a/src/cmd/compile/internal/gc/init.go +++ b/src/cmd/compile/internal/gc/init.go @@ -19,7 +19,7 @@ var renameinitgen int // Function collecting autotmps generated during typechecking, // to be included in the package-level init function. -var initTodo = ir.Nod(ir.ODCLFUNC, nil, nil) +var initTodo = ir.NewFunc(base.Pos) func renameinit() *types.Sym { s := lookupN("init.", renameinitgen) @@ -49,23 +49,23 @@ func fninit(n []ir.Node) { base.Pos = nf[0].Pos() // prolog/epilog gets line number of first init stmt initializers := lookup("init") fn := dclfunc(initializers, ir.Nod(ir.OTFUNC, nil, nil)) - for _, dcl := range initTodo.Func().Dcl { + for _, dcl := range initTodo.Dcl { dcl.Name().Curfn = fn } - fn.Func().Dcl = append(fn.Func().Dcl, initTodo.Func().Dcl...) - initTodo.Func().Dcl = nil + fn.Dcl = append(fn.Dcl, initTodo.Dcl...) + initTodo.Dcl = nil fn.PtrBody().Set(nf) funcbody() - fn = typecheck(fn, ctxStmt) + typecheckFunc(fn) Curfn = fn typecheckslice(nf, ctxStmt) Curfn = nil xtop = append(xtop, fn) fns = append(fns, initializers.Linksym()) } - if initTodo.Func().Dcl != nil { + if initTodo.Dcl != nil { // We only generate temps using initTodo if there // are package-scope initialization statements, so // something's weird if we get here. diff --git a/src/cmd/compile/internal/gc/initorder.go b/src/cmd/compile/internal/gc/initorder.go index 1003f131b8..ea3d74d5ba 100644 --- a/src/cmd/compile/internal/gc/initorder.go +++ b/src/cmd/compile/internal/gc/initorder.go @@ -284,11 +284,11 @@ func (d *initDeps) visit(n ir.Node) bool { case ir.ONAME: switch n.Class() { case ir.PEXTERN, ir.PFUNC: - d.foundDep(n) + d.foundDep(n.(*ir.Name)) } case ir.OCLOSURE: - d.inspectList(n.Func().Decl.Body()) + d.inspectList(n.Func().Body()) case ir.ODOTMETH, ir.OCALLPART: d.foundDep(methodExprName(n)) @@ -299,7 +299,7 @@ func (d *initDeps) visit(n ir.Node) bool { // foundDep records that we've found a dependency on n by adding it to // seen. -func (d *initDeps) foundDep(n ir.Node) { +func (d *initDeps) foundDep(n *ir.Name) { // Can happen with method expressions involving interface // types; e.g., fixedbugs/issue4495.go. if n == nil { @@ -308,7 +308,7 @@ func (d *initDeps) foundDep(n ir.Node) { // Names without definitions aren't interesting as far as // initialization ordering goes. - if n.Name().Defn == nil { + if n.Defn == nil { return } @@ -317,7 +317,7 @@ func (d *initDeps) foundDep(n ir.Node) { } d.seen.Add(n) if d.transitive && n.Class() == ir.PFUNC { - d.inspectList(n.Name().Defn.Body()) + d.inspectList(n.Defn.Body()) } } diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 102144aedf..20f145b8eb 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -53,7 +53,7 @@ const ( // Get the function's package. For ordinary functions it's on the ->sym, but for imported methods // the ->sym can be re-used in the local package, so peel it off the receiver's type. -func fnpkg(fn ir.Node) *types.Pkg { +func fnpkg(fn *ir.Name) *types.Pkg { if ir.IsMethod(fn) { // method rcvr := fn.Type().Recv().Type @@ -73,8 +73,8 @@ func fnpkg(fn ir.Node) *types.Pkg { // Lazy typechecking of imported bodies. For local functions, caninl will set ->typecheck // because they're a copy of an already checked body. -func typecheckinl(fn ir.Node) { - lno := setlineno(fn) +func typecheckinl(fn *ir.Func) { + lno := setlineno(fn.Nname) expandInline(fn) @@ -82,19 +82,19 @@ func typecheckinl(fn ir.Node) { // their bodies may refer to unsafe as long as the package // was marked safe during import (which was checked then). // the ->inl of a local function has been typechecked before caninl copied it. - pkg := fnpkg(fn) + pkg := fnpkg(fn.Nname) if pkg == ir.LocalPkg || pkg == nil { return // typecheckinl on local function } if base.Flag.LowerM > 2 || base.Debug.Export != 0 { - fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym(), fn, ir.AsNodes(fn.Func().Inl.Body)) + fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym(), fn, ir.AsNodes(fn.Inl.Body)) } savefn := Curfn Curfn = fn - typecheckslice(fn.Func().Inl.Body, ctxStmt) + typecheckslice(fn.Inl.Body, ctxStmt) Curfn = savefn // During expandInline (which imports fn.Func.Inl.Body), @@ -102,8 +102,8 @@ func typecheckinl(fn ir.Node) { // to fn.Func.Inl.Dcl for consistency with how local functions // behave. (Append because typecheckinl may be called multiple // times.) - fn.Func().Inl.Dcl = append(fn.Func().Inl.Dcl, fn.Func().Dcl...) - fn.Func().Dcl = nil + fn.Inl.Dcl = append(fn.Inl.Dcl, fn.Dcl...) + fn.Dcl = nil base.Pos = lno } @@ -111,11 +111,8 @@ func typecheckinl(fn ir.Node) { // Caninl determines whether fn is inlineable. // If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy. // fn and ->nbody will already have been typechecked. -func caninl(fn ir.Node) { - if fn.Op() != ir.ODCLFUNC { - base.Fatalf("caninl %v", fn) - } - if fn.Func().Nname == nil { +func caninl(fn *ir.Func) { + if fn.Nname == nil { base.Fatalf("caninl no nname %+v", fn) } @@ -124,7 +121,7 @@ func caninl(fn ir.Node) { defer func() { if reason != "" { if base.Flag.LowerM > 1 { - fmt.Printf("%v: cannot inline %v: %s\n", ir.Line(fn), fn.Func().Nname, reason) + fmt.Printf("%v: cannot inline %v: %s\n", ir.Line(fn), fn.Nname, reason) } if logopt.Enabled() { logopt.LogOpt(fn.Pos(), "cannotInlineFunction", "inline", ir.FuncName(fn), reason) @@ -134,33 +131,33 @@ func caninl(fn ir.Node) { } // If marked "go:noinline", don't inline - if fn.Func().Pragma&ir.Noinline != 0 { + if fn.Pragma&ir.Noinline != 0 { reason = "marked go:noinline" return } // If marked "go:norace" and -race compilation, don't inline. - if base.Flag.Race && fn.Func().Pragma&ir.Norace != 0 { + if base.Flag.Race && fn.Pragma&ir.Norace != 0 { reason = "marked go:norace with -race compilation" return } // If marked "go:nocheckptr" and -d checkptr compilation, don't inline. - if base.Debug.Checkptr != 0 && fn.Func().Pragma&ir.NoCheckPtr != 0 { + if base.Debug.Checkptr != 0 && fn.Pragma&ir.NoCheckPtr != 0 { reason = "marked go:nocheckptr" return } // If marked "go:cgo_unsafe_args", don't inline, since the // function makes assumptions about its argument frame layout. - if fn.Func().Pragma&ir.CgoUnsafeArgs != 0 { + if fn.Pragma&ir.CgoUnsafeArgs != 0 { reason = "marked go:cgo_unsafe_args" return } // If marked as "go:uintptrescapes", don't inline, since the // escape information is lost during inlining. - if fn.Func().Pragma&ir.UintptrEscapes != 0 { + if fn.Pragma&ir.UintptrEscapes != 0 { reason = "marked as having an escaping uintptr argument" return } @@ -169,7 +166,7 @@ func caninl(fn ir.Node) { // granularity, so inlining yeswritebarrierrec functions can // confuse it (#22342). As a workaround, disallow inlining // them for now. - if fn.Func().Pragma&ir.Yeswritebarrierrec != 0 { + if fn.Pragma&ir.Yeswritebarrierrec != 0 { reason = "marked go:yeswritebarrierrec" return } @@ -184,7 +181,7 @@ func caninl(fn ir.Node) { base.Fatalf("caninl on non-typechecked function %v", fn) } - n := fn.Func().Nname + n := fn.Nname if n.Func().InlinabilityChecked() { return } @@ -220,7 +217,7 @@ func caninl(fn ir.Node) { n.Func().Inl = &ir.Inline{ Cost: inlineMaxBudget - visitor.budget, - Dcl: inlcopylist(pruneUnusedAutos(n.Name().Defn.Func().Dcl, &visitor)), + Dcl: pruneUnusedAutos(n.Defn.Func().Dcl, &visitor), Body: inlcopylist(fn.Body().Slice()), } @@ -236,36 +233,38 @@ func caninl(fn ir.Node) { // inlFlood marks n's inline body for export and recursively ensures // all called functions are marked too. -func inlFlood(n ir.Node) { +func inlFlood(n *ir.Name) { if n == nil { return } if n.Op() != ir.ONAME || n.Class() != ir.PFUNC { base.Fatalf("inlFlood: unexpected %v, %v, %v", n, n.Op(), n.Class()) } - if n.Func() == nil { + fn := n.Func() + if fn == nil { base.Fatalf("inlFlood: missing Func on %v", n) } - if n.Func().Inl == nil { + if fn.Inl == nil { return } - if n.Func().ExportInline() { + if fn.ExportInline() { return } - n.Func().SetExportInline(true) + fn.SetExportInline(true) - typecheckinl(n) + typecheckinl(fn) // Recursively identify all referenced functions for // reexport. We want to include even non-called functions, // because after inlining they might be callable. - ir.InspectList(ir.AsNodes(n.Func().Inl.Body), func(n ir.Node) bool { + ir.InspectList(ir.AsNodes(fn.Inl.Body), func(n ir.Node) bool { switch n.Op() { - case ir.OMETHEXPR: + case ir.OMETHEXPR, ir.ODOTMETH: inlFlood(methodExprName(n)) case ir.ONAME: + n := n.(*ir.Name) switch n.Class() { case ir.PFUNC: inlFlood(n) @@ -274,10 +273,6 @@ func inlFlood(n ir.Node) { exportsym(n) } - case ir.ODOTMETH: - fn := methodExprName(n) - inlFlood(fn) - case ir.OCALLPART: // Okay, because we don't yet inline indirect // calls to method values. @@ -342,8 +337,8 @@ func (v *hairyVisitor) visit(n ir.Node) bool { break } - if fn := inlCallee(n.Left()); fn != nil && fn.Func().Inl != nil { - v.budget -= fn.Func().Inl.Cost + if fn := inlCallee(n.Left()); fn != nil && fn.Inl != nil { + v.budget -= fn.Inl.Cost break } @@ -503,7 +498,7 @@ func countNodes(n ir.Node) int { // Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any // calls made to inlineable functions. This is the external entry point. -func inlcalls(fn ir.Node) { +func inlcalls(fn *ir.Func) { savefn := Curfn Curfn = fn maxCost := int32(inlineMaxBudget) @@ -516,8 +511,8 @@ func inlcalls(fn ir.Node) { // but allow inlining if there is a recursion cycle of many functions. // Most likely, the inlining will stop before we even hit the beginning of // the cycle again, but the map catches the unusual case. - inlMap := make(map[ir.Node]bool) - fn = inlnode(fn, maxCost, inlMap) + inlMap := make(map[*ir.Func]bool) + fn = inlnode(fn, maxCost, inlMap).(*ir.Func) if fn != Curfn { base.Fatalf("inlnode replaced curfn") } @@ -558,7 +553,7 @@ func inlconv2list(n ir.Node) []ir.Node { return s } -func inlnodelist(l ir.Nodes, maxCost int32, inlMap map[ir.Node]bool) { +func inlnodelist(l ir.Nodes, maxCost int32, inlMap map[*ir.Func]bool) { s := l.Slice() for i := range s { s[i] = inlnode(s[i], maxCost, inlMap) @@ -578,7 +573,7 @@ func inlnodelist(l ir.Nodes, maxCost int32, inlMap map[ir.Node]bool) { // shorter and less complicated. // The result of inlnode MUST be assigned back to n, e.g. // n.Left = inlnode(n.Left) -func inlnode(n ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { +func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { if n == nil { return n } @@ -684,7 +679,7 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { if isIntrinsicCall(n) { break } - if fn := inlCallee(n.Left()); fn != nil && fn.Func().Inl != nil { + if fn := inlCallee(n.Left()); fn != nil && fn.Inl != nil { n = mkinlcall(n, fn, maxCost, inlMap) } @@ -698,7 +693,7 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { base.Fatalf("no function type for [%p] %+v\n", n.Left(), n.Left()) } - n = mkinlcall(n, methodExprName(n.Left()), maxCost, inlMap) + n = mkinlcall(n, methodExprName(n.Left()).Func(), maxCost, inlMap) } base.Pos = lno @@ -707,7 +702,7 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { // inlCallee takes a function-typed expression and returns the underlying function ONAME // that it refers to if statically known. Otherwise, it returns nil. -func inlCallee(fn ir.Node) ir.Node { +func inlCallee(fn ir.Node) *ir.Func { fn = staticValue(fn) switch { case fn.Op() == ir.OMETHEXPR: @@ -718,13 +713,13 @@ func inlCallee(fn ir.Node) ir.Node { if n == nil || !types.Identical(n.Type().Recv().Type, fn.Left().Type()) { return nil } - return n + return n.Func() case fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC: - return fn + return fn.Func() case fn.Op() == ir.OCLOSURE: - c := fn.Func().Decl + c := fn.Func() caninl(c) - return c.Func().Nname + return c } return nil } @@ -777,7 +772,7 @@ FindRHS: base.Fatalf("RHS is nil: %v", defn) } - unsafe, _ := reassigned(n) + unsafe, _ := reassigned(n.(*ir.Name)) if unsafe { return nil } @@ -791,23 +786,15 @@ FindRHS: // useful for -m output documenting the reason for inhibited optimizations. // NB: global variables are always considered to be re-assigned. // TODO: handle initial declaration not including an assignment and followed by a single assignment? -func reassigned(n ir.Node) (bool, ir.Node) { +func reassigned(n *ir.Name) (bool, ir.Node) { if n.Op() != ir.ONAME { base.Fatalf("reassigned %v", n) } // no way to reliably check for no-reassignment of globals, assume it can be - if n.Name().Curfn == nil { + if n.Curfn == nil { return true, nil } - f := n.Name().Curfn - // There just might be a good reason for this although this can be pretty surprising: - // local variables inside a closure have Curfn pointing to the OCLOSURE node instead - // of the corresponding ODCLFUNC. - // We need to walk the function body to check for reassignments so we follow the - // linkage to the ODCLFUNC node as that is where body is held. - if f.Op() == ir.OCLOSURE { - f = f.Func().Decl - } + f := n.Curfn v := reassignVisitor{name: n} a := v.visitList(f.Body()) return a != nil, a @@ -863,13 +850,13 @@ func (v *reassignVisitor) visitList(l ir.Nodes) ir.Node { return nil } -func inlParam(t *types.Field, as ir.Node, inlvars map[ir.Node]ir.Node) ir.Node { +func inlParam(t *types.Field, as ir.Node, inlvars map[*ir.Name]ir.Node) ir.Node { n := ir.AsNode(t.Nname) if n == nil || ir.IsBlank(n) { return ir.BlankNode } - inlvar := inlvars[n] + inlvar := inlvars[n.(*ir.Name)] if inlvar == nil { base.Fatalf("missing inlvar for %v", n) } @@ -887,25 +874,25 @@ var inlgen int // parameters. // The result of mkinlcall MUST be assigned back to n, e.g. // n.Left = mkinlcall(n.Left, fn, isddd) -func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { - if fn.Func().Inl == nil { +func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { + if fn.Inl == nil { if logopt.Enabled() { logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(Curfn), fmt.Sprintf("%s cannot be inlined", ir.PkgFuncName(fn))) } return n } - if fn.Func().Inl.Cost > maxCost { + if fn.Inl.Cost > maxCost { // The inlined function body is too big. Typically we use this check to restrict // inlining into very big functions. See issue 26546 and 17566. if logopt.Enabled() { logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(Curfn), - fmt.Sprintf("cost %d of %s exceeds max large caller cost %d", fn.Func().Inl.Cost, ir.PkgFuncName(fn), maxCost)) + fmt.Sprintf("cost %d of %s exceeds max large caller cost %d", fn.Inl.Cost, ir.PkgFuncName(fn), maxCost)) } return n } - if fn == Curfn || fn.Name().Defn == Curfn { + if fn == Curfn { // Can't recursively inline a function into itself. if logopt.Enabled() { logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to %s", ir.FuncName(Curfn))) @@ -939,7 +926,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { // We have a function node, and it has an inlineable body. if base.Flag.LowerM > 1 { - fmt.Printf("%v: inlining call to %v %#v { %#v }\n", ir.Line(n), fn.Sym(), fn.Type(), ir.AsNodes(fn.Func().Inl.Body)) + fmt.Printf("%v: inlining call to %v %#v { %#v }\n", ir.Line(n), fn.Sym(), fn.Type(), ir.AsNodes(fn.Inl.Body)) } else if base.Flag.LowerM != 0 { fmt.Printf("%v: inlining call to %v\n", ir.Line(n), fn) } @@ -969,50 +956,48 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { } // Make temp names to use instead of the originals. - inlvars := make(map[ir.Node]ir.Node) + inlvars := make(map[*ir.Name]ir.Node) // record formals/locals for later post-processing var inlfvars []ir.Node // Handle captured variables when inlining closures. - if fn.Name().Defn != nil { - if c := fn.Name().Defn.Func().OClosure; c != nil { - for _, v := range c.Func().ClosureVars.Slice() { - if v.Op() == ir.OXXX { - continue - } + if c := fn.OClosure; c != nil { + for _, v := range c.Func().ClosureVars { + if v.Op() == ir.OXXX { + continue + } - o := v.Name().Outer - // make sure the outer param matches the inlining location - // NB: if we enabled inlining of functions containing OCLOSURE or refined - // the reassigned check via some sort of copy propagation this would most - // likely need to be changed to a loop to walk up to the correct Param - if o == nil || (o.Name().Curfn != Curfn && o.Name().Curfn.Func().OClosure != Curfn) { - base.Fatalf("%v: unresolvable capture %v %v\n", ir.Line(n), fn, v) - } + o := v.Outer + // make sure the outer param matches the inlining location + // NB: if we enabled inlining of functions containing OCLOSURE or refined + // the reassigned check via some sort of copy propagation this would most + // likely need to be changed to a loop to walk up to the correct Param + if o == nil || (o.Curfn != Curfn && o.Curfn.OClosure != Curfn) { + base.Fatalf("%v: unresolvable capture %v %v\n", ir.Line(n), fn, v) + } - if v.Name().Byval() { - iv := typecheck(inlvar(v), ctxExpr) - ninit.Append(ir.Nod(ir.ODCL, iv, nil)) - ninit.Append(typecheck(ir.Nod(ir.OAS, iv, o), ctxStmt)) - inlvars[v] = iv - } else { - addr := NewName(lookup("&" + v.Sym().Name)) - addr.SetType(types.NewPtr(v.Type())) - ia := typecheck(inlvar(addr), ctxExpr) - ninit.Append(ir.Nod(ir.ODCL, ia, nil)) - ninit.Append(typecheck(ir.Nod(ir.OAS, ia, ir.Nod(ir.OADDR, o, nil)), ctxStmt)) - inlvars[addr] = ia + if v.Byval() { + iv := typecheck(inlvar(v), ctxExpr) + ninit.Append(ir.Nod(ir.ODCL, iv, nil)) + ninit.Append(typecheck(ir.Nod(ir.OAS, iv, o), ctxStmt)) + inlvars[v] = iv + } else { + addr := NewName(lookup("&" + v.Sym().Name)) + addr.SetType(types.NewPtr(v.Type())) + ia := typecheck(inlvar(addr), ctxExpr) + ninit.Append(ir.Nod(ir.ODCL, ia, nil)) + ninit.Append(typecheck(ir.Nod(ir.OAS, ia, ir.Nod(ir.OADDR, o, nil)), ctxStmt)) + inlvars[addr] = ia - // When capturing by reference, all occurrence of the captured var - // must be substituted with dereference of the temporary address - inlvars[v] = typecheck(ir.Nod(ir.ODEREF, ia, nil), ctxExpr) - } + // When capturing by reference, all occurrence of the captured var + // must be substituted with dereference of the temporary address + inlvars[v] = typecheck(ir.Nod(ir.ODEREF, ia, nil), ctxExpr) } } } - for _, ln := range fn.Func().Inl.Dcl { + for _, ln := range fn.Inl.Dcl { if ln.Op() != ir.ONAME { continue } @@ -1040,7 +1025,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { } nreturns := 0 - ir.InspectList(ir.AsNodes(fn.Func().Inl.Body), func(n ir.Node) bool { + ir.InspectList(ir.AsNodes(fn.Inl.Body), func(n ir.Node) bool { if n != nil && n.Op() == ir.ORETURN { nreturns++ } @@ -1057,6 +1042,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { for i, t := range fn.Type().Results().Fields().Slice() { var m ir.Node if n := ir.AsNode(t.Nname); n != nil && !ir.IsBlank(n) && !strings.HasPrefix(n.Sym().Name, "~r") { + n := n.(*ir.Name) m = inlvar(n) m = typecheck(m, ctxExpr) inlvars[n] = m @@ -1155,7 +1141,9 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { if b := base.Ctxt.PosTable.Pos(n.Pos()).Base(); b != nil { parent = b.InliningIndex() } - newIndex := base.Ctxt.InlTree.Add(parent, n.Pos(), fn.Sym().Linksym()) + + sym := fn.Sym().Linksym() + newIndex := base.Ctxt.InlTree.Add(parent, n.Pos(), sym) // Add an inline mark just before the inlined body. // This mark is inline in the code so that it's a reasonable spot @@ -1168,9 +1156,9 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { ninit.Append(inlMark) if base.Flag.GenDwarfInl > 0 { - if !fn.Sym().Linksym().WasInlined() { - base.Ctxt.DwFixups.SetPrecursorFunc(fn.Sym().Linksym(), fn) - fn.Sym().Linksym().Set(obj.AttrWasInlined, true) + if !sym.WasInlined() { + base.Ctxt.DwFixups.SetPrecursorFunc(sym, fn) + sym.Set(obj.AttrWasInlined, true) } } @@ -1183,7 +1171,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node { newInlIndex: newIndex, } - body := subst.list(ir.AsNodes(fn.Func().Inl.Body)) + body := subst.list(ir.AsNodes(fn.Inl.Body)) lab := nodSym(ir.OLABEL, nil, retlabel) body = append(body, lab) @@ -1236,11 +1224,11 @@ func inlvar(var_ ir.Node) ir.Node { n := NewName(var_.Sym()) n.SetType(var_.Type()) n.SetClass(ir.PAUTO) - n.Name().SetUsed(true) - n.Name().Curfn = Curfn // the calling function, not the called one - n.Name().SetAddrtaken(var_.Name().Addrtaken()) + n.SetUsed(true) + n.Curfn = Curfn // the calling function, not the called one + n.SetAddrtaken(var_.Name().Addrtaken()) - Curfn.Func().Dcl = append(Curfn.Func().Dcl, n) + Curfn.Dcl = append(Curfn.Dcl, n) return n } @@ -1249,9 +1237,9 @@ func retvar(t *types.Field, i int) ir.Node { n := NewName(lookupN("~R", i)) n.SetType(t.Type) n.SetClass(ir.PAUTO) - n.Name().SetUsed(true) - n.Name().Curfn = Curfn // the calling function, not the called one - Curfn.Func().Dcl = append(Curfn.Func().Dcl, n) + n.SetUsed(true) + n.Curfn = Curfn // the calling function, not the called one + Curfn.Dcl = append(Curfn.Dcl, n) return n } @@ -1261,9 +1249,9 @@ func argvar(t *types.Type, i int) ir.Node { n := NewName(lookupN("~arg", i)) n.SetType(t.Elem()) n.SetClass(ir.PAUTO) - n.Name().SetUsed(true) - n.Name().Curfn = Curfn // the calling function, not the called one - Curfn.Func().Dcl = append(Curfn.Func().Dcl, n) + n.SetUsed(true) + n.Curfn = Curfn // the calling function, not the called one + Curfn.Dcl = append(Curfn.Dcl, n) return n } @@ -1280,7 +1268,7 @@ type inlsubst struct { // "return" statement. delayretvars bool - inlvars map[ir.Node]ir.Node + inlvars map[*ir.Name]ir.Node // bases maps from original PosBase to PosBase with an extra // inlined call frame. @@ -1311,6 +1299,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { switch n.Op() { case ir.ONAME: + n := n.(*ir.Name) if inlvar := subst.inlvars[n]; inlvar != nil { // These will be set during inlnode if base.Flag.LowerM > 2 { fmt.Printf("substituting name %+v -> %+v\n", n, inlvar) @@ -1409,8 +1398,8 @@ func (subst *inlsubst) updatedPos(xpos src.XPos) src.XPos { return base.Ctxt.PosTable.XPos(pos) } -func pruneUnusedAutos(ll []ir.Node, vis *hairyVisitor) []ir.Node { - s := make([]ir.Node, 0, len(ll)) +func pruneUnusedAutos(ll []*ir.Name, vis *hairyVisitor) []*ir.Name { + s := make([]*ir.Name, 0, len(ll)) for _, n := range ll { if n.Class() == ir.PAUTO { if _, found := vis.usedLocals[n]; !found { @@ -1424,7 +1413,7 @@ func pruneUnusedAutos(ll []ir.Node, vis *hairyVisitor) []ir.Node { // devirtualize replaces interface method calls within fn with direct // concrete-type method calls where applicable. -func devirtualize(fn ir.Node) { +func devirtualize(fn *ir.Func) { Curfn = fn ir.InspectList(fn.Body(), func(n ir.Node) bool { if n.Op() == ir.OCALLINTER { diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 931626159d..7bad05265d 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -277,7 +277,7 @@ func Main(archInit func(*Arch)) { for i := 0; i < len(xtop); i++ { n := xtop[i] if n.Op() == ir.ODCLFUNC { - Curfn = n + Curfn = n.(*ir.Func) decldepth = 1 errorsBefore := base.Errors() typecheckslice(Curfn.Body().Slice(), ctxStmt) @@ -307,8 +307,8 @@ func Main(archInit func(*Arch)) { timings.Start("fe", "capturevars") for _, n := range xtop { if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil { - Curfn = n - capturevars(n) + Curfn = n.(*ir.Func) + capturevars(Curfn) } } capturevarscomplete = true @@ -321,7 +321,7 @@ func Main(archInit func(*Arch)) { // Typecheck imported function bodies if Debug.l > 1, // otherwise lazily when used or re-exported. for _, n := range importlist { - if n.Func().Inl != nil { + if n.Inl != nil { typecheckinl(n) } } @@ -330,7 +330,7 @@ func Main(archInit func(*Arch)) { if base.Flag.LowerL != 0 { // Find functions that can be inlined and clone them before walk expands them. - visitBottomUp(xtop, func(list []ir.Node, recursive bool) { + visitBottomUp(xtop, func(list []*ir.Func, recursive bool) { numfns := numNonClosures(list) for _, n := range list { if !recursive || numfns > 1 { @@ -340,7 +340,7 @@ func Main(archInit func(*Arch)) { caninl(n) } else { if base.Flag.LowerM > 1 { - fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(n), n.Func().Nname) + fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(n), n.Nname) } } inlcalls(n) @@ -350,7 +350,7 @@ func Main(archInit func(*Arch)) { for _, n := range xtop { if n.Op() == ir.ODCLFUNC { - devirtualize(n) + devirtualize(n.(*ir.Func)) } } Curfn = nil @@ -380,8 +380,8 @@ func Main(archInit func(*Arch)) { timings.Start("fe", "xclosures") for _, n := range xtop { if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil { - Curfn = n - transformclosure(n) + Curfn = n.(*ir.Func) + transformclosure(Curfn) } } @@ -403,7 +403,7 @@ func Main(archInit func(*Arch)) { for i := 0; i < len(xtop); i++ { n := xtop[i] if n.Op() == ir.ODCLFUNC { - funccompile(n) + funccompile(n.(*ir.Func)) fcount++ } } @@ -481,10 +481,10 @@ func Main(archInit func(*Arch)) { } // numNonClosures returns the number of functions in list which are not closures. -func numNonClosures(list []ir.Node) int { +func numNonClosures(list []*ir.Func) int { count := 0 - for _, n := range list { - if n.Func().OClosure == nil { + for _, fn := range list { + if fn.OClosure == nil { count++ } } diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index cbe8a24051..8ae5874d3b 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -152,7 +152,7 @@ type noder struct { lastCloseScopePos syntax.Pos } -func (p *noder) funcBody(fn ir.Node, block *syntax.BlockStmt) { +func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) { oldScope := p.scope p.scope = 0 funchdr(fn) @@ -165,7 +165,7 @@ func (p *noder) funcBody(fn ir.Node, block *syntax.BlockStmt) { fn.PtrBody().Set(body) base.Pos = p.makeXPos(block.Rbrace) - fn.Func().Endlineno = base.Pos + fn.Endlineno = base.Pos } funcbody() @@ -176,9 +176,9 @@ func (p *noder) openScope(pos syntax.Pos) { types.Markdcl() if trackScopes { - Curfn.Func().Parents = append(Curfn.Func().Parents, p.scope) - p.scopeVars = append(p.scopeVars, len(Curfn.Func().Dcl)) - p.scope = ir.ScopeID(len(Curfn.Func().Parents)) + Curfn.Parents = append(Curfn.Parents, p.scope) + p.scopeVars = append(p.scopeVars, len(Curfn.Dcl)) + p.scope = ir.ScopeID(len(Curfn.Parents)) p.markScope(pos) } @@ -191,29 +191,29 @@ func (p *noder) closeScope(pos syntax.Pos) { if trackScopes { scopeVars := p.scopeVars[len(p.scopeVars)-1] p.scopeVars = p.scopeVars[:len(p.scopeVars)-1] - if scopeVars == len(Curfn.Func().Dcl) { + if scopeVars == len(Curfn.Dcl) { // no variables were declared in this scope, so we can retract it. - if int(p.scope) != len(Curfn.Func().Parents) { + if int(p.scope) != len(Curfn.Parents) { base.Fatalf("scope tracking inconsistency, no variables declared but scopes were not retracted") } - p.scope = Curfn.Func().Parents[p.scope-1] - Curfn.Func().Parents = Curfn.Func().Parents[:len(Curfn.Func().Parents)-1] + p.scope = Curfn.Parents[p.scope-1] + Curfn.Parents = Curfn.Parents[:len(Curfn.Parents)-1] - nmarks := len(Curfn.Func().Marks) - Curfn.Func().Marks[nmarks-1].Scope = p.scope + nmarks := len(Curfn.Marks) + Curfn.Marks[nmarks-1].Scope = p.scope prevScope := ir.ScopeID(0) if nmarks >= 2 { - prevScope = Curfn.Func().Marks[nmarks-2].Scope + prevScope = Curfn.Marks[nmarks-2].Scope } - if Curfn.Func().Marks[nmarks-1].Scope == prevScope { - Curfn.Func().Marks = Curfn.Func().Marks[:nmarks-1] + if Curfn.Marks[nmarks-1].Scope == prevScope { + Curfn.Marks = Curfn.Marks[:nmarks-1] } return } - p.scope = Curfn.Func().Parents[p.scope-1] + p.scope = Curfn.Parents[p.scope-1] p.markScope(pos) } @@ -221,10 +221,10 @@ func (p *noder) closeScope(pos syntax.Pos) { func (p *noder) markScope(pos syntax.Pos) { xpos := p.makeXPos(pos) - if i := len(Curfn.Func().Marks); i > 0 && Curfn.Func().Marks[i-1].Pos == xpos { - Curfn.Func().Marks[i-1].Scope = p.scope + if i := len(Curfn.Marks); i > 0 && Curfn.Marks[i-1].Pos == xpos { + Curfn.Marks[i-1].Scope = p.scope } else { - Curfn.Func().Marks = append(Curfn.Func().Marks, ir.Mark{Pos: xpos, Scope: p.scope}) + Curfn.Marks = append(Curfn.Marks, ir.Mark{Pos: xpos, Scope: p.scope}) } } @@ -444,6 +444,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node { nn := make([]ir.Node, 0, len(names)) for i, n := range names { + n := n.(*ir.Name) if i >= len(values) { base.Errorf("missing value in const declaration") break @@ -456,8 +457,8 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node { n.SetOp(ir.OLITERAL) declare(n, dclcontext) - n.Name().Ntype = typ - n.Name().Defn = v + n.Ntype = typ + n.Defn = v n.SetIota(cs.iota) nn = append(nn, p.nod(decl, ir.ODCLCONST, n, nil)) @@ -514,7 +515,7 @@ func (p *noder) declName(name *syntax.Name) *ir.Name { func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node { name := p.name(fun.Name) t := p.signature(fun.Recv, fun.Type) - f := p.nod(fun, ir.ODCLFUNC, nil, nil) + f := ir.NewFunc(p.pos(fun)) if fun.Recv == nil { if name.Name == "init" { @@ -530,16 +531,16 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node { } } } else { - f.Func().Shortname = name + f.Shortname = name name = ir.BlankNode.Sym() // filled in by typecheckfunc } - f.Func().Nname = newfuncnamel(p.pos(fun.Name), name, f.Func()) - f.Func().Nname.Name().Defn = f - f.Func().Nname.Name().Ntype = t + f.Nname = newFuncNameAt(p.pos(fun.Name), name, f) + f.Nname.Defn = f + f.Nname.Ntype = t if pragma, ok := fun.Pragma.(*Pragma); ok { - f.Func().Pragma = pragma.Flag & FuncPragmas + f.Pragma = pragma.Flag & FuncPragmas if pragma.Flag&ir.Systemstack != 0 && pragma.Flag&ir.Nosplit != 0 { base.ErrorfAt(f.Pos(), "go:nosplit and go:systemstack cannot be combined") } @@ -548,13 +549,13 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node { } if fun.Recv == nil { - declare(f.Func().Nname, ir.PFUNC) + declare(f.Nname, ir.PFUNC) } p.funcBody(f, fun.Body) if fun.Body != nil { - if f.Func().Pragma&ir.Noescape != 0 { + if f.Pragma&ir.Noescape != 0 { base.ErrorfAt(f.Pos(), "can only use //go:noescape with external func implementations") } } else { @@ -1059,7 +1060,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node { n := p.nod(stmt, ir.ORETURN, nil, nil) n.PtrList().Set(results) if n.List().Len() == 0 && Curfn != nil { - for _, ln := range Curfn.Func().Dcl { + for _, ln := range Curfn.Dcl { if ln.Class() == ir.PPARAM { continue } @@ -1133,7 +1134,7 @@ func (p *noder) assignList(expr syntax.Expr, defn ir.Node, colas bool) []ir.Node newOrErr = true n := NewName(sym) declare(n, dclcontext) - n.Name().Defn = defn + n.Defn = defn defn.PtrInit().Append(ir.Nod(ir.ODCL, n, nil)) res[i] = n } @@ -1240,7 +1241,7 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch ir.Node, rbrac declare(nn, dclcontext) n.PtrRlist().Set1(nn) // keep track of the instances for reporting unused - nn.Name().Defn = tswitch + nn.Defn = tswitch } // Trim trailing empty statements. We omit them from diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index d566959d9e..7b5e3015c2 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -143,7 +143,7 @@ func dumpdata() { for i := xtops; i < len(xtop); i++ { n := xtop[i] if n.Op() == ir.ODCLFUNC { - funccompile(n) + funccompile(n.(*ir.Func)) } } xtops = len(xtop) diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index b7d713439b..6a91b8c91b 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -51,9 +51,9 @@ type Order struct { // Order rewrites fn.Nbody to apply the ordering constraints // described in the comment at the top of the file. -func order(fn ir.Node) { +func order(fn *ir.Func) { if base.Flag.W > 1 { - s := fmt.Sprintf("\nbefore order %v", fn.Func().Nname.Sym()) + s := fmt.Sprintf("\nbefore order %v", fn.Sym()) ir.DumpList(s, fn.Body()) } @@ -1258,7 +1258,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { } case ir.OCLOSURE: - if n.Transient() && n.Func().ClosureVars.Len() > 0 { + if n.Transient() && len(n.Func().ClosureVars) > 0 { prealloc[n] = o.newTemp(closureType(n), false) } diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index b74b132632..ea294ed66d 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -24,14 +24,14 @@ import ( // "Portable" code generation. var ( - compilequeue []ir.Node // functions waiting to be compiled + compilequeue []*ir.Func // functions waiting to be compiled ) -func emitptrargsmap(fn ir.Node) { - if ir.FuncName(fn) == "_" || fn.Func().Nname.Sym().Linkname != "" { +func emitptrargsmap(fn *ir.Func) { + if ir.FuncName(fn) == "_" || fn.Sym().Linkname != "" { return } - lsym := base.Ctxt.Lookup(fn.Func().LSym.Name + ".args_stackmap") + lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap") nptr := int(fn.Type().ArgWidth() / int64(Widthptr)) bv := bvalloc(int32(nptr) * 2) @@ -68,7 +68,7 @@ func emitptrargsmap(fn ir.Node) { // really means, in memory, things with pointers needing zeroing at // the top of the stack and increasing in size. // Non-autos sort on offset. -func cmpstackvarlt(a, b ir.Node) bool { +func cmpstackvarlt(a, b *ir.Name) bool { if (a.Class() == ir.PAUTO) != (b.Class() == ir.PAUTO) { return b.Class() == ir.PAUTO } @@ -101,7 +101,7 @@ func cmpstackvarlt(a, b ir.Node) bool { } // byStackvar implements sort.Interface for []*Node using cmpstackvarlt. -type byStackVar []ir.Node +type byStackVar []*ir.Name func (s byStackVar) Len() int { return len(s) } func (s byStackVar) Less(i, j int) bool { return cmpstackvarlt(s[i], s[j]) } @@ -110,7 +110,7 @@ func (s byStackVar) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s *ssafn) AllocFrame(f *ssa.Func) { s.stksize = 0 s.stkptrsize = 0 - fn := s.curfn.Func() + fn := s.curfn // Mark the PAUTO's unused. for _, ln := range fn.Dcl { @@ -193,9 +193,9 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { s.stkptrsize = Rnd(s.stkptrsize, int64(Widthreg)) } -func funccompile(fn ir.Node) { +func funccompile(fn *ir.Func) { if Curfn != nil { - base.Fatalf("funccompile %v inside %v", fn.Func().Nname.Sym(), Curfn.Func().Nname.Sym()) + base.Fatalf("funccompile %v inside %v", fn.Sym(), Curfn.Sym()) } if fn.Type() == nil { @@ -210,21 +210,19 @@ func funccompile(fn ir.Node) { if fn.Body().Len() == 0 { // Initialize ABI wrappers if necessary. - initLSym(fn.Func(), false) + initLSym(fn, false) emitptrargsmap(fn) return } dclcontext = ir.PAUTO Curfn = fn - compile(fn) - Curfn = nil dclcontext = ir.PEXTERN } -func compile(fn ir.Node) { +func compile(fn *ir.Func) { errorsBefore := base.Errors() order(fn) if base.Errors() > errorsBefore { @@ -234,7 +232,7 @@ func compile(fn ir.Node) { // Set up the function's LSym early to avoid data races with the assemblers. // Do this before walk, as walk needs the LSym to set attributes/relocations // (e.g. in markTypeUsedInInterface). - initLSym(fn.Func(), true) + initLSym(fn, true) walk(fn) if base.Errors() > errorsBefore { @@ -259,15 +257,15 @@ func compile(fn ir.Node) { // be types of stack objects. We need to do this here // because symbols must be allocated before the parallel // phase of the compiler. - for _, n := range fn.Func().Dcl { + for _, n := range fn.Dcl { switch n.Class() { case ir.PPARAM, ir.PPARAMOUT, ir.PAUTO: if livenessShouldTrack(n) && n.Name().Addrtaken() { dtypesym(n.Type()) // Also make sure we allocate a linker symbol // for the stack object data, for the same reason. - if fn.Func().LSym.Func().StackObjects == nil { - fn.Func().LSym.Func().StackObjects = base.Ctxt.Lookup(fn.Func().LSym.Name + ".stkobj") + if fn.LSym.Func().StackObjects == nil { + fn.LSym.Func().StackObjects = base.Ctxt.Lookup(fn.LSym.Name + ".stkobj") } } } @@ -284,7 +282,7 @@ func compile(fn ir.Node) { // If functions are not compiled immediately, // they are enqueued in compilequeue, // which is drained by compileFunctions. -func compilenow(fn ir.Node) bool { +func compilenow(fn *ir.Func) bool { // Issue 38068: if this function is a method AND an inline // candidate AND was not inlined (yet), put it onto the compile // queue instead of compiling it immediately. This is in case we @@ -299,8 +297,8 @@ func compilenow(fn ir.Node) bool { // isInlinableButNotInlined returns true if 'fn' was marked as an // inline candidate but then never inlined (presumably because we // found no call sites). -func isInlinableButNotInlined(fn ir.Node) bool { - if fn.Func().Nname.Func().Inl == nil { +func isInlinableButNotInlined(fn *ir.Func) bool { + if fn.Inl == nil { return false } if fn.Sym() == nil { @@ -315,7 +313,7 @@ const maxStackSize = 1 << 30 // uses it to generate a plist, // and flushes that plist to machine code. // worker indicates which of the backend workers is doing the processing. -func compileSSA(fn ir.Node, worker int) { +func compileSSA(fn *ir.Func, worker int) { f := buildssa(fn, worker) // Note: check arg size to fix issue 25507. if f.Frontend().(*ssafn).stksize >= maxStackSize || fn.Type().ArgWidth() >= maxStackSize { @@ -343,7 +341,7 @@ func compileSSA(fn ir.Node, worker int) { pp.Flush() // assemble, fill in boilerplate, etc. // fieldtrack must be called after pp.Flush. See issue 20014. - fieldtrack(pp.Text.From.Sym, fn.Func().FieldTrack) + fieldtrack(pp.Text.From.Sym, fn.FieldTrack) } func init() { @@ -360,7 +358,7 @@ func compileFunctions() { sizeCalculationDisabled = true // not safe to calculate sizes concurrently if race.Enabled { // Randomize compilation order to try to shake out races. - tmp := make([]ir.Node, len(compilequeue)) + tmp := make([]*ir.Func, len(compilequeue)) perm := rand.Perm(len(compilequeue)) for i, v := range perm { tmp[v] = compilequeue[i] @@ -376,7 +374,7 @@ func compileFunctions() { } var wg sync.WaitGroup base.Ctxt.InParallel = true - c := make(chan ir.Node, base.Flag.LowerC) + c := make(chan *ir.Func, base.Flag.LowerC) for i := 0; i < base.Flag.LowerC; i++ { wg.Add(1) go func(worker int) { @@ -398,9 +396,10 @@ func compileFunctions() { } func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope, dwarf.InlCalls) { - fn := curfn.(ir.Node) - if fn.Func().Nname != nil { - if expect := fn.Func().Nname.Sym().Linksym(); fnsym != expect { + fn := curfn.(*ir.Func) + + if fn.Nname != nil { + if expect := fn.Sym().Linksym(); fnsym != expect { base.Fatalf("unexpected fnsym: %v != %v", fnsym, expect) } } @@ -430,12 +429,19 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S // // These two adjustments keep toolstash -cmp working for now. // Deciding the right answer is, as they say, future work. - isODCLFUNC := fn.Op() == ir.ODCLFUNC + // + // We can tell the difference between the old ODCLFUNC and ONAME + // cases by looking at the infosym.Name. If it's empty, DebugInfo is + // being called from (*obj.Link).populateDWARF, which used to use + // the ODCLFUNC. If it's non-empty (the name will end in $abstract), + // DebugInfo is being called from (*obj.Link).DwarfAbstractFunc, + // which used to use the ONAME form. + isODCLFUNC := infosym.Name == "" var apdecls []ir.Node // Populate decls for fn. if isODCLFUNC { - for _, n := range fn.Func().Dcl { + for _, n := range fn.Dcl { if n.Op() != ir.ONAME { // might be OTYPE or OLITERAL continue } @@ -457,7 +463,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S } } - decls, dwarfVars := createDwarfVars(fnsym, isODCLFUNC, fn.Func(), apdecls) + decls, dwarfVars := createDwarfVars(fnsym, isODCLFUNC, fn, apdecls) // For each type referenced by the functions auto vars but not // already referenced by a dwarf var, attach an R_USETYPE relocation to @@ -478,7 +484,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S var varScopes []ir.ScopeID for _, decl := range decls { pos := declPos(decl) - varScopes = append(varScopes, findScope(fn.Func().Marks, pos)) + varScopes = append(varScopes, findScope(fn.Marks, pos)) } scopes := assembleScopes(fnsym, fn, dwarfVars, varScopes) @@ -709,9 +715,9 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []ir. // names of the variables may have been "versioned" to avoid conflicts // with local vars; disregard this versioning when sorting. func preInliningDcls(fnsym *obj.LSym) []ir.Node { - fn := base.Ctxt.DwFixups.GetPrecursorFunc(fnsym).(ir.Node) + fn := base.Ctxt.DwFixups.GetPrecursorFunc(fnsym).(*ir.Func) var rdcl []ir.Node - for _, n := range fn.Func().Inl.Dcl { + for _, n := range fn.Inl.Dcl { c := n.Sym().Name[0] // Avoid reporting "_" parameters, since if there are more than // one, it can result in a collision later on, as in #23179. diff --git a/src/cmd/compile/internal/gc/pgen_test.go b/src/cmd/compile/internal/gc/pgen_test.go index 1984f9aa08..35ce087af6 100644 --- a/src/cmd/compile/internal/gc/pgen_test.go +++ b/src/cmd/compile/internal/gc/pgen_test.go @@ -26,19 +26,19 @@ func typeWithPointers() *types.Type { return t } -func markUsed(n ir.Node) ir.Node { - n.Name().SetUsed(true) +func markUsed(n *ir.Name) *ir.Name { + n.SetUsed(true) return n } -func markNeedZero(n ir.Node) ir.Node { - n.Name().SetNeedzero(true) +func markNeedZero(n *ir.Name) *ir.Name { + n.SetNeedzero(true) return n } // Test all code paths for cmpstackvarlt. func TestCmpstackvar(t *testing.T) { - nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) ir.Node { + nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Name { if s == nil { s = &types.Sym{Name: "."} } @@ -49,7 +49,7 @@ func TestCmpstackvar(t *testing.T) { return n } testdata := []struct { - a, b ir.Node + a, b *ir.Name lt bool }{ { @@ -156,14 +156,14 @@ func TestCmpstackvar(t *testing.T) { } func TestStackvarSort(t *testing.T) { - nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) ir.Node { + nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Name { n := NewName(s) n.SetType(t) n.SetOffset(xoffset) n.SetClass(cl) return n } - inp := []ir.Node{ + inp := []*ir.Name{ nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), @@ -178,7 +178,7 @@ func TestStackvarSort(t *testing.T) { nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), } - want := []ir.Node{ + want := []*ir.Name{ nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), nod(10, &types.Type{}, &types.Sym{}, ir.PFUNC), diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index e3a9b2a198..6ad3140081 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -101,7 +101,7 @@ type BlockEffects struct { // A collection of global state used by liveness analysis. type Liveness struct { - fn ir.Node + fn *ir.Func f *ssa.Func vars []ir.Node idx map[ir.Node]int32 @@ -212,9 +212,9 @@ func livenessShouldTrack(n ir.Node) bool { // getvariables returns the list of on-stack variables that we need to track // and a map for looking up indices by *Node. -func getvariables(fn ir.Node) ([]ir.Node, map[ir.Node]int32) { +func getvariables(fn *ir.Func) ([]ir.Node, map[ir.Node]int32) { var vars []ir.Node - for _, n := range fn.Func().Dcl { + for _, n := range fn.Dcl { if livenessShouldTrack(n) { vars = append(vars, n) } @@ -356,7 +356,7 @@ type livenessFuncCache struct { // Constructs a new liveness structure used to hold the global state of the // liveness computation. The cfg argument is a slice of *BasicBlocks and the // vars argument is a slice of *Nodes. -func newliveness(fn ir.Node, f *ssa.Func, vars []ir.Node, idx map[ir.Node]int32, stkptrsize int64) *Liveness { +func newliveness(fn *ir.Func, f *ssa.Func, vars []ir.Node, idx map[ir.Node]int32, stkptrsize int64) *Liveness { lv := &Liveness{ fn: fn, f: f, @@ -788,7 +788,7 @@ func (lv *Liveness) epilogue() { // pointers to copy values back to the stack). // TODO: if the output parameter is heap-allocated, then we // don't need to keep the stack copy live? - if lv.fn.Func().HasDefer() { + if lv.fn.HasDefer() { for i, n := range lv.vars { if n.Class() == ir.PPARAMOUT { if n.Name().IsOutputParamHeapAddr() { @@ -891,7 +891,7 @@ func (lv *Liveness) epilogue() { if n.Class() == ir.PPARAM { continue // ok } - base.Fatalf("bad live variable at entry of %v: %L", lv.fn.Func().Nname, n) + base.Fatalf("bad live variable at entry of %v: %L", lv.fn.Nname, n) } // Record live variables. @@ -904,7 +904,7 @@ func (lv *Liveness) epilogue() { } // If we have an open-coded deferreturn call, make a liveness map for it. - if lv.fn.Func().OpenCodedDeferDisallowed() { + if lv.fn.OpenCodedDeferDisallowed() { lv.livenessMap.deferreturn = LivenessDontCare } else { lv.livenessMap.deferreturn = LivenessIndex{ @@ -922,7 +922,7 @@ func (lv *Liveness) epilogue() { // input parameters. for j, n := range lv.vars { if n.Class() != ir.PPARAM && lv.stackMaps[0].Get(int32(j)) { - lv.f.Fatalf("%v %L recorded as live on entry", lv.fn.Func().Nname, n) + lv.f.Fatalf("%v %L recorded as live on entry", lv.fn.Nname, n) } } } @@ -980,7 +980,7 @@ func (lv *Liveness) showlive(v *ssa.Value, live bvec) { return } - pos := lv.fn.Func().Nname.Pos() + pos := lv.fn.Nname.Pos() if v != nil { pos = v.Pos } @@ -1090,7 +1090,7 @@ func (lv *Liveness) printDebug() { if b == lv.f.Entry { live := lv.stackMaps[0] - fmt.Printf("(%s) function entry\n", base.FmtPos(lv.fn.Func().Nname.Pos())) + fmt.Printf("(%s) function entry\n", base.FmtPos(lv.fn.Nname.Pos())) fmt.Printf("\tlive=") printed = false for j, n := range lv.vars { @@ -1266,7 +1266,7 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap { } // Emit the live pointer map data structures - ls := e.curfn.Func().LSym + ls := e.curfn.LSym fninfo := ls.Func() fninfo.GCArgs, fninfo.GCLocals = lv.emit() diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go index c41d923f78..6b5d53e806 100644 --- a/src/cmd/compile/internal/gc/racewalk.go +++ b/src/cmd/compile/internal/gc/racewalk.go @@ -60,13 +60,13 @@ func ispkgin(pkgs []string) bool { return false } -func instrument(fn ir.Node) { - if fn.Func().Pragma&ir.Norace != 0 { +func instrument(fn *ir.Func) { + if fn.Pragma&ir.Norace != 0 { return } if !base.Flag.Race || !ispkgin(norace_inst_pkgs) { - fn.Func().SetInstrumentBody(true) + fn.SetInstrumentBody(true) } if base.Flag.Race { @@ -74,8 +74,8 @@ func instrument(fn ir.Node) { base.Pos = src.NoXPos if thearch.LinkArch.Arch.Family != sys.AMD64 { - fn.Func().Enter.Prepend(mkcall("racefuncenterfp", nil, nil)) - fn.Func().Exit.Append(mkcall("racefuncexit", nil, nil)) + fn.Enter.Prepend(mkcall("racefuncenterfp", nil, nil)) + fn.Exit.Append(mkcall("racefuncexit", nil, nil)) } else { // nodpc is the PC of the caller as extracted by @@ -83,12 +83,12 @@ func instrument(fn ir.Node) { // This only works for amd64. This will not // work on arm or others that might support // race in the future. - nodpc := ir.Copy(nodfp) + nodpc := ir.Copy(nodfp).(*ir.Name) nodpc.SetType(types.Types[types.TUINTPTR]) nodpc.SetOffset(int64(-Widthptr)) - fn.Func().Dcl = append(fn.Func().Dcl, nodpc) - fn.Func().Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc)) - fn.Func().Exit.Append(mkcall("racefuncexit", nil, nil)) + fn.Dcl = append(fn.Dcl, nodpc) + fn.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc)) + fn.Exit.Append(mkcall("racefuncexit", nil, nil)) } base.Pos = lno } diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go index 0ff00cca44..d52fad5fec 100644 --- a/src/cmd/compile/internal/gc/range.go +++ b/src/cmd/compile/internal/gc/range.go @@ -593,7 +593,7 @@ func arrayClear(n, v1, v2, a ir.Node) bool { var fn ir.Node if a.Type().Elem().HasPointers() { // memclrHasPointers(hp, hn) - Curfn.Func().SetWBPos(stmt.Pos()) + Curfn.SetWBPos(stmt.Pos()) fn = mkcall("memclrHasPointers", nil, nil, hp, hn) } else { // memclrNoHeapPointers(hp, hn) diff --git a/src/cmd/compile/internal/gc/scc.go b/src/cmd/compile/internal/gc/scc.go index fe7956d5d5..063aaa09bd 100644 --- a/src/cmd/compile/internal/gc/scc.go +++ b/src/cmd/compile/internal/gc/scc.go @@ -32,10 +32,10 @@ import "cmd/compile/internal/ir" // when analyzing a set of mutually recursive functions. type bottomUpVisitor struct { - analyze func([]ir.Node, bool) + analyze func([]*ir.Func, bool) visitgen uint32 - nodeID map[ir.Node]uint32 - stack []ir.Node + nodeID map[*ir.Func]uint32 + stack []*ir.Func } // visitBottomUp invokes analyze on the ODCLFUNC nodes listed in list. @@ -51,18 +51,18 @@ type bottomUpVisitor struct { // If recursive is false, the list consists of only a single function and its closures. // If recursive is true, the list may still contain only a single function, // if that function is itself recursive. -func visitBottomUp(list []ir.Node, analyze func(list []ir.Node, recursive bool)) { +func visitBottomUp(list []ir.Node, analyze func(list []*ir.Func, recursive bool)) { var v bottomUpVisitor v.analyze = analyze - v.nodeID = make(map[ir.Node]uint32) + v.nodeID = make(map[*ir.Func]uint32) for _, n := range list { if n.Op() == ir.ODCLFUNC && !n.Func().IsHiddenClosure() { - v.visit(n) + v.visit(n.(*ir.Func)) } } } -func (v *bottomUpVisitor) visit(n ir.Node) uint32 { +func (v *bottomUpVisitor) visit(n *ir.Func) uint32 { if id := v.nodeID[n]; id > 0 { // already visited return id @@ -80,41 +80,41 @@ func (v *bottomUpVisitor) visit(n ir.Node) uint32 { case ir.ONAME: if n.Class() == ir.PFUNC { if n != nil && n.Name().Defn != nil { - if m := v.visit(n.Name().Defn); m < min { + if m := v.visit(n.Name().Defn.(*ir.Func)); m < min { min = m } } } case ir.OMETHEXPR: fn := methodExprName(n) - if fn != nil && fn.Name().Defn != nil { - if m := v.visit(fn.Name().Defn); m < min { + if fn != nil && fn.Defn != nil { + if m := v.visit(fn.Defn.(*ir.Func)); m < min { min = m } } case ir.ODOTMETH: fn := methodExprName(n) - if fn != nil && fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC && fn.Name().Defn != nil { - if m := v.visit(fn.Name().Defn); m < min { + if fn != nil && fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC && fn.Defn != nil { + if m := v.visit(fn.Defn.(*ir.Func)); m < min { min = m } } case ir.OCALLPART: fn := ir.AsNode(callpartMethod(n).Nname) if fn != nil && fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC && fn.Name().Defn != nil { - if m := v.visit(fn.Name().Defn); m < min { + if m := v.visit(fn.Name().Defn.(*ir.Func)); m < min { min = m } } case ir.OCLOSURE: - if m := v.visit(n.Func().Decl); m < min { + if m := v.visit(n.Func()); m < min { min = m } } return true }) - if (min == id || min == id+1) && !n.Func().IsHiddenClosure() { + if (min == id || min == id+1) && !n.IsHiddenClosure() { // This node is the root of a strongly connected component. // The original min passed to visitcodelist was v.nodeID[n]+1. diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 1a13b14376..91faf18a1d 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -40,7 +40,7 @@ const ssaDumpFile = "ssa.html" const maxOpenDefers = 8 // ssaDumpInlined holds all inlined functions when ssaDump contains a function name. -var ssaDumpInlined []ir.Node +var ssaDumpInlined []*ir.Func func initssaconfig() { types_ := ssa.NewTypes() @@ -242,8 +242,8 @@ func dvarint(x *obj.LSym, off int, v int64) int { // - Size of the argument // - Offset of where argument should be placed in the args frame when making call func (s *state) emitOpenDeferInfo() { - x := base.Ctxt.Lookup(s.curfn.Func().LSym.Name + ".opendefer") - s.curfn.Func().LSym.Func().OpenCodedDeferInfo = x + x := base.Ctxt.Lookup(s.curfn.LSym.Name + ".opendefer") + s.curfn.LSym.Func().OpenCodedDeferInfo = x off := 0 // Compute maxargsize (max size of arguments for all defers) @@ -289,7 +289,7 @@ func (s *state) emitOpenDeferInfo() { // buildssa builds an SSA function for fn. // worker indicates which of the backend workers is doing the processing. -func buildssa(fn ir.Node, worker int) *ssa.Func { +func buildssa(fn *ir.Func, worker int) *ssa.Func { name := ir.FuncName(fn) printssa := false if ssaDump != "" { // match either a simple name e.g. "(*Reader).Reset", or a package.name e.g. "compress/gzip.(*Reader).Reset" @@ -298,9 +298,9 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { var astBuf *bytes.Buffer if printssa { astBuf = &bytes.Buffer{} - ir.FDumpList(astBuf, "buildssa-enter", fn.Func().Enter) + ir.FDumpList(astBuf, "buildssa-enter", fn.Enter) ir.FDumpList(astBuf, "buildssa-body", fn.Body()) - ir.FDumpList(astBuf, "buildssa-exit", fn.Func().Exit) + ir.FDumpList(astBuf, "buildssa-exit", fn.Exit) if ssaDumpStdout { fmt.Println("generating SSA for", name) fmt.Print(astBuf.String()) @@ -311,8 +311,8 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { s.pushLine(fn.Pos()) defer s.popLine() - s.hasdefer = fn.Func().HasDefer() - if fn.Func().Pragma&ir.CgoUnsafeArgs != 0 { + s.hasdefer = fn.HasDefer() + if fn.Pragma&ir.CgoUnsafeArgs != 0 { s.cgoUnsafeArgs = true } @@ -331,7 +331,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { s.f.Name = name s.f.DebugTest = s.f.DebugHashMatch("GOSSAHASH") s.f.PrintOrHtmlSSA = printssa - if fn.Func().Pragma&ir.Nosplit != 0 { + if fn.Pragma&ir.Nosplit != 0 { s.f.NoSplit = true } s.panics = map[funcLine]*ssa.Block{} @@ -359,7 +359,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { s.fwdVars = map[ir.Node]*ssa.Value{} s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem) - s.hasOpenDefers = base.Flag.N == 0 && s.hasdefer && !s.curfn.Func().OpenCodedDeferDisallowed() + s.hasOpenDefers = base.Flag.N == 0 && s.hasdefer && !s.curfn.OpenCodedDeferDisallowed() switch { case s.hasOpenDefers && (base.Ctxt.Flag_shared || base.Ctxt.Flag_dynlink) && thearch.LinkArch.Name == "386": // Don't support open-coded defers for 386 ONLY when using shared @@ -368,7 +368,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { // that we don't track correctly. s.hasOpenDefers = false } - if s.hasOpenDefers && s.curfn.Func().Exit.Len() > 0 { + if s.hasOpenDefers && s.curfn.Exit.Len() > 0 { // Skip doing open defers if there is any extra exit code (likely // copying heap-allocated return values or race detection), since // we will not generate that code in the case of the extra @@ -376,7 +376,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { s.hasOpenDefers = false } if s.hasOpenDefers && - s.curfn.Func().NumReturns*s.curfn.Func().NumDefers > 15 { + s.curfn.NumReturns*s.curfn.NumDefers > 15 { // Since we are generating defer calls at every exit for // open-coded defers, skip doing open-coded defers if there are // too many returns (especially if there are multiple defers). @@ -413,7 +413,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { s.decladdrs = map[ir.Node]*ssa.Value{} var args []ssa.Param var results []ssa.Param - for _, n := range fn.Func().Dcl { + for _, n := range fn.Dcl { switch n.Class() { case ir.PPARAM: s.decladdrs[n] = s.entryNewValue2A(ssa.OpLocalAddr, types.NewPtr(n.Type()), n, s.sp, s.startmem) @@ -440,7 +440,7 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { } // Populate SSAable arguments. - for _, n := range fn.Func().Dcl { + for _, n := range fn.Dcl { if n.Class() == ir.PPARAM && s.canSSA(n) { v := s.newValue0A(ssa.OpArg, n.Type(), n) s.vars[n] = v @@ -449,12 +449,12 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { } // Convert the AST-based IR to the SSA-based IR - s.stmtList(fn.Func().Enter) + s.stmtList(fn.Enter) s.stmtList(fn.Body()) // fallthrough to exit if s.curBlock != nil { - s.pushLine(fn.Func().Endlineno) + s.pushLine(fn.Endlineno) s.exit() s.popLine() } @@ -477,10 +477,10 @@ func buildssa(fn ir.Node, worker int) *ssa.Func { return s.f } -func dumpSourcesColumn(writer *ssa.HTMLWriter, fn ir.Node) { +func dumpSourcesColumn(writer *ssa.HTMLWriter, fn *ir.Func) { // Read sources of target function fn. fname := base.Ctxt.PosTable.Pos(fn.Pos()).Filename() - targetFn, err := readFuncLines(fname, fn.Pos().Line(), fn.Func().Endlineno.Line()) + targetFn, err := readFuncLines(fname, fn.Pos().Line(), fn.Endlineno.Line()) if err != nil { writer.Logf("cannot read sources for function %v: %v", fn, err) } @@ -488,13 +488,7 @@ func dumpSourcesColumn(writer *ssa.HTMLWriter, fn ir.Node) { // Read sources of inlined functions. var inlFns []*ssa.FuncLines for _, fi := range ssaDumpInlined { - var elno src.XPos - if fi.Name().Defn == nil { - // Endlineno is filled from exported data. - elno = fi.Func().Endlineno - } else { - elno = fi.Name().Defn.Func().Endlineno - } + elno := fi.Endlineno fname := base.Ctxt.PosTable.Pos(fi.Pos()).Filename() fnLines, err := readFuncLines(fname, fi.Pos().Line(), elno.Line()) if err != nil { @@ -593,7 +587,7 @@ type state struct { f *ssa.Func // Node for function - curfn ir.Node + curfn *ir.Func // labels in f labels map[string]*ssaLabel @@ -972,7 +966,7 @@ func (s *state) newValueOrSfCall2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Valu } func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) { - if !s.curfn.Func().InstrumentBody() { + if !s.curfn.InstrumentBody() { return } @@ -1571,7 +1565,7 @@ func (s *state) exit() *ssa.Block { // Run exit code. Typically, this code copies heap-allocated PPARAMOUT // variables back to the stack. - s.stmtList(s.curfn.Func().Exit) + s.stmtList(s.curfn.Exit) // Store SSAable PPARAMOUT variables back to stack locations. for _, n := range s.returns { @@ -4296,7 +4290,7 @@ func (s *state) openDeferSave(n ir.Node, t *types.Type, val *ssa.Value) *ssa.Val pos = n.Pos() } argTemp := tempAt(pos.WithNotStmt(), s.curfn, t) - argTemp.Name().SetOpenDeferSlot(true) + argTemp.SetOpenDeferSlot(true) var addrArgTemp *ssa.Value // Use OpVarLive to make sure stack slots for the args, etc. are not // removed by dead-store elimination @@ -4322,7 +4316,7 @@ func (s *state) openDeferSave(n ir.Node, t *types.Type, val *ssa.Value) *ssa.Val // Therefore, we must make sure it is zeroed out in the entry // block if it contains pointers, else GC may wrongly follow an // uninitialized pointer value. - argTemp.Name().SetNeedzero(true) + argTemp.SetNeedzero(true) } if !canSSA { a := s.addr(n) @@ -4790,7 +4784,7 @@ func (s *state) getMethodClosure(fn ir.Node) *ssa.Value { // We get back an SSA value representing &sync.(*Mutex).Unlock·f. // We can then pass that to defer or go. n2 := ir.NewNameAt(fn.Pos(), fn.Sym()) - n2.Name().Curfn = s.curfn + n2.Curfn = s.curfn n2.SetClass(ir.PFUNC) // n2.Sym already existed, so it's already marked as a function. n2.SetPos(fn.Pos()) @@ -5023,7 +5017,7 @@ func (s *state) exprPtr(n ir.Node, bounded bool, lineno src.XPos) *ssa.Value { // Used only for automatically inserted nil checks, // not for user code like 'x != nil'. func (s *state) nilCheck(ptr *ssa.Value) { - if base.Debug.DisableNil != 0 || s.curfn.Func().NilCheckDisabled() { + if base.Debug.DisableNil != 0 || s.curfn.NilCheckDisabled() { return } s.newValue2(ssa.OpNilCheck, types.TypeVoid, ptr, s.mem()) @@ -6197,7 +6191,7 @@ func (s byXoffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func emitStackObjects(e *ssafn, pp *Progs) { var vars []ir.Node - for _, n := range e.curfn.Func().Dcl { + for _, n := range e.curfn.Dcl { if livenessShouldTrack(n) && n.Name().Addrtaken() { vars = append(vars, n) } @@ -6211,7 +6205,7 @@ func emitStackObjects(e *ssafn, pp *Progs) { // Populate the stack object data. // Format must match runtime/stack.go:stackObjectRecord. - x := e.curfn.Func().LSym.Func().StackObjects + x := e.curfn.LSym.Func().StackObjects off := 0 off = duintptr(x, off, uint64(len(vars))) for _, v := range vars { @@ -6248,7 +6242,7 @@ func genssa(f *ssa.Func, pp *Progs) { s.livenessMap = liveness(e, f, pp) emitStackObjects(e, pp) - openDeferInfo := e.curfn.Func().LSym.Func().OpenCodedDeferInfo + openDeferInfo := e.curfn.LSym.Func().OpenCodedDeferInfo if openDeferInfo != nil { // This function uses open-coded defers -- write out the funcdata // info that we computed at the end of genssa. @@ -6453,7 +6447,7 @@ func genssa(f *ssa.Func, pp *Progs) { // some of the inline marks. // Use this instruction instead. p.Pos = p.Pos.WithIsStmt() // promote position to a statement - pp.curfn.Func().LSym.Func().AddInlMark(p, inlMarks[m]) + pp.curfn.LSym.Func().AddInlMark(p, inlMarks[m]) // Make the inline mark a real nop, so it doesn't generate any code. m.As = obj.ANOP m.Pos = src.NoXPos @@ -6465,14 +6459,14 @@ func genssa(f *ssa.Func, pp *Progs) { // Any unmatched inline marks now need to be added to the inlining tree (and will generate a nop instruction). for _, p := range inlMarkList { if p.As != obj.ANOP { - pp.curfn.Func().LSym.Func().AddInlMark(p, inlMarks[p]) + pp.curfn.LSym.Func().AddInlMark(p, inlMarks[p]) } } } if base.Ctxt.Flag_locationlists { debugInfo := ssa.BuildFuncDebug(base.Ctxt, f, base.Debug.LocationLists > 1, stackOffset) - e.curfn.Func().DebugInfo = debugInfo + e.curfn.DebugInfo = debugInfo bstart := s.bstart // Note that at this moment, Prog.Pc is a sequence number; it's // not a real PC until after assembly, so this mapping has to @@ -6486,7 +6480,7 @@ func genssa(f *ssa.Func, pp *Progs) { } return bstart[b].Pc case ssa.BlockEnd.ID: - return e.curfn.Func().LSym.Size + return e.curfn.LSym.Size default: return valueToProgAfter[v].Pc } @@ -6584,7 +6578,7 @@ func defframe(s *SSAGenState, e *ssafn) { var state uint32 // Iterate through declarations. They are sorted in decreasing Xoffset order. - for _, n := range e.curfn.Func().Dcl { + for _, n := range e.curfn.Dcl { if !n.Name().Needzero() { continue } @@ -6949,7 +6943,7 @@ func fieldIdx(n ir.Node) int { // ssafn holds frontend information about a function that the backend is processing. // It also exports a bunch of compiler services for the ssa backend. type ssafn struct { - curfn ir.Node + curfn *ir.Func strings map[string]*obj.LSym // map from constant string to data symbols scratchFpMem ir.Node // temp for floating point register / memory moves on some architectures stksize int64 // stack size for current frame @@ -7072,8 +7066,8 @@ func (e *ssafn) SplitSlot(parent *ssa.LocalSlot, suffix string, offset int64, t n.SetType(t) n.SetClass(ir.PAUTO) n.SetEsc(EscNever) - n.Name().Curfn = e.curfn - e.curfn.Func().Dcl = append(e.curfn.Func().Dcl, n) + n.Curfn = e.curfn + e.curfn.Dcl = append(e.curfn.Dcl, n) dowidth(t) return ssa.LocalSlot{N: n, Type: t, Off: 0, SplitOf: parent, SplitOffset: offset} } @@ -7136,7 +7130,7 @@ func (e *ssafn) Syslook(name string) *obj.LSym { } func (e *ssafn) SetWBPos(pos src.XPos) { - e.curfn.Func().SetWBPos(pos) + e.curfn.SetWBPos(pos) } func (e *ssafn) MyImportPath() string { diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 28703205d6..336465db98 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -95,8 +95,8 @@ func autolabel(prefix string) *types.Sym { if Curfn == nil { base.Fatalf("autolabel outside function") } - n := fn.Func().Label - fn.Func().Label++ + n := fn.Label + fn.Label++ return lookupN(prefix, int(n)) } @@ -138,7 +138,7 @@ func importdot(opkg *types.Pkg, pack *ir.PkgName) { // newname returns a new ONAME Node associated with symbol s. func NewName(s *types.Sym) *ir.Name { n := ir.NewNameAt(base.Pos, s) - n.Name().Curfn = Curfn + n.Curfn = Curfn return n } @@ -1165,7 +1165,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { tfn.PtrRlist().Set(structargs(method.Type.Results(), false)) fn := dclfunc(newnam, tfn) - fn.Func().SetDupok(true) + fn.SetDupok(true) nthis := ir.AsNode(tfn.Type().Recv().Nname) @@ -1201,7 +1201,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { fn.PtrBody().Append(as) fn.PtrBody().Append(nodSym(ir.ORETJMP, nil, methodSym(methodrcvr, method.Sym))) } else { - fn.Func().SetWrapper(true) // ignore frame for panic+recover matching + fn.SetWrapper(true) // ignore frame for panic+recover matching call := ir.Nod(ir.OCALL, dot, nil) call.PtrList().Set(paramNnames(tfn.Type())) call.SetIsDDD(tfn.Type().IsVariadic()) @@ -1222,8 +1222,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { testdclstack() } - fn = typecheck(fn, ctxStmt) - + typecheckFunc(fn) Curfn = fn typecheckslice(fn.Body().Slice(), ctxStmt) @@ -1233,7 +1232,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym != nil { inlcalls(fn) } - escapeFuncs([]ir.Node{fn}, false) + escapeFuncs([]*ir.Func{fn}, false) Curfn = nil xtop = append(xtop, fn) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 4ab47fb406..7d19a2b58e 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -95,7 +95,7 @@ func resolve(n ir.Node) (res ir.Node) { base.Fatalf("recursive inimport") } inimport = true - expandDecl(n) + expandDecl(n.(*ir.Name)) inimport = false return n } @@ -199,6 +199,13 @@ func cycleTrace(cycle []ir.Node) string { var typecheck_tcstack []ir.Node +func typecheckFunc(fn *ir.Func) { + new := typecheck(fn, ctxStmt) + if new != fn { + base.Fatalf("typecheck changed func") + } +} + // typecheck type checks node n. // The result of typecheck MUST be assigned back to n, e.g. // n.Left = typecheck(n.Left, top) @@ -2069,7 +2076,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { case ir.ODCLFUNC: ok |= ctxStmt - typecheckfunc(n) + typecheckfunc(n.(*ir.Func)) case ir.ODCLCONST: ok |= ctxStmt @@ -3402,36 +3409,38 @@ out: } // type check function definition -func typecheckfunc(n ir.Node) { +// To be called by typecheck, not directly. +// (Call typecheckfn instead.) +func typecheckfunc(n *ir.Func) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckfunc", n)(nil) } - for _, ln := range n.Func().Dcl { + for _, ln := range n.Dcl { if ln.Op() == ir.ONAME && (ln.Class() == ir.PPARAM || ln.Class() == ir.PPARAMOUT) { ln.Name().Decldepth = 1 } } - n.Func().Nname = typecheck(n.Func().Nname, ctxExpr|ctxAssign) - t := n.Func().Nname.Type() + n.Nname = typecheck(n.Nname, ctxExpr|ctxAssign).(*ir.Name) + t := n.Nname.Type() if t == nil { return } n.SetType(t) rcvr := t.Recv() - if rcvr != nil && n.Func().Shortname != nil { - m := addmethod(n, n.Func().Shortname, t, true, n.Func().Pragma&ir.Nointerface != 0) + if rcvr != nil && n.Shortname != nil { + m := addmethod(n, n.Shortname, t, true, n.Pragma&ir.Nointerface != 0) if m == nil { return } - n.Func().Nname.SetSym(methodSym(rcvr.Type, n.Func().Shortname)) - declare(n.Func().Nname, ir.PFUNC) + n.Nname.SetSym(methodSym(rcvr.Type, n.Shortname)) + declare(n.Nname, ir.PFUNC) } - if base.Ctxt.Flag_dynlink && !inimport && n.Func().Nname != nil { - makefuncsym(n.Func().Nname.Sym()) + if base.Ctxt.Flag_dynlink && !inimport && n.Nname != nil { + makefuncsym(n.Sym()) } } @@ -3861,22 +3870,19 @@ func isTermNode(n ir.Node) bool { } // checkreturn makes sure that fn terminates appropriately. -func checkreturn(fn ir.Node) { +func checkreturn(fn *ir.Func) { if fn.Type().NumResults() != 0 && fn.Body().Len() != 0 { var labels map[*types.Sym]ir.Node markbreaklist(&labels, fn.Body(), nil) if !isTermNodes(fn.Body()) { - base.ErrorfAt(fn.Func().Endlineno, "missing return at end of function") + base.ErrorfAt(fn.Endlineno, "missing return at end of function") } } } -func deadcode(fn ir.Node) { +func deadcode(fn *ir.Func) { deadcodeslice(fn.PtrBody()) - deadcodefn(fn) -} -func deadcodefn(fn ir.Node) { if fn.Body().Len() == 0 { return } @@ -4014,21 +4020,15 @@ func curpkg() *types.Pkg { // Initialization expressions for package-scope variables. return ir.LocalPkg } - - // TODO(mdempsky): Standardize on either ODCLFUNC or ONAME for - // Curfn, rather than mixing them. - if fn.Op() == ir.ODCLFUNC { - fn = fn.Func().Nname - } - - return fnpkg(fn) + return fnpkg(fn.Nname) } // MethodName returns the ONAME representing the method // referenced by expression n, which must be a method selector, // method expression, or method value. -func methodExprName(n ir.Node) ir.Node { - return ir.AsNode(methodExprFunc(n).Nname) +func methodExprName(n ir.Node) *ir.Name { + name, _ := ir.AsNode(methodExprFunc(n).Nname).(*ir.Name) + return name } // MethodFunc is like MethodName, but returns the types.Field instead. diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index c05aa0c372..d749dff827 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -22,33 +22,33 @@ import ( const tmpstringbufsize = 32 const zeroValSize = 1024 // must match value of runtime/map.go:maxZero -func walk(fn ir.Node) { +func walk(fn *ir.Func) { Curfn = fn errorsBefore := base.Errors() if base.Flag.W != 0 { - s := fmt.Sprintf("\nbefore walk %v", Curfn.Func().Nname.Sym()) + s := fmt.Sprintf("\nbefore walk %v", Curfn.Sym()) ir.DumpList(s, Curfn.Body()) } lno := base.Pos // Final typecheck for any unused variables. - for i, ln := range fn.Func().Dcl { + for i, ln := range fn.Dcl { if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) { - ln = typecheck(ln, ctxExpr|ctxAssign) - fn.Func().Dcl[i] = ln + ln = typecheck(ln, ctxExpr|ctxAssign).(*ir.Name) + fn.Dcl[i] = ln } } // Propagate the used flag for typeswitch variables up to the NONAME in its definition. - for _, ln := range fn.Func().Dcl { + for _, ln := range fn.Dcl { if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) && ln.Name().Defn != nil && ln.Name().Defn.Op() == ir.OTYPESW && ln.Name().Used() { ln.Name().Defn.Left().Name().SetUsed(true) } } - for _, ln := range fn.Func().Dcl { + for _, ln := range fn.Dcl { if ln.Op() != ir.ONAME || (ln.Class() != ir.PAUTO && ln.Class() != ir.PAUTOHEAP) || ln.Sym().Name[0] == '&' || ln.Name().Used() { continue } @@ -69,15 +69,15 @@ func walk(fn ir.Node) { } walkstmtlist(Curfn.Body().Slice()) if base.Flag.W != 0 { - s := fmt.Sprintf("after walk %v", Curfn.Func().Nname.Sym()) + s := fmt.Sprintf("after walk %v", Curfn.Sym()) ir.DumpList(s, Curfn.Body()) } zeroResults() heapmoves() - if base.Flag.W != 0 && Curfn.Func().Enter.Len() > 0 { - s := fmt.Sprintf("enter %v", Curfn.Func().Nname.Sym()) - ir.DumpList(s, Curfn.Func().Enter) + if base.Flag.W != 0 && Curfn.Enter.Len() > 0 { + s := fmt.Sprintf("enter %v", Curfn.Sym()) + ir.DumpList(s, Curfn.Enter) } } @@ -87,8 +87,8 @@ func walkstmtlist(s []ir.Node) { } } -func paramoutheap(fn ir.Node) bool { - for _, ln := range fn.Func().Dcl { +func paramoutheap(fn *ir.Func) bool { + for _, ln := range fn.Dcl { switch ln.Class() { case ir.PPARAMOUT: if isParamStackCopy(ln) || ln.Name().Addrtaken() { @@ -209,18 +209,18 @@ func walkstmt(n ir.Node) ir.Node { base.Errorf("case statement out of place") case ir.ODEFER: - Curfn.Func().SetHasDefer(true) - Curfn.Func().NumDefers++ - if Curfn.Func().NumDefers > maxOpenDefers { + Curfn.SetHasDefer(true) + Curfn.NumDefers++ + if Curfn.NumDefers > maxOpenDefers { // Don't allow open-coded defers if there are more than // 8 defers in the function, since we use a single // byte to record active defers. - Curfn.Func().SetOpenCodedDeferDisallowed(true) + Curfn.SetOpenCodedDeferDisallowed(true) } if n.Esc() != EscNever { // If n.Esc is not EscNever, then this defer occurs in a loop, // so open-coded defers cannot be used in this function. - Curfn.Func().SetOpenCodedDeferDisallowed(true) + Curfn.SetOpenCodedDeferDisallowed(true) } fallthrough case ir.OGO: @@ -270,7 +270,7 @@ func walkstmt(n ir.Node) ir.Node { walkstmtlist(n.Rlist().Slice()) case ir.ORETURN: - Curfn.Func().NumReturns++ + Curfn.NumReturns++ if n.List().Len() == 0 { break } @@ -279,12 +279,13 @@ func walkstmt(n ir.Node) ir.Node { // so that reorder3 can fix up conflicts var rl []ir.Node - for _, ln := range Curfn.Func().Dcl { + for _, ln := range Curfn.Dcl { cl := ln.Class() if cl == ir.PAUTO || cl == ir.PAUTOHEAP { break } if cl == ir.PPARAMOUT { + var ln ir.Node = ln if isParamStackCopy(ln) { ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name().Heapaddr, nil), ctxExpr), nil) } @@ -800,8 +801,8 @@ opswitch: fromType := n.Left().Type() toType := n.Type() - if !fromType.IsInterface() && !ir.IsBlank(Curfn.Func().Nname) { // skip unnamed functions (func _()) - markTypeUsedInInterface(fromType, Curfn.Func().LSym) + if !fromType.IsInterface() && !ir.IsBlank(Curfn.Nname) { // skip unnamed functions (func _()) + markTypeUsedInInterface(fromType, Curfn.LSym) } // typeword generates the type word of the interface value. @@ -1625,7 +1626,7 @@ func markTypeUsedInInterface(t *types.Type, from *obj.LSym) { func markUsedIfaceMethod(n ir.Node) { ityp := n.Left().Left().Type() tsym := typenamesym(ityp).Linksym() - r := obj.Addrel(Curfn.Func().LSym) + r := obj.Addrel(Curfn.LSym) r.Sym = tsym // n.Left.Xoffset is the method index * Widthptr (the offset of code pointer // in itab). @@ -2448,7 +2449,7 @@ func zeroResults() { v = v.Name().Stackcopy } // Zero the stack location containing f. - Curfn.Func().Enter.Append(ir.NodAt(Curfn.Pos(), ir.OAS, v, nil)) + Curfn.Enter.Append(ir.NodAt(Curfn.Pos(), ir.OAS, v, nil)) } } @@ -2478,9 +2479,9 @@ func heapmoves() { nn := paramstoheap(Curfn.Type().Recvs()) nn = append(nn, paramstoheap(Curfn.Type().Params())...) nn = append(nn, paramstoheap(Curfn.Type().Results())...) - Curfn.Func().Enter.Append(nn...) - base.Pos = Curfn.Func().Endlineno - Curfn.Func().Exit.Append(returnsfromheap(Curfn.Type().Results())...) + Curfn.Enter.Append(nn...) + base.Pos = Curfn.Endlineno + Curfn.Exit.Append(returnsfromheap(Curfn.Type().Results())...) base.Pos = lno } @@ -2781,7 +2782,7 @@ func appendslice(n ir.Node, init *ir.Nodes) ir.Node { nptr2 := l2 - Curfn.Func().SetWBPos(n.Pos()) + Curfn.SetWBPos(n.Pos()) // instantiate typedslicecopy(typ *type, dstPtr *any, dstLen int, srcPtr *any, srcLen int) int fn := syslook("typedslicecopy") @@ -2966,7 +2967,7 @@ func extendslice(n ir.Node, init *ir.Nodes) ir.Node { hasPointers := elemtype.HasPointers() if hasPointers { clrname = "memclrHasPointers" - Curfn.Func().SetWBPos(n.Pos()) + Curfn.SetWBPos(n.Pos()) } var clr ir.Nodes @@ -3100,7 +3101,7 @@ func walkappend(n ir.Node, init *ir.Nodes, dst ir.Node) ir.Node { // func copyany(n ir.Node, init *ir.Nodes, runtimecall bool) ir.Node { if n.Left().Type().Elem().HasPointers() { - Curfn.Func().SetWBPos(n.Pos()) + Curfn.SetWBPos(n.Pos()) fn := writebarrierfn("typedslicecopy", n.Left().Type().Elem(), n.Right().Type().Elem()) n.SetLeft(cheapexpr(n.Left(), init)) ptrL, lenL := backingArrayPtrLen(n.Left()) @@ -3714,9 +3715,9 @@ func usemethod(n ir.Node) { // (including global variables such as numImports - was issue #19028). // Also need to check for reflect package itself (see Issue #38515). if s := res0.Type.Sym; s != nil && s.Name == "Method" && isReflectPkg(s.Pkg) { - Curfn.Func().SetReflectMethod(true) + Curfn.SetReflectMethod(true) // The LSym is initialized at this point. We need to set the attribute on the LSym. - Curfn.Func().LSym.Set(obj.AttrReflectMethod, true) + Curfn.LSym.Set(obj.AttrReflectMethod, true) } } @@ -3765,10 +3766,10 @@ func usefield(n ir.Node) { } sym := tracksym(outer, field) - if Curfn.Func().FieldTrack == nil { - Curfn.Func().FieldTrack = make(map[*types.Sym]struct{}) + if Curfn.FieldTrack == nil { + Curfn.FieldTrack = make(map[*types.Sym]struct{}) } - Curfn.Func().FieldTrack[sym] = struct{}{} + Curfn.FieldTrack[sym] = struct{}{} } func candiscardlist(l ir.Nodes) bool { @@ -3948,12 +3949,12 @@ func wrapCall(n ir.Node, init *ir.Nodes) ir.Node { funcbody() - fn = typecheck(fn, ctxStmt) + typecheckFunc(fn) typecheckslice(fn.Body().Slice(), ctxStmt) xtop = append(xtop, fn) call = ir.Nod(ir.OCALL, nil, nil) - call.SetLeft(fn.Func().Nname) + call.SetLeft(fn.Nname) call.PtrList().Set(n.List().Slice()) call = typecheck(call, ctxStmt) call = walkexpr(call, init) @@ -4091,6 +4092,6 @@ func walkCheckPtrArithmetic(n ir.Node, init *ir.Nodes) ir.Node { // checkPtr reports whether pointer checking should be enabled for // function fn at a given level. See debugHelpFooter for defined // levels. -func checkPtr(fn ir.Node, level int) bool { - return base.Debug.Checkptr >= level && fn.Func().Pragma&ir.NoCheckPtr == 0 +func checkPtr(fn *ir.Func, level int) bool { + return base.Debug.Checkptr >= level && fn.Pragma&ir.NoCheckPtr == 0 } diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 3822c4c73b..a3999b6da0 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1338,7 +1338,7 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { mode.Fprintf(s, "%v { %v }", n.Type(), n.Body()) return } - mode.Fprintf(s, "%v { %v }", n.Type(), n.Func().Decl.Body()) + mode.Fprintf(s, "%v { %v }", n.Type(), n.Func().Body()) case OCOMPLIT: if mode == FErr { @@ -1638,7 +1638,7 @@ func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { } } - if n.Op() == OCLOSURE && n.Func().Decl != nil && n.Func().Nname.Sym() != nil { + if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Nname.Sym() != nil { mode.Fprintf(s, " fnName %v", n.Func().Nname.Sym()) } if n.Sym() != nil && n.Op() != ONAME { @@ -1656,15 +1656,15 @@ func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { if n.Right() != nil { mode.Fprintf(s, "%v", n.Right()) } - if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Decl != nil && n.Func().Decl.Body().Len() != 0 { + if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Body().Len() != 0 { indent(s) // The function associated with a closure - mode.Fprintf(s, "%v-clofunc%v", n.Op(), n.Func().Decl) + mode.Fprintf(s, "%v-clofunc%v", n.Op(), n.Func()) } if n.Op() == ODCLFUNC && n.Func() != nil && n.Func().Dcl != nil && len(n.Func().Dcl) != 0 { indent(s) // The dcls for a func or closure - mode.Fprintf(s, "%v-dcl%v", n.Op(), AsNodes(n.Func().Dcl)) + mode.Fprintf(s, "%v-dcl%v", n.Op(), asNameNodes(n.Func().Dcl)) } if n.List().Len() != 0 { indent(s) @@ -1683,6 +1683,16 @@ func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { } } +// asNameNodes copies list to a new Nodes. +// It should only be called in debug formatting and other low-performance contexts. +func asNameNodes(list []*Name) Nodes { + var ns Nodes + for _, n := range list { + ns.Append(n) + } + return ns +} + // "%S" suppresses qualifying with package func symFormat(s *types.Sym, f fmt.State, verb rune, mode FmtMode) { switch verb { diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 57ec0707e9..92a24c8385 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -53,9 +53,8 @@ type Func struct { body Nodes iota int64 - Nname Node // ONAME node - Decl Node // ODCLFUNC node - OClosure Node // OCLOSURE node + Nname *Name // ONAME node + OClosure Node // OCLOSURE node Shortname *types.Sym @@ -65,12 +64,11 @@ type Func struct { Exit Nodes // ONAME nodes for all params/locals for this func/closure, does NOT // include closurevars until transformclosure runs. - Dcl []Node + Dcl []*Name - ClosureEnter Nodes // list of ONAME nodes of captured variables - ClosureType Node // closure representation type - ClosureCalled bool // closure is only immediately called - ClosureVars Nodes // closure params; each has closurevar set + ClosureEnter Nodes // list of ONAME nodes (or OADDR-of-ONAME nodes, for output parameters) of captured variables + ClosureType Node // closure representation type + ClosureVars []*Name // closure params; each has closurevar set // Parents records the parent scope of each scope within a // function. The root scope (0) has no parent, so the i'th @@ -80,17 +78,17 @@ type Func struct { // Marks records scope boundary changes. Marks []Mark - // Closgen tracks how many closures have been generated within - // this function. Used by closurename for creating unique - // function names. - Closgen int - FieldTrack map[*types.Sym]struct{} DebugInfo interface{} LSym *obj.LSym Inl *Inline + // Closgen tracks how many closures have been generated within + // this function. Used by closurename for creating unique + // function names. + Closgen int32 + Label int32 // largest auto-generated label in this function Endlineno src.XPos @@ -99,8 +97,8 @@ type Func struct { Pragma PragmaFlag // go:xxx function annotations flags bitset16 - NumDefers int // number of defer calls in the function - NumReturns int // number of explicit returns in the function + NumDefers int32 // number of defer calls in the function + NumReturns int32 // number of explicit returns in the function // nwbrCalls records the LSyms of functions called by this // function for go:nowritebarrierrec analysis. Only filled in @@ -112,7 +110,6 @@ func NewFunc(pos src.XPos) *Func { f := new(Func) f.pos = pos f.op = ODCLFUNC - f.Decl = f f.iota = -1 return f } @@ -141,7 +138,7 @@ type Inline struct { Cost int32 // heuristic cost of inlining this function // Copies of Func.Dcl and Nbody for use during inlining. - Dcl []Node + Dcl []*Name Body []Node } @@ -172,6 +169,7 @@ const ( funcExportInline // include inline body in export data funcInstrumentBody // add race/msan instrumentation during SSA construction funcOpenCodedDeferDisallowed // can't do open-coded defers + funcClosureCalled // closure is only immediately called ) type SymAndPos struct { @@ -190,6 +188,7 @@ func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinability func (f *Func) ExportInline() bool { return f.flags&funcExportInline != 0 } func (f *Func) InstrumentBody() bool { return f.flags&funcInstrumentBody != 0 } func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 } +func (f *Func) ClosureCalled() bool { return f.flags&funcClosureCalled != 0 } func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) } func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) } @@ -202,6 +201,7 @@ func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilit func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInline, b) } func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) } func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) } +func (f *Func) SetClosureCalled(b bool) { f.flags.set(funcClosureCalled, b) } func (f *Func) SetWBPos(pos src.XPos) { if base.Debug.WB != 0 { diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index d330745cfb..5546488fa7 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -32,9 +32,10 @@ type Name struct { // For a local variable (not param) or extern, the initializing assignment (OAS or OAS2). // For a closure var, the ONAME node of the outer captured variable Defn Node - // The ODCLFUNC node (for a static function/method or a closure) in which - // local variable or param is declared. - Curfn Node + + // The function, method, or closure in which local variable or param is declared. + Curfn *Func + // Unique number for ONAME nodes within a function. Function outputs // (results) are numbered starting at one, followed by function inputs // (parameters), and then local variables. Vargen is used to distinguish diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go index 8597ad492a..9321f765e0 100644 --- a/src/cmd/compile/internal/ir/sizeof_test.go +++ b/src/cmd/compile/internal/ir/sizeof_test.go @@ -20,8 +20,8 @@ func TestSizeof(t *testing.T) { _32bit uintptr // size on 32bit platforms _64bit uintptr // size on 64bit platforms }{ - {Func{}, 180, 320}, - {Name{}, 132, 232}, + {Func{}, 172, 296}, + {Name{}, 128, 224}, {node{}, 84, 144}, } From 4eaef981b5b5bac873256d63ffecaaa73fb5f28b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 26 Nov 2020 00:47:44 -0500 Subject: [PATCH 025/212] [dev.regabi] cmd/compile: add ir.Closure, ir.ClosureRead Closures are another reference to Funcs, and it cleans up the code quite a bit to be clear about types. OCLOSUREVAR is renamed to OCLOSUREREAD to make clearer that it is unrelated to the list Func.ClosureVars. Passes buildall w/ toolstash -cmp. Change-Id: Id0d28df2d4d6e9954e34df7a39ea226995eee937 Reviewed-on: https://go-review.googlesource.com/c/go/+/274098 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/closure.go | 32 ++++++++---------- src/cmd/compile/internal/gc/escape.go | 4 +-- src/cmd/compile/internal/gc/inl.go | 4 +-- src/cmd/compile/internal/gc/ssa.go | 4 +-- src/cmd/compile/internal/gc/typecheck.go | 6 ++-- src/cmd/compile/internal/gc/walk.go | 2 +- src/cmd/compile/internal/ir/expr.go | 39 ++++++++++++++++++++++ src/cmd/compile/internal/ir/func.go | 4 +-- src/cmd/compile/internal/ir/node.go | 30 ++++++++--------- src/cmd/compile/internal/ir/op_string.go | 6 ++-- src/cmd/compile/internal/ir/sizeof_test.go | 2 +- 11 files changed, 82 insertions(+), 51 deletions(-) diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 0cf59ee0eb..e8a0617be3 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -23,8 +23,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { fn.Nname.Ntype = xtype fn.Nname.Defn = fn - clo := p.nod(expr, ir.OCLOSURE, nil, nil) - clo.SetFunc(fn) + clo := ir.NewClosureExpr(p.pos(expr), fn) fn.ClosureType = ntype fn.OClosure = clo @@ -285,21 +284,19 @@ func transformclosure(fn *ir.Func) { offset := int64(Widthptr) for _, v := range fn.ClosureVars { // cv refers to the field inside of closure OSTRUCTLIT. - cv := ir.Nod(ir.OCLOSUREVAR, nil, nil) - - cv.SetType(v.Type()) + typ := v.Type() if !v.Byval() { - cv.SetType(types.NewPtr(v.Type())) + typ = types.NewPtr(typ) } - offset = Rnd(offset, int64(cv.Type().Align)) - cv.SetOffset(offset) - offset += cv.Type().Width + offset = Rnd(offset, int64(typ.Align)) + cr := ir.NewClosureRead(typ, offset) + offset += typ.Width if v.Byval() && v.Type().Width <= int64(2*Widthptr) { // If it is a small variable captured by value, downgrade it to PAUTO. v.SetClass(ir.PAUTO) fn.Dcl = append(fn.Dcl, v) - body = append(body, ir.Nod(ir.OAS, v, cv)) + body = append(body, ir.Nod(ir.OAS, v, cr)) } else { // Declare variable holding addresses taken from closure // and initialize in entry prologue. @@ -310,10 +307,11 @@ func transformclosure(fn *ir.Func) { addr.Curfn = fn fn.Dcl = append(fn.Dcl, addr) v.Heapaddr = addr + var src ir.Node = cr if v.Byval() { - cv = ir.Nod(ir.OADDR, cv, nil) + src = ir.Nod(ir.OADDR, cr, nil) } - body = append(body, ir.Nod(ir.OAS, addr, cv)) + body = append(body, ir.Nod(ir.OAS, addr, src)) } } @@ -473,21 +471,17 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) *ir.Func { tfn.Type().SetPkg(t0.Pkg()) // Declare and initialize variable holding receiver. - - cv := ir.Nod(ir.OCLOSUREVAR, nil, nil) - cv.SetType(rcvrtype) - cv.SetOffset(Rnd(int64(Widthptr), int64(cv.Type().Align))) - + cr := ir.NewClosureRead(rcvrtype, Rnd(int64(Widthptr), int64(rcvrtype.Align))) ptr := NewName(lookup(".this")) declare(ptr, ir.PAUTO) ptr.SetUsed(true) var body []ir.Node if rcvrtype.IsPtr() || rcvrtype.IsInterface() { ptr.SetType(rcvrtype) - body = append(body, ir.Nod(ir.OAS, ptr, cv)) + body = append(body, ir.Nod(ir.OAS, ptr, cr)) } else { ptr.SetType(types.NewPtr(rcvrtype)) - body = append(body, ir.Nod(ir.OAS, ptr, ir.Nod(ir.OADDR, cv, nil))) + body = append(body, ir.Nod(ir.OAS, ptr, ir.Nod(ir.OADDR, cr, nil))) } call := ir.Nod(ir.OCALL, nodSym(ir.OXDOT, ptr, meth), nil) diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 4bddb7f0f4..4cbc5d3851 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -486,7 +486,7 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) { default: base.Fatalf("unexpected expr: %v", n) - case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OCLOSUREVAR, ir.OTYPE, ir.OMETHEXPR: + case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OCLOSUREREAD, ir.OTYPE, ir.OMETHEXPR: // nop case ir.ONAME: @@ -1718,7 +1718,7 @@ func mayAffectMemory(n ir.Node) bool { // We're ignoring things like division by zero, index out of range, // and nil pointer dereference here. switch n.Op() { - case ir.ONAME, ir.OCLOSUREVAR, ir.OLITERAL, ir.ONIL: + case ir.ONAME, ir.OCLOSUREREAD, ir.OLITERAL, ir.ONIL: return false // Left+Right group. diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 20f145b8eb..97f37a4716 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -963,7 +963,7 @@ func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool) // Handle captured variables when inlining closures. if c := fn.OClosure; c != nil { - for _, v := range c.Func().ClosureVars { + for _, v := range fn.ClosureVars { if v.Op() == ir.OXXX { continue } @@ -973,7 +973,7 @@ func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool) // NB: if we enabled inlining of functions containing OCLOSURE or refined // the reassigned check via some sort of copy propagation this would most // likely need to be changed to a loop to walk up to the correct Param - if o == nil || (o.Curfn != Curfn && o.Curfn.OClosure != Curfn) { + if o == nil || o.Curfn != Curfn { base.Fatalf("%v: unresolvable capture %v %v\n", ir.Line(n), fn, v) } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 91faf18a1d..10df6d5411 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -2025,7 +2025,7 @@ func (s *state) expr(n ir.Node) *ssa.Value { } addr := s.addr(n) return s.load(n.Type(), addr) - case ir.OCLOSUREVAR: + case ir.OCLOSUREREAD: addr := s.addr(n) return s.load(n.Type(), addr) case ir.ONIL: @@ -4895,7 +4895,7 @@ func (s *state) addr(n ir.Node) *ssa.Value { case ir.ODOTPTR: p := s.exprPtr(n.Left(), n.Bounded(), n.Pos()) return s.newValue1I(ssa.OpOffPtr, t, n.Offset(), p) - case ir.OCLOSUREVAR: + case ir.OCLOSUREREAD: return s.newValue1I(ssa.OpOffPtr, t, n.Offset(), s.entryNewValue0(ssa.OpGetClosurePtr, s.f.Config.Types.BytePtr)) case ir.OCONVNOP: diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 7d19a2b58e..8c2df77ffe 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1948,7 +1948,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(types.NewPtr(t.Elem())) } - case ir.OCLOSUREVAR: + case ir.OCLOSUREREAD: ok |= ctxExpr case ir.OCFUNC: @@ -3099,7 +3099,7 @@ func islvalue(n ir.Node) bool { return false } fallthrough - case ir.ODEREF, ir.ODOTPTR, ir.OCLOSUREVAR: + case ir.ODEREF, ir.ODOTPTR, ir.OCLOSUREREAD: return true case ir.ODOT: @@ -3186,7 +3186,7 @@ func samesafeexpr(l ir.Node, r ir.Node) bool { } switch l.Op() { - case ir.ONAME, ir.OCLOSUREVAR: + case ir.ONAME, ir.OCLOSUREREAD: return l == r case ir.ODOT, ir.ODOTPTR: diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index d749dff827..e0e715716b 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -555,7 +555,7 @@ opswitch: case ir.ORECOVER: n = mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil)) - case ir.OCLOSUREVAR, ir.OCFUNC: + case ir.OCLOSUREREAD, ir.OCFUNC: case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH: if n.Op() == ir.OCALLINTER { diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 418351742e..13774a2c7b 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -6,6 +6,8 @@ package ir import ( "cmd/compile/internal/types" + "cmd/internal/src" + "fmt" ) // A miniStmt is a miniNode with extra fields common to expressions. @@ -45,3 +47,40 @@ func (n *miniExpr) SetBounded(b bool) { n.flags.set(miniExprBounded, b) } func (n *miniExpr) Init() Nodes { return n.init } func (n *miniExpr) PtrInit() *Nodes { return &n.init } func (n *miniExpr) SetInit(x Nodes) { n.init = x } + +// A ClosureExpr is a function literal expression. +type ClosureExpr struct { + miniExpr + fn *Func +} + +func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr { + n := &ClosureExpr{fn: fn} + n.op = OCLOSURE + n.pos = pos + return n +} + +func (n *ClosureExpr) String() string { return fmt.Sprint(n) } +func (n *ClosureExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ClosureExpr) RawCopy() Node { c := *n; return &c } +func (n *ClosureExpr) Func() *Func { return n.fn } + +// A ClosureRead denotes reading a variable stored within a closure struct. +type ClosureRead struct { + miniExpr + offset int64 +} + +func NewClosureRead(typ *types.Type, offset int64) *ClosureRead { + n := &ClosureRead{offset: offset} + n.typ = typ + n.op = OCLOSUREREAD + return n +} + +func (n *ClosureRead) String() string { return fmt.Sprint(n) } +func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ClosureRead) RawCopy() Node { c := *n; return &c } +func (n *ClosureRead) Type() *types.Type { return n.typ } +func (n *ClosureRead) Offset() int64 { return n.offset } diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 92a24c8385..9d2a8ad94b 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -53,8 +53,8 @@ type Func struct { body Nodes iota int64 - Nname *Name // ONAME node - OClosure Node // OCLOSURE node + Nname *Name // ONAME node + OClosure *ClosureExpr // OCLOSURE node Shortname *types.Sym diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 02a5d7769a..8e10569f6a 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -601,20 +601,20 @@ const ( OTARRAY // []int, [8]int, [N]int or [...]int // misc - ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}. - OINLCALL // intermediary representation of an inlined call. - OEFACE // itable and data words of an empty-interface value. - OITAB // itable word of an interface value. - OIDATA // data word of an interface value in Left - OSPTR // base pointer of a slice or string. - OCLOSUREVAR // variable reference at beginning of closure function - OCFUNC // reference to c function pointer (not go func value) - OCHECKNIL // emit code to ensure pointer/interface not nil - OVARDEF // variable is about to be fully initialized - OVARKILL // variable is dead - OVARLIVE // variable is alive - ORESULT // result of a function call; Xoffset is stack offset - OINLMARK // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree. + ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}. + OINLCALL // intermediary representation of an inlined call. + OEFACE // itable and data words of an empty-interface value. + OITAB // itable word of an interface value. + OIDATA // data word of an interface value in Left + OSPTR // base pointer of a slice or string. + OCLOSUREREAD // read from inside closure struct at beginning of closure function + OCFUNC // reference to c function pointer (not go func value) + OCHECKNIL // emit code to ensure pointer/interface not nil + OVARDEF // variable is about to be fully initialized + OVARKILL // variable is dead + OVARLIVE // variable is alive + ORESULT // result of a function call; Xoffset is stack offset + OINLMARK // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree. // arch-specific opcodes ORETJMP // return to other function @@ -1162,8 +1162,6 @@ var okForNod = [OEND]bool{ OCFUNC: true, OCHECKNIL: true, OCLOSE: true, - OCLOSURE: true, - OCLOSUREVAR: true, OCOMPLEX: true, OCOMPLIT: true, OCONV: true, diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index d0d3778357..637c924dd5 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -152,7 +152,7 @@ func _() { _ = x[OITAB-141] _ = x[OIDATA-142] _ = x[OSPTR-143] - _ = x[OCLOSUREVAR-144] + _ = x[OCLOSUREREAD-144] _ = x[OCFUNC-145] _ = x[OCHECKNIL-146] _ = x[OVARDEF-147] @@ -165,9 +165,9 @@ func _() { _ = x[OEND-154] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREREADCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 310, 317, 323, 326, 332, 339, 347, 351, 358, 366, 368, 370, 372, 374, 376, 378, 383, 388, 396, 399, 408, 411, 415, 423, 430, 439, 452, 455, 458, 461, 464, 467, 470, 476, 479, 485, 488, 494, 498, 501, 505, 510, 515, 521, 526, 530, 535, 543, 551, 557, 566, 577, 584, 588, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 658, 663, 668, 672, 680, 685, 690, 694, 697, 705, 709, 711, 716, 718, 723, 729, 735, 741, 747, 752, 756, 763, 769, 774, 780, 783, 790, 795, 799, 804, 808, 818, 823, 831, 837, 844, 851, 857, 864, 870, 874, 877} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 310, 317, 323, 326, 332, 339, 347, 351, 358, 366, 368, 370, 372, 374, 376, 378, 383, 388, 396, 399, 408, 411, 415, 423, 430, 439, 452, 455, 458, 461, 464, 467, 470, 476, 479, 485, 488, 494, 498, 501, 505, 510, 515, 521, 526, 530, 535, 543, 551, 557, 566, 577, 584, 588, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 658, 663, 668, 672, 680, 685, 690, 694, 697, 705, 709, 711, 716, 718, 723, 729, 735, 741, 747, 752, 756, 763, 769, 774, 780, 783, 790, 795, 799, 804, 808, 819, 824, 832, 838, 845, 852, 858, 865, 871, 875, 878} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go index 9321f765e0..0859022a62 100644 --- a/src/cmd/compile/internal/ir/sizeof_test.go +++ b/src/cmd/compile/internal/ir/sizeof_test.go @@ -20,7 +20,7 @@ func TestSizeof(t *testing.T) { _32bit uintptr // size on 32bit platforms _64bit uintptr // size on 64bit platforms }{ - {Func{}, 172, 296}, + {Func{}, 168, 288}, {Name{}, 128, 224}, {node{}, 84, 144}, } From e5c6463e205e0dfe5df8af59c76fd1ee94feddd4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 26 Nov 2020 01:05:39 -0500 Subject: [PATCH 026/212] [dev.regabi] cmd/compile: add ir.CallPartExpr Now there are no longer any generic nodes with a non-nil associated Func, so node.fn can be deleted. Also all manipulation of func fields is done with concrete types, so Node.SetFunc can be deleted, along with generic implementations. Passes buildall w/ toolstash -cmp. Change-Id: I4fee99870951ec9dc224f146d87b22e2bfe16889 Reviewed-on: https://go-review.googlesource.com/c/go/+/274099 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/closure.go | 10 +++------ src/cmd/compile/internal/gc/dcl.go | 2 +- src/cmd/compile/internal/gc/ssa.go | 8 +++++-- src/cmd/compile/internal/gc/typecheck.go | 2 +- src/cmd/compile/internal/gc/walk.go | 2 +- src/cmd/compile/internal/ir/expr.go | 26 ++++++++++++++++++++++ src/cmd/compile/internal/ir/mini.go | 1 - src/cmd/compile/internal/ir/node.go | 8 +------ src/cmd/compile/internal/ir/sizeof_test.go | 2 +- 9 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index e8a0617be3..58113977d5 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -414,7 +414,7 @@ func walkclosure(clo ir.Node, init *ir.Nodes) ir.Node { return walkexpr(clos, init) } -func typecheckpartialcall(dot ir.Node, sym *types.Sym) { +func typecheckpartialcall(dot ir.Node, sym *types.Sym) *ir.CallPartExpr { switch dot.Op() { case ir.ODOTINTER, ir.ODOTMETH: break @@ -427,11 +427,7 @@ func typecheckpartialcall(dot ir.Node, sym *types.Sym) { fn := makepartialcall(dot, dot.Type(), sym) fn.SetWrapper(true) - dot.SetOp(ir.OCALLPART) - dot.SetRight(NewName(sym)) - dot.SetType(fn.Type()) - dot.SetFunc(fn) - dot.SetOpt(nil) // clear types.Field from ODOTMETH + return ir.NewCallPartExpr(dot.Pos(), dot.Left(), NewName(sym), fn) } // makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed @@ -522,7 +518,7 @@ func partialCallType(n ir.Node) *types.Type { return t } -func walkpartialcall(n ir.Node, init *ir.Nodes) ir.Node { +func walkpartialcall(n *ir.CallPartExpr, init *ir.Nodes) ir.Node { // Create closure in the form of a composite literal. // For x.M with receiver (x) type T, the generated code looks like: // diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 2bcee269d9..5d1bde384a 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -795,7 +795,7 @@ func methodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy // - msym is the method symbol // - t is function type (with receiver) // Returns a pointer to the existing or added Field; or nil if there's an error. -func addmethod(n ir.Node, msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field { +func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field { if msym == nil { base.Fatalf("no method symbol") } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 10df6d5411..6d818be132 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -4146,10 +4146,14 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder { } func isIntrinsicCall(n ir.Node) bool { - if n == nil || n.Left() == nil { + if n == nil { return false } - return findIntrinsic(n.Left().Sym()) != nil + name, ok := n.Left().(*ir.Name) + if !ok { + return false + } + return findIntrinsic(name.Sym()) != nil } // intrinsicCall converts a call to a recognized intrinsic function into the intrinsic SSA operation. diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 8c2df77ffe..0ed5009a22 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -964,7 +964,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { if top&ctxCallee != 0 { ok |= ctxCallee } else { - typecheckpartialcall(n, s) + n = typecheckpartialcall(n, s) ok |= ctxExpr } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index e0e715716b..e04413841a 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1578,7 +1578,7 @@ opswitch: n = walkclosure(n, init) case ir.OCALLPART: - n = walkpartialcall(n, init) + n = walkpartialcall(n.(*ir.CallPartExpr), init) } // Expressions that are constant at run time but not diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 13774a2c7b..2c13918599 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -84,3 +84,29 @@ func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ClosureRead) RawCopy() Node { c := *n; return &c } func (n *ClosureRead) Type() *types.Type { return n.typ } func (n *ClosureRead) Offset() int64 { return n.offset } + +// A CallPartExpr is a method expression X.Method (uncalled). +type CallPartExpr struct { + miniExpr + fn *Func + X Node + Method *Name +} + +func NewCallPartExpr(pos src.XPos, x Node, method *Name, fn *Func) *CallPartExpr { + n := &CallPartExpr{fn: fn, X: x, Method: method} + n.op = OCALLPART + n.pos = pos + n.typ = fn.Type() + n.fn = fn + return n +} + +func (n *CallPartExpr) String() string { return fmt.Sprint(n) } +func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *CallPartExpr) RawCopy() Node { c := *n; return &c } +func (n *CallPartExpr) Func() *Func { return n.fn } +func (n *CallPartExpr) Left() Node { return n.X } +func (n *CallPartExpr) Right() Node { return n.Method } +func (n *CallPartExpr) SetLeft(x Node) { n.X = x } +func (n *CallPartExpr) SetRight(x Node) { n.Method = x.(*Name) } diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index 248fe232cb..338ded3308 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -128,7 +128,6 @@ func (n *miniNode) SetSubOp(Op) { panic(n.no("SetSubOp")) } func (n *miniNode) Type() *types.Type { return nil } func (n *miniNode) SetType(*types.Type) { panic(n.no("SetType")) } func (n *miniNode) Func() *Func { return nil } -func (n *miniNode) SetFunc(*Func) { panic(n.no("SetFunc")) } func (n *miniNode) Name() *Name { return nil } func (n *miniNode) Sym() *types.Sym { return nil } func (n *miniNode) SetSym(*types.Sym) { panic(n.no("SetSym")) } diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 8e10569f6a..f09727c369 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -56,7 +56,6 @@ type Node interface { Type() *types.Type SetType(t *types.Type) Func() *Func - SetFunc(x *Func) Name() *Name Sym() *types.Sym SetSym(x *types.Sym) @@ -143,9 +142,6 @@ type node struct { typ *types.Type orig Node // original form, for printing, and tracking copies of ONAMEs - // func - fn *Func - sym *types.Sym // various opt interface{} @@ -177,8 +173,7 @@ func (n *node) Orig() Node { return n.orig } func (n *node) SetOrig(x Node) { n.orig = x } func (n *node) Type() *types.Type { return n.typ } func (n *node) SetType(x *types.Type) { n.typ = x } -func (n *node) Func() *Func { return n.fn } -func (n *node) SetFunc(x *Func) { n.fn = x } +func (n *node) Func() *Func { return nil } func (n *node) Name() *Name { return nil } func (n *node) Sym() *types.Sym { return n.sym } func (n *node) SetSym(x *types.Sym) { n.sym = x } @@ -1156,7 +1151,6 @@ var okForNod = [OEND]bool{ OCALLFUNC: true, OCALLINTER: true, OCALLMETH: true, - OCALLPART: true, OCAP: true, OCASE: true, OCFUNC: true, diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go index 0859022a62..2f31ba8d34 100644 --- a/src/cmd/compile/internal/ir/sizeof_test.go +++ b/src/cmd/compile/internal/ir/sizeof_test.go @@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) { }{ {Func{}, 168, 288}, {Name{}, 128, 224}, - {node{}, 84, 144}, + {node{}, 80, 136}, } for _, tt := range tests { From 1b84aabb01770ae65d28f951c65a9eb6c16441d7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 09:07:48 -0500 Subject: [PATCH 027/212] [dev.regabi] cmd/compile: move typenod, typenodl to ir.TypeNode, ir.TypeNodeAt [generated] [git-generate] cd src/cmd/compile/internal/gc rf ' mv typenod TypeNode mv typenodl TypeNodeAt mv TypeNode TypeNodeAt type.go mv type.go cmd/compile/internal/ir ' Passes buildall w/ toolstash -cmp. Change-Id: Id546a8cfae93074ebb1496490da7635800807faf Reviewed-on: https://go-review.googlesource.com/c/go/+/274100 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/closure.go | 4 ++-- src/cmd/compile/internal/gc/dcl.go | 17 --------------- src/cmd/compile/internal/gc/iexport.go | 2 +- src/cmd/compile/internal/gc/iimport.go | 10 ++++----- src/cmd/compile/internal/gc/inl.go | 2 +- src/cmd/compile/internal/gc/sinit.go | 4 ++-- src/cmd/compile/internal/gc/typecheck.go | 6 +++--- src/cmd/compile/internal/gc/universe.go | 12 +++++------ src/cmd/compile/internal/gc/walk.go | 4 ++-- src/cmd/compile/internal/ir/type.go | 27 ++++++++++++++++++++++++ 10 files changed, 49 insertions(+), 39 deletions(-) create mode 100644 src/cmd/compile/internal/ir/type.go diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 58113977d5..ee09e7876e 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -392,7 +392,7 @@ func walkclosure(clo ir.Node, init *ir.Nodes) ir.Node { typ := closureType(clo) - clos := ir.Nod(ir.OCOMPLIT, nil, typenod(typ)) + clos := ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(typ)) clos.SetEsc(clo.Esc()) clos.PtrList().Set(append([]ir.Node{ir.Nod(ir.OCFUNC, fn.Nname, nil)}, fn.ClosureEnter.Slice()...)) @@ -542,7 +542,7 @@ func walkpartialcall(n *ir.CallPartExpr, init *ir.Nodes) ir.Node { typ := partialCallType(n) - clos := ir.Nod(ir.OCOMPLIT, nil, typenod(typ)) + clos := ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(typ)) clos.SetEsc(n.Esc()) clos.PtrList().Set2(ir.Nod(ir.OCFUNC, n.Func().Nname, nil), n.Left()) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 5d1bde384a..3d8f97d93d 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -221,23 +221,6 @@ func dclname(s *types.Sym) *ir.Name { return n } -func typenod(t *types.Type) ir.Node { - return typenodl(src.NoXPos, t) -} - -func typenodl(pos src.XPos, t *types.Type) ir.Node { - // if we copied another type with *t = *u - // then t->nod might be out of date, so - // check t->nod->type too - if ir.AsNode(t.Nod) == nil || ir.AsNode(t.Nod).Type() != t { - t.Nod = ir.NodAt(pos, ir.OTYPE, nil, nil) - ir.AsNode(t.Nod).SetType(t) - ir.AsNode(t.Nod).SetSym(t.Sym) - } - - return ir.AsNode(t.Nod) -} - func anonfield(typ *types.Type) ir.Node { return symfield(nil, typ) } diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 3f5ec2e4dd..3f0f381974 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -640,7 +640,7 @@ func (w *exportWriter) doTyp(t *types.Type) { } w.startType(definedType) - w.qualifiedIdent(typenod(t)) + w.qualifiedIdent(ir.TypeNode(t)) return } diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 5a50682ab2..88f6e36e07 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -836,7 +836,7 @@ func (r *importReader) node() ir.Node { // unreachable - should have been resolved by typechecking case ir.OTYPE: - return typenod(r.typ()) + return ir.TypeNode(r.typ()) case ir.OTYPESW: n := ir.NodAt(r.pos(), ir.OTYPESW, nil, nil) @@ -860,7 +860,7 @@ func (r *importReader) node() ir.Node { // TODO(mdempsky): Export position information for OSTRUCTKEY nodes. savedlineno := base.Pos base.Pos = r.pos() - n := ir.NodAt(base.Pos, ir.OCOMPLIT, nil, typenod(r.typ())) + n := ir.NodAt(base.Pos, ir.OCOMPLIT, nil, ir.TypeNode(r.typ())) n.PtrList().Set(r.elemList()) // special handling of field names base.Pos = savedlineno return n @@ -869,7 +869,7 @@ func (r *importReader) node() ir.Node { // unreachable - mapped to case OCOMPLIT below by exporter case ir.OCOMPLIT: - n := ir.NodAt(r.pos(), ir.OCOMPLIT, nil, typenod(r.typ())) + n := ir.NodAt(r.pos(), ir.OCOMPLIT, nil, ir.TypeNode(r.typ())) n.PtrList().Set(r.exprList()) return n @@ -944,7 +944,7 @@ func (r *importReader) node() ir.Node { case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE: n := npos(r.pos(), builtinCall(ir.OMAKE)) - n.PtrList().Append(typenod(r.typ())) + n.PtrList().Append(ir.TypeNode(r.typ())) n.PtrList().Append(r.exprList()...) return n @@ -971,7 +971,7 @@ func (r *importReader) node() ir.Node { case ir.ODCL: pos := r.pos() lhs := npos(pos, dclname(r.ident())) - typ := typenod(r.typ()) + typ := ir.TypeNode(r.typ()) return npos(pos, liststmt(variter([]ir.Node{lhs}, typ, nil))) // TODO(gri) avoid list creation // case ODCLFIELD: diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 97f37a4716..bbbffebf5c 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -1108,7 +1108,7 @@ func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool) vas.SetRight(nodnil()) vas.Right().SetType(param.Type) } else { - vas.SetRight(ir.Nod(ir.OCOMPLIT, nil, typenod(param.Type))) + vas.SetRight(ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(param.Type))) vas.Right().PtrList().Set(varargs) } } diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index fca81763c0..ff3d3281dd 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -687,7 +687,7 @@ func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) { a = ir.Nod(ir.OADDR, a, nil) } else { a = ir.Nod(ir.ONEW, nil, nil) - a.PtrList().Set1(typenod(t)) + a.PtrList().Set1(ir.TypeNode(t)) } a = ir.Nod(ir.OAS, vauto, a) @@ -763,7 +763,7 @@ func maplit(n ir.Node, m ir.Node, init *ir.Nodes) { // make the map var a := ir.Nod(ir.OMAKE, nil, nil) a.SetEsc(n.Esc()) - a.PtrList().Set2(typenod(n.Type()), nodintconst(int64(n.List().Len()))) + a.PtrList().Set2(ir.TypeNode(n.Type()), nodintconst(int64(n.List().Len()))) litas(m, a, init) entries := n.List().Slice() diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 0ed5009a22..a1b1809790 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2785,11 +2785,11 @@ func pushtype(n ir.Node, t *types.Type) ir.Node { switch { case iscomptype(t): // For T, return T{...}. - n.SetRight(typenod(t)) + n.SetRight(ir.TypeNode(t)) case t.IsPtr() && iscomptype(t.Elem()): // For *T, return &T{...}. - n.SetRight(typenod(t.Elem())) + n.SetRight(ir.TypeNode(t.Elem())) n = ir.NodAt(n.Pos(), ir.OADDR, n, nil) n.SetImplicit(true) @@ -3458,7 +3458,7 @@ func stringtoruneslit(n ir.Node) ir.Node { i++ } - nn := ir.Nod(ir.OCOMPLIT, nil, typenod(n.Type())) + nn := ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(n.Type())) nn.PtrList().Set(l) nn = typecheck(nn, ctxExpr) return nn diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 1068720748..931135759a 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -109,7 +109,7 @@ func lexinit() { } types.Types[etype] = t } - s2.Def = typenod(t) + s2.Def = ir.TypeNode(t) } for _, s := range &builtinFuncs { @@ -176,7 +176,7 @@ func typeinit() { t := types.New(types.TUNSAFEPTR) types.Types[types.TUNSAFEPTR] = t t.Sym = unsafepkg.Lookup("Pointer") - t.Sym.Def = typenod(t) + t.Sym.Def = ir.TypeNode(t) dowidth(types.Types[types.TUNSAFEPTR]) for et := types.TINT8; et <= types.TUINT64; et++ { @@ -337,7 +337,7 @@ func lexinit1() { types.Errortype = makeErrorInterface() types.Errortype.Sym = s types.Errortype.Orig = makeErrorInterface() - s.Def = typenod(types.Errortype) + s.Def = ir.TypeNode(types.Errortype) dowidth(types.Errortype) // We create separate byte and rune types for better error messages @@ -352,14 +352,14 @@ func lexinit1() { s = ir.BuiltinPkg.Lookup("byte") types.Bytetype = types.New(types.TUINT8) types.Bytetype.Sym = s - s.Def = typenod(types.Bytetype) + s.Def = ir.TypeNode(types.Bytetype) dowidth(types.Bytetype) // rune alias s = ir.BuiltinPkg.Lookup("rune") types.Runetype = types.New(types.TINT32) types.Runetype.Sym = s - s.Def = typenod(types.Runetype) + s.Def = ir.TypeNode(types.Runetype) dowidth(types.Runetype) // backend-dependent builtin types (e.g. int). @@ -376,7 +376,7 @@ func lexinit1() { t := types.New(s.etype) t.Sym = s1 types.Types[s.etype] = t - s1.Def = typenod(t) + s1.Def = ir.TypeNode(t) s1.Origpkg = ir.BuiltinPkg dowidth(t) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index e04413841a..2376bfc093 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1810,7 +1810,7 @@ func mkdotargslice(typ *types.Type, args []ir.Node) ir.Node { n = nodnil() n.SetType(typ) } else { - n = ir.Nod(ir.OCOMPLIT, nil, typenod(typ)) + n = ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(typ)) n.PtrList().Append(args...) n.SetImplicit(true) } @@ -2687,7 +2687,7 @@ func addstr(n ir.Node, init *ir.Nodes) ir.Node { fn = "concatstrings" t := types.NewSlice(types.Types[types.TSTRING]) - slice := ir.Nod(ir.OCOMPLIT, nil, typenod(t)) + slice := ir.Nod(ir.OCOMPLIT, nil, ir.TypeNode(t)) if prealloc[n] != nil { prealloc[slice] = prealloc[n] } diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go new file mode 100644 index 0000000000..3409424fed --- /dev/null +++ b/src/cmd/compile/internal/ir/type.go @@ -0,0 +1,27 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ir + +import ( + "cmd/compile/internal/types" + "cmd/internal/src" +) + +func TypeNode(t *types.Type) Node { + return TypeNodeAt(src.NoXPos, t) +} + +func TypeNodeAt(pos src.XPos, t *types.Type) Node { + // if we copied another type with *t = *u + // then t->nod might be out of date, so + // check t->nod->type too + if AsNode(t.Nod) == nil || AsNode(t.Nod).Type() != t { + t.Nod = NodAt(pos, OTYPE, nil, nil) + AsNode(t.Nod).SetType(t) + AsNode(t.Nod).SetSym(t.Sym) + } + + return AsNode(t.Nod) +} From f0001e8867be0004a8bc13eaea8b59653a5d141e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 29 Nov 2020 08:09:01 -0500 Subject: [PATCH 028/212] [dev.regabi] cmd/compile: add OTSLICE Op This is not safe for toolstash -cmp and so is split into its own CL. Change-Id: Ic3254e68fb84a90a11ac5f0b59ef252135c23658 Reviewed-on: https://go-review.googlesource.com/c/go/+/274101 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/node.go | 1 + src/cmd/compile/internal/ir/op_string.go | 39 ++++++++++++------------ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index f09727c369..47c38c2ab5 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -594,6 +594,7 @@ const ( // list of result fields. OTFUNC OTARRAY // []int, [8]int, [N]int or [...]int + OTSLICE // to be used in future CL // misc ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}. diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index 637c924dd5..faec164c7b 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -146,28 +146,29 @@ func _() { _ = x[OTINTER-135] _ = x[OTFUNC-136] _ = x[OTARRAY-137] - _ = x[ODDD-138] - _ = x[OINLCALL-139] - _ = x[OEFACE-140] - _ = x[OITAB-141] - _ = x[OIDATA-142] - _ = x[OSPTR-143] - _ = x[OCLOSUREREAD-144] - _ = x[OCFUNC-145] - _ = x[OCHECKNIL-146] - _ = x[OVARDEF-147] - _ = x[OVARKILL-148] - _ = x[OVARLIVE-149] - _ = x[ORESULT-150] - _ = x[OINLMARK-151] - _ = x[ORETJMP-152] - _ = x[OGETG-153] - _ = x[OEND-154] + _ = x[OTSLICE-138] + _ = x[ODDD-139] + _ = x[OINLCALL-140] + _ = x[OEFACE-141] + _ = x[OITAB-142] + _ = x[OIDATA-143] + _ = x[OSPTR-144] + _ = x[OCLOSUREREAD-145] + _ = x[OCFUNC-146] + _ = x[OCHECKNIL-147] + _ = x[OVARDEF-148] + _ = x[OVARKILL-149] + _ = x[OVARLIVE-150] + _ = x[ORESULT-151] + _ = x[OINLMARK-152] + _ = x[ORETJMP-153] + _ = x[OGETG-154] + _ = x[OEND-155] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREREADCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEDDDINLCALLEFACEITABIDATASPTRCLOSUREREADCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 310, 317, 323, 326, 332, 339, 347, 351, 358, 366, 368, 370, 372, 374, 376, 378, 383, 388, 396, 399, 408, 411, 415, 423, 430, 439, 452, 455, 458, 461, 464, 467, 470, 476, 479, 485, 488, 494, 498, 501, 505, 510, 515, 521, 526, 530, 535, 543, 551, 557, 566, 577, 584, 588, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 658, 663, 668, 672, 680, 685, 690, 694, 697, 705, 709, 711, 716, 718, 723, 729, 735, 741, 747, 752, 756, 763, 769, 774, 780, 783, 790, 795, 799, 804, 808, 819, 824, 832, 838, 845, 852, 858, 865, 871, 875, 878} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 310, 317, 323, 326, 332, 339, 347, 351, 358, 366, 368, 370, 372, 374, 376, 378, 383, 388, 396, 399, 408, 411, 415, 423, 430, 439, 452, 455, 458, 461, 464, 467, 470, 476, 479, 485, 488, 494, 498, 501, 505, 510, 515, 521, 526, 530, 535, 543, 551, 557, 566, 577, 584, 588, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 658, 663, 668, 672, 680, 685, 690, 694, 697, 705, 709, 711, 716, 718, 723, 729, 735, 741, 747, 752, 756, 763, 769, 774, 780, 786, 789, 796, 801, 805, 810, 814, 825, 830, 838, 844, 851, 858, 864, 871, 877, 881, 884} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { From d40869fcedb208b0bcf7e7d828db12f210a17dc6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 29 Nov 2020 09:38:52 -0500 Subject: [PATCH 029/212] [dev.regabi] cmd/compile: move gc.treecopy to ir.DeepCopy This is a general operation on IR nodes, so it belongs in ir. The copied implementation is adapted to support the extension pattern, allowing nodes to implement their own DeepCopy implementations if needed. This is the first step toward higher-level operations instead of Left, Right, etc. It will allow the new type syntax nodes to be properly immutable and opt out of those fine-grained methods. Passes buildall w/ toolstash -cmp. Change-Id: Ibd64061e01daf14aebc6586cb2eb2b12057ca85a Reviewed-on: https://go-review.googlesource.com/c/go/+/274102 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/noder.go | 2 +- src/cmd/compile/internal/gc/order.go | 8 +- src/cmd/compile/internal/gc/subr.go | 44 ---------- src/cmd/compile/internal/ir/copy.go | 127 +++++++++++++++++++++++++++ src/cmd/compile/internal/ir/node.go | 53 ----------- 5 files changed, 133 insertions(+), 101 deletions(-) create mode 100644 src/cmd/compile/internal/ir/copy.go diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 8ae5874d3b..1c433b5d30 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -451,7 +451,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node { } v := values[i] if decl.Values == nil { - v = treecopy(v, n.Pos()) + v = ir.DeepCopy(n.Pos(), v) } n.SetOp(ir.OLITERAL) diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 6a91b8c91b..d4db7be911 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -609,7 +609,10 @@ func (o *Order) stmt(n ir.Node) { n.SetLeft(o.safeExpr(n.Left())) - l := treecopy(n.Left(), src.NoXPos) + // TODO(rsc): Why is this DeepCopy? + // We should know enough about the form here + // to do something more provably shallower. + l := ir.DeepCopy(src.NoXPos, n.Left()) if l.Op() == ir.OINDEXMAP { l.SetIndexMapLValue(false) } @@ -1123,8 +1126,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { needCopy = mapKeyReplaceStrConv(n.Right()) if instrumenting { - // Race detector needs the copy so it can - // call treecopy on the result. + // Race detector needs the copy. needCopy = true } } diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 336465db98..25490246e6 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -181,42 +181,6 @@ func nodstr(s string) ir.Node { return ir.NewLiteral(constant.MakeString(s)) } -// treecopy recursively copies n, with the exception of -// ONAME, OLITERAL, OTYPE, and ONONAME leaves. -// If pos.IsKnown(), it sets the source position of newly -// allocated nodes to pos. -func treecopy(n ir.Node, pos src.XPos) ir.Node { - if n == nil { - return nil - } - - switch n.Op() { - default: - m := ir.SepCopy(n) - m.SetLeft(treecopy(n.Left(), pos)) - m.SetRight(treecopy(n.Right(), pos)) - m.PtrList().Set(listtreecopy(n.List().Slice(), pos)) - if pos.IsKnown() { - m.SetPos(pos) - } - if m.Name() != nil && n.Op() != ir.ODCLFIELD { - ir.Dump("treecopy", n) - base.Fatalf("treecopy Name") - } - return m - - case ir.OPACK: - // OPACK nodes are never valid in const value declarations, - // but allow them like any other declared symbol to avoid - // crashing (golang.org/issue/11361). - fallthrough - - case ir.ONAME, ir.ONONAME, ir.OLITERAL, ir.ONIL, ir.OTYPE: - return n - - } -} - func isptrto(t *types.Type, et types.EType) bool { if t == nil { return false @@ -1375,14 +1339,6 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool return true } -func listtreecopy(l []ir.Node, pos src.XPos) []ir.Node { - var out []ir.Node - for _, n := range l { - out = append(out, treecopy(n, pos)) - } - return out -} - func liststmt(l []ir.Node) ir.Node { n := ir.Nod(ir.OBLOCK, nil, nil) n.PtrList().Set(l) diff --git a/src/cmd/compile/internal/ir/copy.go b/src/cmd/compile/internal/ir/copy.go new file mode 100644 index 0000000000..7a1611d0d6 --- /dev/null +++ b/src/cmd/compile/internal/ir/copy.go @@ -0,0 +1,127 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ir + +import ( + "cmd/compile/internal/base" + "cmd/internal/src" +) + +// A Node may implement the Orig and SetOrig method to +// maintain a pointer to the "unrewritten" form of a Node. +// If a Node does not implement OrigNode, it is its own Orig. +// +// Note that both SepCopy and Copy have definitions compatible +// with a Node that does not implement OrigNode: such a Node +// is its own Orig, and in that case, that's what both want to return +// anyway (SepCopy unconditionally, and Copy only when the input +// is its own Orig as well, but if the output does not implement +// OrigNode, then neither does the input, making the condition true). +type OrigNode interface { + Node + Orig() Node + SetOrig(Node) +} + +// Orig returns the “original” node for n. +// If n implements OrigNode, Orig returns n.Orig(). +// Otherwise Orig returns n itself. +func Orig(n Node) Node { + if n, ok := n.(OrigNode); ok { + o := n.Orig() + if o == nil { + Dump("Orig nil", n) + base.Fatalf("Orig returned nil") + } + return o + } + return n +} + +// SepCopy returns a separate shallow copy of n, +// breaking any Orig link to any other nodes. +func SepCopy(n Node) Node { + n = n.RawCopy() + if n, ok := n.(OrigNode); ok { + n.SetOrig(n) + } + return n +} + +// Copy returns a shallow copy of n. +// If Orig(n) == n, then Orig(Copy(n)) == the copy. +// Otherwise the Orig link is preserved as well. +// +// The specific semantics surrounding Orig are subtle but right for most uses. +// See issues #26855 and #27765 for pitfalls. +func Copy(n Node) Node { + copy := n.RawCopy() + if n, ok := n.(OrigNode); ok && n.Orig() == n { + copy.(OrigNode).SetOrig(copy) + } + return copy +} + +// A Node can implement DeepCopyNode to provide a custom implementation +// of DeepCopy. If the compiler only needs access to a Node's structure during +// DeepCopy, then a Node can implement DeepCopyNode instead of providing +// fine-grained mutable access with Left, SetLeft, Right, SetRight, and so on. +type DeepCopyNode interface { + Node + DeepCopy(pos src.XPos) Node +} + +// DeepCopy returns a “deep” copy of n, with its entire structure copied +// (except for shared nodes like ONAME, ONONAME, OLITERAL, and OTYPE). +// If pos.IsKnown(), it sets the source position of newly allocated Nodes to pos. +// +// The default implementation is to traverse the Node graph, making +// a shallow copy of each node and then updating each field to point +// at shallow copies of children, recursively, using Left, SetLeft, and so on. +// +// If a Node wishes to provide an alternate implementation, it can +// implement a DeepCopy method: see the DeepCopyNode interface. +func DeepCopy(pos src.XPos, n Node) Node { + if n == nil { + return nil + } + + if n, ok := n.(DeepCopyNode); ok { + return n.DeepCopy(pos) + } + + switch n.Op() { + default: + m := SepCopy(n) + m.SetLeft(DeepCopy(pos, n.Left())) + m.SetRight(DeepCopy(pos, n.Right())) + m.PtrList().Set(deepCopyList(pos, n.List().Slice())) + if pos.IsKnown() { + m.SetPos(pos) + } + if m.Name() != nil { + Dump("DeepCopy", n) + base.Fatalf("DeepCopy Name") + } + return m + + case OPACK: + // OPACK nodes are never valid in const value declarations, + // but allow them like any other declared symbol to avoid + // crashing (golang.org/issue/11361). + fallthrough + + case ONAME, ONONAME, OLITERAL, ONIL, OTYPE: + return n + } +} + +func deepCopyList(pos src.XPos, list []Node) []Node { + var out []Node + for _, n := range list { + out = append(out, DeepCopy(pos, n)) + } + return out +} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 47c38c2ab5..653410d175 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -1021,59 +1021,6 @@ func (n *node) RawCopy() Node { return © } -// A Node may implement the Orig and SetOrig method to -// maintain a pointer to the "unrewritten" form of a Node. -// If a Node does not implement OrigNode, it is its own Orig. -// -// Note that both SepCopy and Copy have definitions compatible -// with a Node that does not implement OrigNode: such a Node -// is its own Orig, and in that case, that's what both want to return -// anyway (SepCopy unconditionally, and Copy only when the input -// is its own Orig as well, but if the output does not implement -// OrigNode, then neither does the input, making the condition true). -type OrigNode interface { - Node - Orig() Node - SetOrig(Node) -} - -func Orig(n Node) Node { - if n, ok := n.(OrigNode); ok { - o := n.Orig() - if o == nil { - Dump("Orig nil", n) - base.Fatalf("Orig returned nil") - } - return o - } - return n -} - -// sepcopy returns a separate shallow copy of n, with the copy's -// Orig pointing to itself. -func SepCopy(n Node) Node { - n = n.RawCopy() - if n, ok := n.(OrigNode); ok { - n.SetOrig(n) - } - return n -} - -// copy returns shallow copy of n and adjusts the copy's Orig if -// necessary: In general, if n.Orig points to itself, the copy's -// Orig should point to itself as well. Otherwise, if n is modified, -// the copy's Orig node appears modified, too, and then doesn't -// represent the original node anymore. -// (This caused the wrong complit Op to be used when printing error -// messages; see issues #26855, #27765). -func Copy(n Node) Node { - copy := n.RawCopy() - if n, ok := n.(OrigNode); ok && n.Orig() == n { - copy.(OrigNode).SetOrig(copy) - } - return copy -} - // isNil reports whether n represents the universal untyped zero value "nil". func IsNil(n Node) bool { // Check n.Orig because constant propagation may produce typed nil constants, From 4e7685ef1afbf8b1cc692f2a1bd3b02e444d5901 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 26 Nov 2020 07:02:13 -0500 Subject: [PATCH 030/212] [dev.regabi] cmd/compile: add custom type syntax Node implementations The type syntax is reused to stand in for the actual type once typechecked, to avoid updating all the possible references to the original type syntax. So all these implementations allow changing their Op from the raw syntax like OTMAP to the finished form OTYPE, even though obviously the representation does not change. Passes buildall w/ toolstash -cmp. Change-Id: I4acca1a5b35fa2f48ee08e8f1e5a330a004c284b Reviewed-on: https://go-review.googlesource.com/c/go/+/274103 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/fmtmap_test.go | 1 + src/cmd/compile/internal/gc/alg.go | 21 +- src/cmd/compile/internal/gc/builtin.go | 182 +++++------ src/cmd/compile/internal/gc/closure.go | 10 +- src/cmd/compile/internal/gc/dcl.go | 134 ++++---- src/cmd/compile/internal/gc/embed.go | 8 +- src/cmd/compile/internal/gc/iexport.go | 3 - src/cmd/compile/internal/gc/iimport.go | 3 - src/cmd/compile/internal/gc/init.go | 2 +- src/cmd/compile/internal/gc/mkbuiltin.go | 2 +- src/cmd/compile/internal/gc/noder.go | 102 +++--- src/cmd/compile/internal/gc/reflect.go | 8 +- src/cmd/compile/internal/gc/select.go | 2 +- src/cmd/compile/internal/gc/subr.go | 22 +- src/cmd/compile/internal/gc/typecheck.go | 174 +++++------ src/cmd/compile/internal/gc/universe.go | 5 +- src/cmd/compile/internal/gc/walk.go | 11 +- src/cmd/compile/internal/ir/expr.go | 44 +++ src/cmd/compile/internal/ir/fmt.go | 50 ++- src/cmd/compile/internal/ir/mini.go | 9 + src/cmd/compile/internal/ir/name.go | 6 +- src/cmd/compile/internal/ir/node.go | 45 +-- src/cmd/compile/internal/ir/type.go | 376 ++++++++++++++++++++++- 23 files changed, 790 insertions(+), 430 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index e949a89d93..32891aea66 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -95,6 +95,7 @@ var knownFormats = map[string]string{ "cmd/compile/internal/ir.Nodes %+v": "", "cmd/compile/internal/ir.Nodes %.v": "", "cmd/compile/internal/ir.Nodes %v": "", + "cmd/compile/internal/ir.Ntype %v": "", "cmd/compile/internal/ir.Op %#v": "", "cmd/compile/internal/ir.Op %v": "", "cmd/compile/internal/ssa.BranchPrediction %d": "", diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go index b40a56fe39..806417d03d 100644 --- a/src/cmd/compile/internal/gc/alg.go +++ b/src/cmd/compile/internal/gc/alg.go @@ -292,12 +292,12 @@ func genhash(t *types.Type) *obj.LSym { dclcontext = ir.PEXTERN // func sym(p *T, h uintptr) uintptr - tfn := ir.Nod(ir.OTFUNC, nil, nil) - tfn.PtrList().Set2( + args := []*ir.Field{ namedfield("p", types.NewPtr(t)), namedfield("h", types.Types[types.TUINTPTR]), - ) - tfn.PtrRlist().Set1(anonfield(types.Types[types.TUINTPTR])) + } + results := []*ir.Field{anonfield(types.Types[types.TUINTPTR])} + tfn := ir.NewFuncType(base.Pos, nil, args, results) fn := dclfunc(sym, tfn) np := ir.AsNode(tfn.Type().Params().Field(0).Nname) @@ -432,10 +432,10 @@ func hashfor(t *types.Type) ir.Node { n := NewName(sym) setNodeNameFunc(n) - n.SetType(functype(nil, []ir.Node{ + n.SetType(functype(nil, []*ir.Field{ anonfield(types.NewPtr(t)), anonfield(types.Types[types.TUINTPTR]), - }, []ir.Node{ + }, []*ir.Field{ anonfield(types.Types[types.TUINTPTR]), })) return n @@ -521,12 +521,9 @@ func geneq(t *types.Type) *obj.LSym { dclcontext = ir.PEXTERN // func sym(p, q *T) bool - tfn := ir.Nod(ir.OTFUNC, nil, nil) - tfn.PtrList().Set2( - namedfield("p", types.NewPtr(t)), - namedfield("q", types.NewPtr(t)), - ) - tfn.PtrRlist().Set1(namedfield("r", types.Types[types.TBOOL])) + tfn := ir.NewFuncType(base.Pos, nil, + []*ir.Field{namedfield("p", types.NewPtr(t)), namedfield("q", types.NewPtr(t))}, + []*ir.Field{namedfield("r", types.Types[types.TBOOL])}) fn := dclfunc(sym, tfn) np := ir.AsNode(tfn.Type().Params().Field(0).Nname) diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go index a57c611559..efca44c667 100644 --- a/src/cmd/compile/internal/gc/builtin.go +++ b/src/cmd/compile/internal/gc/builtin.go @@ -210,132 +210,132 @@ func runtimeTypes() []*types.Type { typs[1] = types.NewPtr(typs[0]) typs[2] = types.Types[types.TANY] typs[3] = types.NewPtr(typs[2]) - typs[4] = functype(nil, []ir.Node{anonfield(typs[1])}, []ir.Node{anonfield(typs[3])}) + typs[4] = functype(nil, []*ir.Field{anonfield(typs[1])}, []*ir.Field{anonfield(typs[3])}) typs[5] = types.Types[types.TUINTPTR] typs[6] = types.Types[types.TBOOL] typs[7] = types.Types[types.TUNSAFEPTR] - typs[8] = functype(nil, []ir.Node{anonfield(typs[5]), anonfield(typs[1]), anonfield(typs[6])}, []ir.Node{anonfield(typs[7])}) + typs[8] = functype(nil, []*ir.Field{anonfield(typs[5]), anonfield(typs[1]), anonfield(typs[6])}, []*ir.Field{anonfield(typs[7])}) typs[9] = functype(nil, nil, nil) typs[10] = types.Types[types.TINTER] - typs[11] = functype(nil, []ir.Node{anonfield(typs[10])}, nil) + typs[11] = functype(nil, []*ir.Field{anonfield(typs[10])}, nil) typs[12] = types.Types[types.TINT32] typs[13] = types.NewPtr(typs[12]) - typs[14] = functype(nil, []ir.Node{anonfield(typs[13])}, []ir.Node{anonfield(typs[10])}) + typs[14] = functype(nil, []*ir.Field{anonfield(typs[13])}, []*ir.Field{anonfield(typs[10])}) typs[15] = types.Types[types.TINT] - typs[16] = functype(nil, []ir.Node{anonfield(typs[15]), anonfield(typs[15])}, nil) + typs[16] = functype(nil, []*ir.Field{anonfield(typs[15]), anonfield(typs[15])}, nil) typs[17] = types.Types[types.TUINT] - typs[18] = functype(nil, []ir.Node{anonfield(typs[17]), anonfield(typs[15])}, nil) - typs[19] = functype(nil, []ir.Node{anonfield(typs[6])}, nil) + typs[18] = functype(nil, []*ir.Field{anonfield(typs[17]), anonfield(typs[15])}, nil) + typs[19] = functype(nil, []*ir.Field{anonfield(typs[6])}, nil) typs[20] = types.Types[types.TFLOAT64] - typs[21] = functype(nil, []ir.Node{anonfield(typs[20])}, nil) + typs[21] = functype(nil, []*ir.Field{anonfield(typs[20])}, nil) typs[22] = types.Types[types.TINT64] - typs[23] = functype(nil, []ir.Node{anonfield(typs[22])}, nil) + typs[23] = functype(nil, []*ir.Field{anonfield(typs[22])}, nil) typs[24] = types.Types[types.TUINT64] - typs[25] = functype(nil, []ir.Node{anonfield(typs[24])}, nil) + typs[25] = functype(nil, []*ir.Field{anonfield(typs[24])}, nil) typs[26] = types.Types[types.TCOMPLEX128] - typs[27] = functype(nil, []ir.Node{anonfield(typs[26])}, nil) + typs[27] = functype(nil, []*ir.Field{anonfield(typs[26])}, nil) typs[28] = types.Types[types.TSTRING] - typs[29] = functype(nil, []ir.Node{anonfield(typs[28])}, nil) - typs[30] = functype(nil, []ir.Node{anonfield(typs[2])}, nil) - typs[31] = functype(nil, []ir.Node{anonfield(typs[5])}, nil) + typs[29] = functype(nil, []*ir.Field{anonfield(typs[28])}, nil) + typs[30] = functype(nil, []*ir.Field{anonfield(typs[2])}, nil) + typs[31] = functype(nil, []*ir.Field{anonfield(typs[5])}, nil) typs[32] = types.NewArray(typs[0], 32) typs[33] = types.NewPtr(typs[32]) - typs[34] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[28])}) - typs[35] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[28])}) - typs[36] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[28])}) - typs[37] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[28])}) + typs[34] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[28])}) + typs[35] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[28])}) + typs[36] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[28])}) + typs[37] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[28])}) typs[38] = types.NewSlice(typs[28]) - typs[39] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[38])}, []ir.Node{anonfield(typs[28])}) - typs[40] = functype(nil, []ir.Node{anonfield(typs[28]), anonfield(typs[28])}, []ir.Node{anonfield(typs[15])}) + typs[39] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[38])}, []*ir.Field{anonfield(typs[28])}) + typs[40] = functype(nil, []*ir.Field{anonfield(typs[28]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[15])}) typs[41] = types.NewArray(typs[0], 4) typs[42] = types.NewPtr(typs[41]) - typs[43] = functype(nil, []ir.Node{anonfield(typs[42]), anonfield(typs[22])}, []ir.Node{anonfield(typs[28])}) - typs[44] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[1]), anonfield(typs[15])}, []ir.Node{anonfield(typs[28])}) - typs[45] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15])}, []ir.Node{anonfield(typs[28])}) + typs[43] = functype(nil, []*ir.Field{anonfield(typs[42]), anonfield(typs[22])}, []*ir.Field{anonfield(typs[28])}) + typs[44] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[1]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[28])}) + typs[45] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[28])}) typs[46] = types.Runetype typs[47] = types.NewSlice(typs[46]) - typs[48] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[47])}, []ir.Node{anonfield(typs[28])}) + typs[48] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[47])}, []*ir.Field{anonfield(typs[28])}) typs[49] = types.NewSlice(typs[0]) - typs[50] = functype(nil, []ir.Node{anonfield(typs[33]), anonfield(typs[28])}, []ir.Node{anonfield(typs[49])}) + typs[50] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[49])}) typs[51] = types.NewArray(typs[46], 32) typs[52] = types.NewPtr(typs[51]) - typs[53] = functype(nil, []ir.Node{anonfield(typs[52]), anonfield(typs[28])}, []ir.Node{anonfield(typs[47])}) - typs[54] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []ir.Node{anonfield(typs[15])}) - typs[55] = functype(nil, []ir.Node{anonfield(typs[28]), anonfield(typs[15])}, []ir.Node{anonfield(typs[46]), anonfield(typs[15])}) - typs[56] = functype(nil, []ir.Node{anonfield(typs[28])}, []ir.Node{anonfield(typs[15])}) - typs[57] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[2])}, []ir.Node{anonfield(typs[2])}) - typs[58] = functype(nil, []ir.Node{anonfield(typs[2])}, []ir.Node{anonfield(typs[7])}) - typs[59] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[3])}, []ir.Node{anonfield(typs[2])}) - typs[60] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[2])}, []ir.Node{anonfield(typs[2]), anonfield(typs[6])}) - typs[61] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil) - typs[62] = functype(nil, []ir.Node{anonfield(typs[1])}, nil) + typs[53] = functype(nil, []*ir.Field{anonfield(typs[52]), anonfield(typs[28])}, []*ir.Field{anonfield(typs[47])}) + typs[54] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []*ir.Field{anonfield(typs[15])}) + typs[55] = functype(nil, []*ir.Field{anonfield(typs[28]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[46]), anonfield(typs[15])}) + typs[56] = functype(nil, []*ir.Field{anonfield(typs[28])}, []*ir.Field{anonfield(typs[15])}) + typs[57] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[2])}, []*ir.Field{anonfield(typs[2])}) + typs[58] = functype(nil, []*ir.Field{anonfield(typs[2])}, []*ir.Field{anonfield(typs[7])}) + typs[59] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[2])}) + typs[60] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[2])}, []*ir.Field{anonfield(typs[2]), anonfield(typs[6])}) + typs[61] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil) + typs[62] = functype(nil, []*ir.Field{anonfield(typs[1])}, nil) typs[63] = types.NewPtr(typs[5]) - typs[64] = functype(nil, []ir.Node{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []ir.Node{anonfield(typs[6])}) + typs[64] = functype(nil, []*ir.Field{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []*ir.Field{anonfield(typs[6])}) typs[65] = types.Types[types.TUINT32] - typs[66] = functype(nil, nil, []ir.Node{anonfield(typs[65])}) + typs[66] = functype(nil, nil, []*ir.Field{anonfield(typs[65])}) typs[67] = types.NewMap(typs[2], typs[2]) - typs[68] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []ir.Node{anonfield(typs[67])}) - typs[69] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []ir.Node{anonfield(typs[67])}) - typs[70] = functype(nil, nil, []ir.Node{anonfield(typs[67])}) - typs[71] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []ir.Node{anonfield(typs[3])}) - typs[72] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []ir.Node{anonfield(typs[3])}) - typs[73] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []ir.Node{anonfield(typs[3])}) - typs[74] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []ir.Node{anonfield(typs[3]), anonfield(typs[6])}) - typs[75] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []ir.Node{anonfield(typs[3]), anonfield(typs[6])}) - typs[76] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []ir.Node{anonfield(typs[3]), anonfield(typs[6])}) - typs[77] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil) - typs[78] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil) - typs[79] = functype(nil, []ir.Node{anonfield(typs[3])}, nil) - typs[80] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[67])}, nil) + typs[68] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[67])}) + typs[69] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[67])}) + typs[70] = functype(nil, nil, []*ir.Field{anonfield(typs[67])}) + typs[71] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[3])}) + typs[72] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*ir.Field{anonfield(typs[3])}) + typs[73] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*ir.Field{anonfield(typs[3])}) + typs[74] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[3]), anonfield(typs[6])}) + typs[75] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*ir.Field{anonfield(typs[3]), anonfield(typs[6])}) + typs[76] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*ir.Field{anonfield(typs[3]), anonfield(typs[6])}) + typs[77] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil) + typs[78] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil) + typs[79] = functype(nil, []*ir.Field{anonfield(typs[3])}, nil) + typs[80] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[67])}, nil) typs[81] = types.NewChan(typs[2], types.Cboth) - typs[82] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[22])}, []ir.Node{anonfield(typs[81])}) - typs[83] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15])}, []ir.Node{anonfield(typs[81])}) + typs[82] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[22])}, []*ir.Field{anonfield(typs[81])}) + typs[83] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[81])}) typs[84] = types.NewChan(typs[2], types.Crecv) - typs[85] = functype(nil, []ir.Node{anonfield(typs[84]), anonfield(typs[3])}, nil) - typs[86] = functype(nil, []ir.Node{anonfield(typs[84]), anonfield(typs[3])}, []ir.Node{anonfield(typs[6])}) + typs[85] = functype(nil, []*ir.Field{anonfield(typs[84]), anonfield(typs[3])}, nil) + typs[86] = functype(nil, []*ir.Field{anonfield(typs[84]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[6])}) typs[87] = types.NewChan(typs[2], types.Csend) - typs[88] = functype(nil, []ir.Node{anonfield(typs[87]), anonfield(typs[3])}, nil) + typs[88] = functype(nil, []*ir.Field{anonfield(typs[87]), anonfield(typs[3])}, nil) typs[89] = types.NewArray(typs[0], 3) - typs[90] = tostruct([]ir.Node{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])}) - typs[91] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) - typs[92] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[3])}, nil) - typs[93] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []ir.Node{anonfield(typs[15])}) - typs[94] = functype(nil, []ir.Node{anonfield(typs[87]), anonfield(typs[3])}, []ir.Node{anonfield(typs[6])}) - typs[95] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[84])}, []ir.Node{anonfield(typs[6])}) + typs[90] = tostruct([]*ir.Field{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])}) + typs[91] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) + typs[92] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[3])}, nil) + typs[93] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[15])}) + typs[94] = functype(nil, []*ir.Field{anonfield(typs[87]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[6])}) + typs[95] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[84])}, []*ir.Field{anonfield(typs[6])}) typs[96] = types.NewPtr(typs[6]) - typs[97] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []ir.Node{anonfield(typs[6])}) - typs[98] = functype(nil, []ir.Node{anonfield(typs[63])}, nil) - typs[99] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []ir.Node{anonfield(typs[15]), anonfield(typs[6])}) - typs[100] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []ir.Node{anonfield(typs[7])}) - typs[101] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []ir.Node{anonfield(typs[7])}) - typs[102] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []ir.Node{anonfield(typs[7])}) + typs[97] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []*ir.Field{anonfield(typs[6])}) + typs[98] = functype(nil, []*ir.Field{anonfield(typs[63])}, nil) + typs[99] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []*ir.Field{anonfield(typs[15]), anonfield(typs[6])}) + typs[100] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[7])}) + typs[101] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*ir.Field{anonfield(typs[7])}) + typs[102] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*ir.Field{anonfield(typs[7])}) typs[103] = types.NewSlice(typs[2]) - typs[104] = functype(nil, []ir.Node{anonfield(typs[1]), anonfield(typs[103]), anonfield(typs[15])}, []ir.Node{anonfield(typs[103])}) - typs[105] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil) - typs[106] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[5])}, nil) - typs[107] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []ir.Node{anonfield(typs[6])}) - typs[108] = functype(nil, []ir.Node{anonfield(typs[3]), anonfield(typs[3])}, []ir.Node{anonfield(typs[6])}) - typs[109] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[7])}, []ir.Node{anonfield(typs[6])}) - typs[110] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []ir.Node{anonfield(typs[5])}) - typs[111] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[5])}, []ir.Node{anonfield(typs[5])}) - typs[112] = functype(nil, []ir.Node{anonfield(typs[22]), anonfield(typs[22])}, []ir.Node{anonfield(typs[22])}) - typs[113] = functype(nil, []ir.Node{anonfield(typs[24]), anonfield(typs[24])}, []ir.Node{anonfield(typs[24])}) - typs[114] = functype(nil, []ir.Node{anonfield(typs[20])}, []ir.Node{anonfield(typs[22])}) - typs[115] = functype(nil, []ir.Node{anonfield(typs[20])}, []ir.Node{anonfield(typs[24])}) - typs[116] = functype(nil, []ir.Node{anonfield(typs[20])}, []ir.Node{anonfield(typs[65])}) - typs[117] = functype(nil, []ir.Node{anonfield(typs[22])}, []ir.Node{anonfield(typs[20])}) - typs[118] = functype(nil, []ir.Node{anonfield(typs[24])}, []ir.Node{anonfield(typs[20])}) - typs[119] = functype(nil, []ir.Node{anonfield(typs[65])}, []ir.Node{anonfield(typs[20])}) - typs[120] = functype(nil, []ir.Node{anonfield(typs[26]), anonfield(typs[26])}, []ir.Node{anonfield(typs[26])}) - typs[121] = functype(nil, []ir.Node{anonfield(typs[5]), anonfield(typs[5])}, nil) - typs[122] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil) + typs[104] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[103]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[103])}) + typs[105] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil) + typs[106] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[5])}, nil) + typs[107] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*ir.Field{anonfield(typs[6])}) + typs[108] = functype(nil, []*ir.Field{anonfield(typs[3]), anonfield(typs[3])}, []*ir.Field{anonfield(typs[6])}) + typs[109] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[7])}, []*ir.Field{anonfield(typs[6])}) + typs[110] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*ir.Field{anonfield(typs[5])}) + typs[111] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[5])}, []*ir.Field{anonfield(typs[5])}) + typs[112] = functype(nil, []*ir.Field{anonfield(typs[22]), anonfield(typs[22])}, []*ir.Field{anonfield(typs[22])}) + typs[113] = functype(nil, []*ir.Field{anonfield(typs[24]), anonfield(typs[24])}, []*ir.Field{anonfield(typs[24])}) + typs[114] = functype(nil, []*ir.Field{anonfield(typs[20])}, []*ir.Field{anonfield(typs[22])}) + typs[115] = functype(nil, []*ir.Field{anonfield(typs[20])}, []*ir.Field{anonfield(typs[24])}) + typs[116] = functype(nil, []*ir.Field{anonfield(typs[20])}, []*ir.Field{anonfield(typs[65])}) + typs[117] = functype(nil, []*ir.Field{anonfield(typs[22])}, []*ir.Field{anonfield(typs[20])}) + typs[118] = functype(nil, []*ir.Field{anonfield(typs[24])}, []*ir.Field{anonfield(typs[20])}) + typs[119] = functype(nil, []*ir.Field{anonfield(typs[65])}, []*ir.Field{anonfield(typs[20])}) + typs[120] = functype(nil, []*ir.Field{anonfield(typs[26]), anonfield(typs[26])}, []*ir.Field{anonfield(typs[26])}) + typs[121] = functype(nil, []*ir.Field{anonfield(typs[5]), anonfield(typs[5])}, nil) + typs[122] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil) typs[123] = types.NewSlice(typs[7]) - typs[124] = functype(nil, []ir.Node{anonfield(typs[7]), anonfield(typs[123])}, nil) + typs[124] = functype(nil, []*ir.Field{anonfield(typs[7]), anonfield(typs[123])}, nil) typs[125] = types.Types[types.TUINT8] - typs[126] = functype(nil, []ir.Node{anonfield(typs[125]), anonfield(typs[125])}, nil) + typs[126] = functype(nil, []*ir.Field{anonfield(typs[125]), anonfield(typs[125])}, nil) typs[127] = types.Types[types.TUINT16] - typs[128] = functype(nil, []ir.Node{anonfield(typs[127]), anonfield(typs[127])}, nil) - typs[129] = functype(nil, []ir.Node{anonfield(typs[65]), anonfield(typs[65])}, nil) - typs[130] = functype(nil, []ir.Node{anonfield(typs[24]), anonfield(typs[24])}, nil) + typs[128] = functype(nil, []*ir.Field{anonfield(typs[127]), anonfield(typs[127])}, nil) + typs[129] = functype(nil, []*ir.Field{anonfield(typs[65]), anonfield(typs[65])}, nil) + typs[130] = functype(nil, []*ir.Field{anonfield(typs[24]), anonfield(typs[24])}, nil) return typs[:] } diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index ee09e7876e..0ba2858b8b 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -363,7 +363,7 @@ func closureType(clo ir.Node) *types.Type { // The information appears in the binary in the form of type descriptors; // the struct is unnamed so that closures in multiple packages with the // same struct type can share the descriptor. - fields := []ir.Node{ + fields := []*ir.Field{ namedfield(".F", types.Types[types.TUINTPTR]), } for _, v := range clo.Func().ClosureVars { @@ -456,9 +456,9 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) *ir.Func { // number at the use of the method expression in this // case. See issue 29389. - tfn := ir.Nod(ir.OTFUNC, nil, nil) - tfn.PtrList().Set(structargs(t0.Params(), true)) - tfn.PtrRlist().Set(structargs(t0.Results(), false)) + tfn := ir.NewFuncType(base.Pos, nil, + structargs(t0.Params(), true), + structargs(t0.Results(), false)) fn := dclfunc(sym, tfn) fn.SetDupok(true) @@ -510,7 +510,7 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) *ir.Func { // needed in the closure for n (n must be a OCALLPART node). // The address of a variable of the returned type can be cast to a func. func partialCallType(n ir.Node) *types.Type { - t := tostruct([]ir.Node{ + t := tostruct([]*ir.Field{ namedfield("F", types.Types[types.TUINTPTR]), namedfield("R", n.Left().Type()), }) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 3d8f97d93d..637587392a 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -134,7 +134,7 @@ func addvar(n *ir.Name, t *types.Type, ctxt ir.Class) { // declare variables from grammar // new_name_list (type | [type] = expr_list) -func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node { +func variter(vl []ir.Node, t ir.Ntype, el []ir.Node) []ir.Node { var init []ir.Node doexpr := len(el) > 0 @@ -221,18 +221,16 @@ func dclname(s *types.Sym) *ir.Name { return n } -func anonfield(typ *types.Type) ir.Node { +func anonfield(typ *types.Type) *ir.Field { return symfield(nil, typ) } -func namedfield(s string, typ *types.Type) ir.Node { +func namedfield(s string, typ *types.Type) *ir.Field { return symfield(lookup(s), typ) } -func symfield(s *types.Sym, typ *types.Type) ir.Node { - n := nodSym(ir.ODCLFIELD, nil, s) - n.SetType(typ) - return n +func symfield(s *types.Sym, typ *types.Type) *ir.Field { + return ir.NewField(base.Pos, s, nil, typ) } // oldname returns the Node that declares symbol s in the current scope. @@ -279,7 +277,8 @@ func oldname(s *types.Sym) ir.Node { return n } -// importName is like oldname, but it reports an error if sym is from another package and not exported. +// importName is like oldname, +// but it reports an error if sym is from another package and not exported. func importName(sym *types.Sym) ir.Node { n := oldname(sym) if !types.IsExported(sym.Name) && sym.Pkg != ir.LocalPkg { @@ -348,12 +347,12 @@ func colasdefn(left []ir.Node, defn ir.Node) { // declare the arguments in an // interface field declaration. -func ifacedcl(n ir.Node) { - if n.Op() != ir.ODCLFIELD || n.Left() == nil { +func ifacedcl(n *ir.Field) { + if n.Sym == nil { base.Fatalf("ifacedcl") } - if n.Sym().IsBlank() { + if n.Sym.IsBlank() { base.Errorf("methods must have a unique non-blank name") } } @@ -371,13 +370,13 @@ func funchdr(fn *ir.Func) { types.Markdcl() if fn.Nname != nil && fn.Nname.Ntype != nil { - funcargs(fn.Nname.Ntype) + funcargs(fn.Nname.Ntype.(*ir.FuncType)) } else { funcargs2(fn.Type()) } } -func funcargs(nt ir.Node) { +func funcargs(nt *ir.FuncType) { if nt.Op() != ir.OTFUNC { base.Fatalf("funcargs %v", nt.Op()) } @@ -389,13 +388,13 @@ func funcargs(nt ir.Node) { // TODO(mdempsky): This is ugly, and only necessary because // esc.go uses Vargen to figure out result parameters' index // within the result tuple. - vargen = nt.Rlist().Len() + vargen = len(nt.Results) // declare the receiver and in arguments. - if nt.Left() != nil { - funcarg(nt.Left(), ir.PPARAM) + if nt.Recv != nil { + funcarg(nt.Recv, ir.PPARAM) } - for _, n := range nt.List().Slice() { + for _, n := range nt.Params { funcarg(n, ir.PPARAM) } @@ -403,21 +402,21 @@ func funcargs(nt ir.Node) { vargen = 0 // declare the out arguments. - gen := nt.List().Len() - for _, n := range nt.Rlist().Slice() { - if n.Sym() == nil { + gen := len(nt.Params) + for _, n := range nt.Results { + if n.Sym == nil { // Name so that escape analysis can track it. ~r stands for 'result'. - n.SetSym(lookupN("~r", gen)) + n.Sym = lookupN("~r", gen) gen++ } - if n.Sym().IsBlank() { + if n.Sym.IsBlank() { // Give it a name so we can assign to it during return. ~b stands for 'blank'. // The name must be different from ~r above because if you have // func f() (_ int) // func g() int // f is allowed to use a plain 'return' with no arguments, while g is not. // So the two cases must be distinguished. - n.SetSym(lookupN("~b", gen)) + n.Sym = lookupN("~b", gen) gen++ } @@ -427,22 +426,19 @@ func funcargs(nt ir.Node) { vargen = oldvargen } -func funcarg(n ir.Node, ctxt ir.Class) { - if n.Op() != ir.ODCLFIELD { - base.Fatalf("funcarg %v", n.Op()) - } - if n.Sym() == nil { +func funcarg(n *ir.Field, ctxt ir.Class) { + if n.Sym == nil { return } - name := ir.NewNameAt(n.Pos(), n.Sym()) - n.SetRight(name) - name.Ntype = n.Left() - name.SetIsDDD(n.IsDDD()) + name := ir.NewNameAt(n.Pos, n.Sym) + n.Decl = name + name.Ntype = n.Ntype + name.SetIsDDD(n.IsDDD) declare(name, ctxt) vargen++ - n.Right().Name().Vargen = int32(vargen) + n.Decl.Name().Vargen = int32(vargen) } // Same as funcargs, except run over an already constructed TFUNC. @@ -514,28 +510,22 @@ func checkembeddedtype(t *types.Type) { } } -func structfield(n ir.Node) *types.Field { +func structfield(n *ir.Field) *types.Field { lno := base.Pos - base.Pos = n.Pos() + base.Pos = n.Pos - if n.Op() != ir.ODCLFIELD { - base.Fatalf("structfield: oops %v\n", n) + if n.Ntype != nil { + n.Ntype = typecheckNtype(n.Ntype) + n.Type = n.Ntype.Type() + n.Ntype = nil } - if n.Left() != nil { - n.SetLeft(typecheck(n.Left(), ctxType)) - n.SetType(n.Left().Type()) - n.SetLeft(nil) - } - - f := types.NewField(n.Pos(), n.Sym(), n.Type()) - if n.Embedded() { - checkembeddedtype(n.Type()) + f := types.NewField(n.Pos, n.Sym, n.Type) + if n.Embedded { + checkembeddedtype(n.Type) f.Embedded = 1 } - if n.Opt() != nil { - f.Note = n.Opt().(string) - } + f.Note = n.Note base.Pos = lno return f @@ -561,7 +551,7 @@ func checkdupfields(what string, fss ...[]*types.Field) { // convert a parsed id/type list into // a type for struct/interface/arglist -func tostruct(l []ir.Node) *types.Type { +func tostruct(l []*ir.Field) *types.Type { t := types.New(types.TSTRUCT) fields := make([]*types.Field, len(l)) @@ -583,17 +573,17 @@ func tostruct(l []ir.Node) *types.Type { return t } -func tofunargs(l []ir.Node, funarg types.Funarg) *types.Type { +func tofunargs(l []*ir.Field, funarg types.Funarg) *types.Type { t := types.New(types.TSTRUCT) t.StructType().Funarg = funarg fields := make([]*types.Field, len(l)) for i, n := range l { f := structfield(n) - f.SetIsDDD(n.IsDDD()) - if n.Right() != nil { - n.Right().SetType(f.Type) - f.Nname = n.Right() + f.SetIsDDD(n.IsDDD) + if n.Decl != nil { + n.Decl.SetType(f.Type) + f.Nname = n.Decl } if f.Broke() { t.SetBroke(true) @@ -611,15 +601,11 @@ func tofunargsfield(fields []*types.Field, funarg types.Funarg) *types.Type { return t } -func interfacefield(n ir.Node) *types.Field { +func interfacefield(n *ir.Field) *types.Field { lno := base.Pos - base.Pos = n.Pos() + base.Pos = n.Pos - if n.Op() != ir.ODCLFIELD { - base.Fatalf("interfacefield: oops %v\n", n) - } - - if n.Opt() != nil { + if n.Note != "" { base.Errorf("interface method cannot have annotation") } @@ -628,19 +614,19 @@ func interfacefield(n ir.Node) *types.Field { // If Sym != nil, then Sym is MethodName and Left is Signature. // Otherwise, Left is InterfaceTypeName. - if n.Left() != nil { - n.SetLeft(typecheck(n.Left(), ctxType)) - n.SetType(n.Left().Type()) - n.SetLeft(nil) + if n.Ntype != nil { + n.Ntype = typecheckNtype(n.Ntype) + n.Type = n.Ntype.Type() + n.Ntype = nil } - f := types.NewField(n.Pos(), n.Sym(), n.Type()) + f := types.NewField(n.Pos, n.Sym, n.Type) base.Pos = lno return f } -func tointerface(l []ir.Node) *types.Type { +func tointerface(l []*ir.Field) *types.Type { if len(l) == 0 { return types.Types[types.TINTER] } @@ -657,7 +643,7 @@ func tointerface(l []ir.Node) *types.Type { return t } -func fakeRecv() ir.Node { +func fakeRecv() *ir.Field { return anonfield(types.FakeRecvType()) } @@ -673,12 +659,12 @@ func isifacemethod(f *types.Type) bool { } // turn a parsed function declaration into a type -func functype(this ir.Node, in, out []ir.Node) *types.Type { +func functype(this *ir.Field, in, out []*ir.Field) *types.Type { t := types.New(types.TFUNC) - var rcvr []ir.Node + var rcvr []*ir.Field if this != nil { - rcvr = []ir.Node{this} + rcvr = []*ir.Field{this} } t.FuncType().Receiver = tofunargs(rcvr, types.FunargRcvr) t.FuncType().Params = tofunargs(in, types.FunargParams) @@ -923,7 +909,7 @@ func setNodeNameFunc(n ir.Node) { n.Sym().SetFunc(true) } -func dclfunc(sym *types.Sym, tfn ir.Node) *ir.Func { +func dclfunc(sym *types.Sym, tfn ir.Ntype) *ir.Func { if tfn.Op() != ir.OTFUNC { base.Fatalf("expected OTFUNC node, got %v", tfn) } @@ -934,7 +920,7 @@ func dclfunc(sym *types.Sym, tfn ir.Node) *ir.Func { fn.Nname.Ntype = tfn setNodeNameFunc(fn.Nname) funchdr(fn) - fn.Nname.Ntype = typecheck(fn.Nname.Ntype, ctxType) + fn.Nname.Ntype = typecheckNtype(fn.Nname.Ntype) return fn } diff --git a/src/cmd/compile/internal/gc/embed.go b/src/cmd/compile/internal/gc/embed.go index 1c8ccdadef..d9bfd6f5ed 100644 --- a/src/cmd/compile/internal/gc/embed.go +++ b/src/cmd/compile/internal/gc/embed.go @@ -28,7 +28,7 @@ const ( var numLocalEmbed int -func varEmbed(p *noder, names []ir.Node, typ ir.Node, exprs []ir.Node, embeds []PragmaEmbed) (newExprs []ir.Node) { +func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds []PragmaEmbed) (newExprs []ir.Node) { haveEmbed := false for _, decl := range p.file.DeclList { imp, ok := decl.(*syntax.ImportDecl) @@ -141,8 +141,10 @@ func embedKindApprox(typ ir.Node) int { if typ.Sym() != nil && typ.Sym().Name == "string" && typ.Sym().Pkg == ir.LocalPkg { return embedString } - if typ.Op() == ir.OTARRAY && typ.Left() == nil && typ.Right().Sym() != nil && typ.Right().Sym().Name == "byte" && typ.Right().Sym().Pkg == ir.LocalPkg { - return embedBytes + if typ, ok := typ.(*ir.SliceType); ok { + if sym := typ.Elem.Sym(); sym != nil && sym.Name == "byte" && sym.Pkg == ir.LocalPkg { + return embedBytes + } } return embedUnknown } diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 3f0f381974..c9f5d0c85c 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -1056,9 +1056,6 @@ func (w *exportWriter) stmt(n ir.Node) { w.localName(n.Left()) w.typ(n.Left().Type()) - // case ODCLFIELD: - // unimplemented - handled by default case - case ir.OAS: // Don't export "v = " initializing statements, hope they're always // preceded by the DCL which will be re-parsed and typecheck to reproduce diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 88f6e36e07..c219b70e0f 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -974,9 +974,6 @@ func (r *importReader) node() ir.Node { typ := ir.TypeNode(r.typ()) return npos(pos, liststmt(variter([]ir.Node{lhs}, typ, nil))) // TODO(gri) avoid list creation - // case ODCLFIELD: - // unimplemented - // case OAS, OASWB: // unreachable - mapped to OAS case below by exporter diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go index 7f2a39ff46..ed0218c0e2 100644 --- a/src/cmd/compile/internal/gc/init.go +++ b/src/cmd/compile/internal/gc/init.go @@ -48,7 +48,7 @@ func fninit(n []ir.Node) { if len(nf) > 0 { base.Pos = nf[0].Pos() // prolog/epilog gets line number of first init stmt initializers := lookup("init") - fn := dclfunc(initializers, ir.Nod(ir.OTFUNC, nil, nil)) + fn := dclfunc(initializers, ir.NewFuncType(base.Pos, nil, nil, nil)) for _, dcl := range initTodo.Dcl { dcl.Name().Curfn = fn } diff --git a/src/cmd/compile/internal/gc/mkbuiltin.go b/src/cmd/compile/internal/gc/mkbuiltin.go index d763f1ebee..5317484de9 100644 --- a/src/cmd/compile/internal/gc/mkbuiltin.go +++ b/src/cmd/compile/internal/gc/mkbuiltin.go @@ -207,7 +207,7 @@ func (i *typeInterner) fields(fl *ast.FieldList, keepNames bool) string { } } } - return fmt.Sprintf("[]ir.Node{%s}", strings.Join(res, ", ")) + return fmt.Sprintf("[]*ir.Field{%s}", strings.Join(res, ", ")) } func intconst(e ast.Expr) int64 { diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 1c433b5d30..e6c78d1afb 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -412,7 +412,7 @@ func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node { // constant declarations are handled correctly (e.g., issue 15550). type constState struct { group *syntax.Group - typ ir.Node + typ ir.Ntype values []ir.Node iota int64 } @@ -578,18 +578,18 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node { return f } -func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) ir.Node { - n := p.nod(typ, ir.OTFUNC, nil, nil) +func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *ir.FuncType { + var rcvr *ir.Field if recv != nil { - n.SetLeft(p.param(recv, false, false)) + rcvr = p.param(recv, false, false) } - n.PtrList().Set(p.params(typ.ParamList, true)) - n.PtrRlist().Set(p.params(typ.ResultList, false)) - return n + return ir.NewFuncType(p.pos(typ), rcvr, + p.params(typ.ParamList, true), + p.params(typ.ResultList, false)) } -func (p *noder) params(params []*syntax.Field, dddOk bool) []ir.Node { - nodes := make([]ir.Node, 0, len(params)) +func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Field { + nodes := make([]*ir.Field, 0, len(params)) for i, param := range params { p.setlineno(param) nodes = append(nodes, p.param(param, dddOk, i+1 == len(params))) @@ -597,17 +597,17 @@ func (p *noder) params(params []*syntax.Field, dddOk bool) []ir.Node { return nodes } -func (p *noder) param(param *syntax.Field, dddOk, final bool) ir.Node { +func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Field { var name *types.Sym if param.Name != nil { name = p.name(param.Name) } typ := p.typeExpr(param.Type) - n := p.nodSym(param, ir.ODCLFIELD, typ, name) + n := ir.NewField(p.pos(param), name, typ, nil) // rewrite ...T parameter - if typ.Op() == ir.ODDD { + if typ, ok := typ.(*ir.SliceType); ok && typ.DDD { if !dddOk { // We mark these as syntax errors to get automatic elimination // of multiple such errors per line (see ErrorfAt in subr.go). @@ -619,13 +619,8 @@ func (p *noder) param(param *syntax.Field, dddOk, final bool) ir.Node { p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value) } } - typ.SetOp(ir.OTARRAY) - typ.SetRight(typ.Left()) - typ.SetLeft(nil) - n.SetIsDDD(true) - if n.Left() != nil { - n.Left().SetIsDDD(true) - } + typ.DDD = false + n.IsDDD = true } return n @@ -727,14 +722,14 @@ func (p *noder) expr(expr syntax.Expr) ir.Node { var len ir.Node if expr.Len != nil { len = p.expr(expr.Len) - } else { - len = p.nod(expr, ir.ODDD, nil, nil) } - return p.nod(expr, ir.OTARRAY, len, p.typeExpr(expr.Elem)) + return ir.NewArrayType(p.pos(expr), len, p.typeExpr(expr.Elem)) case *syntax.SliceType: - return p.nod(expr, ir.OTARRAY, nil, p.typeExpr(expr.Elem)) + return ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem)) case *syntax.DotsType: - return p.nod(expr, ir.ODDD, p.typeExpr(expr.Elem), nil) + t := ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem)) + t.DDD = true + return t case *syntax.StructType: return p.structType(expr) case *syntax.InterfaceType: @@ -742,11 +737,11 @@ func (p *noder) expr(expr syntax.Expr) ir.Node { case *syntax.FuncType: return p.signature(nil, expr) case *syntax.MapType: - return p.nod(expr, ir.OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value)) + return ir.NewMapType(p.pos(expr), + p.typeExpr(expr.Key), p.typeExpr(expr.Value)) case *syntax.ChanType: - n := p.nod(expr, ir.OTCHAN, p.typeExpr(expr.Elem), nil) - n.SetTChanDir(p.chanDir(expr.Dir)) - return n + return ir.NewChanType(p.pos(expr), + p.typeExpr(expr.Elem), p.chanDir(expr.Dir)) case *syntax.TypeSwitchGuard: n := p.nod(expr, ir.OTYPESW, nil, p.expr(expr.X)) @@ -837,14 +832,21 @@ func (p *noder) sum(x syntax.Expr) ir.Node { return n } -func (p *noder) typeExpr(typ syntax.Expr) ir.Node { +func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype { // TODO(mdempsky): Be stricter? typecheck should handle errors anyway. - return p.expr(typ) + n := p.expr(typ) + if n == nil { + return nil + } + if _, ok := n.(ir.Ntype); !ok { + ir.Dump("NOT NTYPE", n) + } + return n.(ir.Ntype) } -func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Node { +func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Ntype { if typ != nil { - return p.expr(typ) + return p.typeExpr(typ) } return nil } @@ -862,47 +864,43 @@ func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir { } func (p *noder) structType(expr *syntax.StructType) ir.Node { - l := make([]ir.Node, 0, len(expr.FieldList)) + l := make([]*ir.Field, 0, len(expr.FieldList)) for i, field := range expr.FieldList { p.setlineno(field) - var n ir.Node + var n *ir.Field if field.Name == nil { n = p.embedded(field.Type) } else { - n = p.nodSym(field, ir.ODCLFIELD, p.typeExpr(field.Type), p.name(field.Name)) + n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil) } if i < len(expr.TagList) && expr.TagList[i] != nil { - n.SetOpt(constant.StringVal(p.basicLit(expr.TagList[i]))) + n.Note = constant.StringVal(p.basicLit(expr.TagList[i])) } l = append(l, n) } p.setlineno(expr) - n := p.nod(expr, ir.OTSTRUCT, nil, nil) - n.PtrList().Set(l) - return n + return ir.NewStructType(p.pos(expr), l) } func (p *noder) interfaceType(expr *syntax.InterfaceType) ir.Node { - l := make([]ir.Node, 0, len(expr.MethodList)) + l := make([]*ir.Field, 0, len(expr.MethodList)) for _, method := range expr.MethodList { p.setlineno(method) - var n ir.Node + var n *ir.Field if method.Name == nil { - n = p.nodSym(method, ir.ODCLFIELD, importName(p.packname(method.Type)), nil) + n = ir.NewField(p.pos(method), nil, importName(p.packname(method.Type)).(ir.Ntype), nil) } else { mname := p.name(method.Name) - sig := p.typeExpr(method.Type) - sig.SetLeft(fakeRecv()) - n = p.nodSym(method, ir.ODCLFIELD, sig, mname) + sig := p.typeExpr(method.Type).(*ir.FuncType) + sig.Recv = fakeRecv() + n = ir.NewField(p.pos(method), mname, sig, nil) ifacedcl(n) } l = append(l, n) } - n := p.nod(expr, ir.OTINTER, nil, nil) - n.PtrList().Set(l) - return n + return ir.NewInterfaceType(p.pos(expr), l) } func (p *noder) packname(expr syntax.Expr) *types.Sym { @@ -934,7 +932,7 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym { panic(fmt.Sprintf("unexpected packname: %#v", expr)) } -func (p *noder) embedded(typ syntax.Expr) ir.Node { +func (p *noder) embedded(typ syntax.Expr) *ir.Field { op, isStar := typ.(*syntax.Operation) if isStar { if op.Op != syntax.Mul || op.Y != nil { @@ -944,11 +942,11 @@ func (p *noder) embedded(typ syntax.Expr) ir.Node { } sym := p.packname(typ) - n := p.nodSym(typ, ir.ODCLFIELD, importName(sym), lookup(sym.Name)) - n.SetEmbedded(true) + n := ir.NewField(p.pos(typ), lookup(sym.Name), importName(sym).(ir.Ntype), nil) + n.Embedded = true if isStar { - n.SetLeft(p.nod(op, ir.ODEREF, n.Left(), nil)) + n.Ntype = ir.NewStarExpr(p.pos(op), n.Ntype) } return n } diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index dc9efc07fe..73d369f413 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -347,7 +347,7 @@ func methodfunc(f *types.Type, receiver *types.Type) *types.Type { if receiver != nil { inLen++ } - in := make([]ir.Node, 0, inLen) + in := make([]*ir.Field, 0, inLen) if receiver != nil { d := anonfield(receiver) @@ -356,12 +356,12 @@ func methodfunc(f *types.Type, receiver *types.Type) *types.Type { for _, t := range f.Params().Fields().Slice() { d := anonfield(t.Type) - d.SetIsDDD(t.IsDDD()) + d.IsDDD = t.IsDDD() in = append(in, d) } outLen := f.Results().Fields().Len() - out := make([]ir.Node, 0, outLen) + out := make([]*ir.Field, 0, outLen) for _, t := range f.Results().Fields().Slice() { d := anonfield(t.Type) out = append(out, d) @@ -1626,7 +1626,7 @@ func dumpbasictypes() { // The latter is the type of an auto-generated wrapper. dtypesym(types.NewPtr(types.Errortype)) - dtypesym(functype(nil, []ir.Node{anonfield(types.Errortype)}, []ir.Node{anonfield(types.Types[types.TSTRING])})) + dtypesym(functype(nil, []*ir.Field{anonfield(types.Errortype)}, []*ir.Field{anonfield(types.Types[types.TSTRING])})) // add paths for runtime and main, which 6l imports implicitly. dimportpath(Runtimepkg) diff --git a/src/cmd/compile/internal/gc/select.go b/src/cmd/compile/internal/gc/select.go index 116b6f5b6e..9668df082a 100644 --- a/src/cmd/compile/internal/gc/select.go +++ b/src/cmd/compile/internal/gc/select.go @@ -381,7 +381,7 @@ var scase *types.Type // Keep in sync with src/runtime/select.go. func scasetype() *types.Type { if scase == nil { - scase = tostruct([]ir.Node{ + scase = tostruct([]*ir.Field{ namedfield("c", types.Types[types.TUNSAFEPTR]), namedfield("elem", types.Types[types.TUNSAFEPTR]), }) diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 25490246e6..b1c9d24d99 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -1062,9 +1062,9 @@ func expandmeth(t *types.Type) { t.AllMethods().Set(ms) } -// Given funarg struct list, return list of ODCLFIELD Node fn args. -func structargs(tl *types.Type, mustname bool) []ir.Node { - var args []ir.Node +// Given funarg struct list, return list of fn args. +func structargs(tl *types.Type, mustname bool) []*ir.Field { + var args []*ir.Field gen := 0 for _, t := range tl.Fields().Slice() { s := t.Sym @@ -1074,8 +1074,8 @@ func structargs(tl *types.Type, mustname bool) []ir.Node { gen++ } a := symfield(s, t.Type) - a.SetPos(t.Pos) - a.SetIsDDD(t.IsDDD()) + a.Pos = t.Pos + a.IsDDD = t.IsDDD() args = append(args, a) } @@ -1123,10 +1123,10 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { base.Pos = autogeneratedPos dclcontext = ir.PEXTERN - tfn := ir.Nod(ir.OTFUNC, nil, nil) - tfn.SetLeft(namedfield(".this", rcvr)) - tfn.PtrList().Set(structargs(method.Type.Params(), true)) - tfn.PtrRlist().Set(structargs(method.Type.Results(), false)) + tfn := ir.NewFuncType(base.Pos, + namedfield(".this", rcvr), + structargs(method.Type.Params(), true), + structargs(method.Type.Results(), false)) fn := dclfunc(newnam, tfn) fn.SetDupok(true) @@ -1215,11 +1215,11 @@ func hashmem(t *types.Type) ir.Node { n := NewName(sym) setNodeNameFunc(n) - n.SetType(functype(nil, []ir.Node{ + n.SetType(functype(nil, []*ir.Field{ anonfield(types.NewPtr(t)), anonfield(types.Types[types.TUINTPTR]), anonfield(types.Types[types.TUINTPTR]), - }, []ir.Node{ + }, []*ir.Field{ anonfield(types.Types[types.TUINTPTR]), })) return n diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index a1b1809790..19146e2a9e 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -206,6 +206,10 @@ func typecheckFunc(fn *ir.Func) { } } +func typecheckNtype(n ir.Ntype) ir.Ntype { + return typecheck(n, ctxType).(ir.Ntype) +} + // typecheck type checks node n. // The result of typecheck MUST be assigned back to n, e.g. // n.Left = typecheck(n.Left, top) @@ -403,9 +407,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n - case ir.ODDD: - break - // types (ODEREF is with exprs) case ir.OTYPE: ok |= ctxType @@ -414,70 +415,69 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n } - case ir.OTARRAY: + case ir.OTSLICE: ok |= ctxType - r := typecheck(n.Right(), ctxType) - if r.Type() == nil { - n.SetType(nil) + n := n.(*ir.SliceType) + n.Elem = typecheck(n.Elem, ctxType) + if n.Elem.Type() == nil { return n } + t := types.NewSlice(n.Elem.Type()) + n.SetOTYPE(t) + checkwidth(t) - var t *types.Type - if n.Left() == nil { - t = types.NewSlice(r.Type()) - } else if n.Left().Op() == ir.ODDD { + case ir.OTARRAY: + ok |= ctxType + n := n.(*ir.ArrayType) + n.Elem = typecheck(n.Elem, ctxType) + if n.Elem.Type() == nil { + return n + } + if n.Len == nil { // [...]T if !n.Diag() { n.SetDiag(true) base.Errorf("use of [...] array outside of array literal") } - n.SetType(nil) return n - } else { - n.SetLeft(indexlit(typecheck(n.Left(), ctxExpr))) - l := n.Left() - if ir.ConstType(l) != constant.Int { - switch { - case l.Type() == nil: - // Error already reported elsewhere. - case l.Type().IsInteger() && l.Op() != ir.OLITERAL: - base.Errorf("non-constant array bound %v", l) - default: - base.Errorf("invalid array bound %v", l) - } - n.SetType(nil) - return n + } + n.Len = indexlit(typecheck(n.Len, ctxExpr)) + size := n.Len + if ir.ConstType(size) != constant.Int { + switch { + case size.Type() == nil: + // Error already reported elsewhere. + case size.Type().IsInteger() && size.Op() != ir.OLITERAL: + base.Errorf("non-constant array bound %v", size) + default: + base.Errorf("invalid array bound %v", size) } - - v := l.Val() - if doesoverflow(v, types.Types[types.TINT]) { - base.Errorf("array bound is too large") - n.SetType(nil) - return n - } - - if constant.Sign(v) < 0 { - base.Errorf("array bound must be non-negative") - n.SetType(nil) - return n - } - - bound, _ := constant.Int64Val(v) - t = types.NewArray(r.Type(), bound) + return n } - setTypeNode(n, t) - n.SetLeft(nil) - n.SetRight(nil) + v := size.Val() + if doesoverflow(v, types.Types[types.TINT]) { + base.Errorf("array bound is too large") + return n + } + + if constant.Sign(v) < 0 { + base.Errorf("array bound must be non-negative") + return n + } + + bound, _ := constant.Int64Val(v) + t := types.NewArray(n.Elem.Type(), bound) + n.SetOTYPE(t) checkwidth(t) case ir.OTMAP: ok |= ctxType - n.SetLeft(typecheck(n.Left(), ctxType)) - n.SetRight(typecheck(n.Right(), ctxType)) - l := n.Left() - r := n.Right() + n := n.(*ir.MapType) + n.Key = typecheck(n.Key, ctxType) + n.Elem = typecheck(n.Elem, ctxType) + l := n.Key + r := n.Elem if l.Type() == nil || r.Type() == nil { - n.SetType(nil) return n } if l.Type().NotInHeap() { @@ -486,48 +486,42 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { if r.Type().NotInHeap() { base.Errorf("incomplete (or unallocatable) map value not allowed") } - - setTypeNode(n, types.NewMap(l.Type(), r.Type())) + n.SetOTYPE(types.NewMap(l.Type(), r.Type())) mapqueue = append(mapqueue, n) // check map keys when all types are settled - n.SetLeft(nil) - n.SetRight(nil) case ir.OTCHAN: ok |= ctxType - n.SetLeft(typecheck(n.Left(), ctxType)) - l := n.Left() + n := n.(*ir.ChanType) + n.Elem = typecheck(n.Elem, ctxType) + l := n.Elem if l.Type() == nil { - n.SetType(nil) return n } if l.Type().NotInHeap() { base.Errorf("chan of incomplete (or unallocatable) type not allowed") } - - setTypeNode(n, types.NewChan(l.Type(), n.TChanDir())) - n.SetLeft(nil) - n.ResetAux() + n.SetOTYPE(types.NewChan(l.Type(), n.Dir)) case ir.OTSTRUCT: ok |= ctxType - setTypeNode(n, tostruct(n.List().Slice())) - n.PtrList().Set(nil) + n := n.(*ir.StructType) + n.SetOTYPE(tostruct(n.Fields)) case ir.OTINTER: ok |= ctxType - setTypeNode(n, tointerface(n.List().Slice())) + n := n.(*ir.InterfaceType) + n.SetOTYPE(tointerface(n.Methods)) case ir.OTFUNC: ok |= ctxType - setTypeNode(n, functype(n.Left(), n.List().Slice(), n.Rlist().Slice())) - n.SetLeft(nil) - n.PtrList().Set(nil) - n.PtrRlist().Set(nil) + n := n.(*ir.FuncType) + n.SetOTYPE(functype(n.Recv, n.Params, n.Results)) // type or expr case ir.ODEREF: - n.SetLeft(typecheck(n.Left(), ctxExpr|ctxType)) - l := n.Left() + n := n.(*ir.StarExpr) + n.X = typecheck(n.X, ctxExpr|ctxType) + l := n.X t := l.Type() if t == nil { n.SetType(nil) @@ -535,8 +529,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } if l.Op() == ir.OTYPE { ok |= ctxType - setTypeNode(n, types.NewPtr(l.Type())) - n.SetLeft(nil) + n.SetOTYPE(types.NewPtr(l.Type())) // Ensure l.Type gets dowidth'd for the backend. Issue 20174. checkwidth(l.Type()) break @@ -2822,16 +2815,14 @@ func typecheckcomplit(n ir.Node) (res ir.Node) { setlineno(n.Right()) // Need to handle [...]T arrays specially. - if n.Right().Op() == ir.OTARRAY && n.Right().Left() != nil && n.Right().Left().Op() == ir.ODDD { - n.Right().SetRight(typecheck(n.Right().Right(), ctxType)) - if n.Right().Right().Type() == nil { + if array, ok := n.Right().(*ir.ArrayType); ok && array.Elem != nil && array.Len == nil { + array.Elem = typecheck(array.Elem, ctxType) + elemType := array.Elem.Type() + if elemType == nil { n.SetType(nil) return n } - elemType := n.Right().Right().Type() - length := typecheckarraylit(elemType, -1, n.List().Slice(), "array literal") - n.SetOp(ir.OARRAYLIT) n.SetType(types.NewArray(elemType, length)) n.SetRight(nil) @@ -3464,7 +3455,7 @@ func stringtoruneslit(n ir.Node) ir.Node { return nn } -var mapqueue []ir.Node +var mapqueue []*ir.MapType func checkMapKeys() { for _, n := range mapqueue { @@ -3531,7 +3522,7 @@ func typecheckdeftype(n ir.Node) { } n.SetTypecheck(1) - n.Name().Ntype = typecheck(n.Name().Ntype, ctxType) + n.Name().Ntype = typecheckNtype(n.Name().Ntype) t := n.Name().Ntype.Type() if t == nil { n.SetDiag(true) @@ -3593,7 +3584,7 @@ func typecheckdef(n ir.Node) { case ir.OLITERAL: if n.Name().Ntype != nil { - n.Name().Ntype = typecheck(n.Name().Ntype, ctxType) + n.Name().Ntype = typecheckNtype(n.Name().Ntype) n.SetType(n.Name().Ntype.Type()) n.Name().Ntype = nil if n.Type() == nil { @@ -3647,7 +3638,7 @@ func typecheckdef(n ir.Node) { case ir.ONAME: if n.Name().Ntype != nil { - n.Name().Ntype = typecheck(n.Name().Ntype, ctxType) + n.Name().Ntype = typecheckNtype(n.Name().Ntype) n.SetType(n.Name().Ntype.Type()) if n.Type() == nil { n.SetDiag(true) @@ -3686,9 +3677,9 @@ func typecheckdef(n ir.Node) { if n.Alias() { // Type alias declaration: Simply use the rhs type - no need // to create a new type. - // If we have a syntax error, p.Ntype may be nil. + // If we have a syntax error, name.Ntype may be nil. if n.Ntype != nil { - n.Ntype = typecheck(n.Ntype, ctxType) + n.Ntype = typecheckNtype(n.Ntype) n.SetType(n.Ntype.Type()) if n.Type() == nil { n.SetDiag(true) @@ -3706,8 +3697,10 @@ func typecheckdef(n ir.Node) { // regular type declaration defercheckwidth() n.SetWalkdef(1) - setTypeNode(n, types.New(types.TFORW)) - n.Type().Sym = n.Sym() + t := types.New(types.TFORW) + t.Nod = n + t.Sym = n.Sym() + n.SetType(t) errorsBefore := base.Errors() typecheckdeftype(n) if n.Type().Etype == types.TFORW && base.Errors() > errorsBefore { @@ -3990,11 +3983,12 @@ func deadcodeexpr(n ir.Node) ir.Node { return n } -// setTypeNode sets n to an OTYPE node representing t. -func setTypeNode(n ir.Node, t *types.Type) { - n.SetOp(ir.OTYPE) +func toTypeNode(orig ir.Node, t *types.Type) ir.Node { + n := ir.Nod(ir.OTYPE, nil, nil) + n.SetPos(orig.Pos()) n.SetType(t) - n.Type().Nod = n + t.Nod = n + return n } // getIotaValue returns the current value for "iota", diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 931135759a..d43545391c 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -176,7 +176,10 @@ func typeinit() { t := types.New(types.TUNSAFEPTR) types.Types[types.TUNSAFEPTR] = t t.Sym = unsafepkg.Lookup("Pointer") - t.Sym.Def = ir.TypeNode(t) + n := ir.NewNameAt(src.NoXPos, t.Sym) // NewNameAt to get a package for use tracking + n.SetOp(ir.OTYPE) + n.SetType(t) + t.Sym.Def = n dowidth(types.Types[types.TUNSAFEPTR]) for et := types.TINT8; et <= types.TUINT64; et++ { diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 2376bfc093..e7c88bd329 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -853,7 +853,7 @@ opswitch: } value = ir.Nod(ir.OINDEX, staticuint64s, index) value.SetBounded(true) - case n.Left().Class() == ir.PEXTERN && n.Left().Name() != nil && n.Left().Name().Readonly(): + case n.Left().Name() != nil && n.Left().Class() == ir.PEXTERN && n.Left().Name().Readonly(): // n.Left is a readonly global; use it directly. value = n.Left() case !fromType.IsInterface() && n.Esc() == EscNone && fromType.Width <= 1024: @@ -3183,10 +3183,10 @@ func eqfor(t *types.Type) (n ir.Node, needsize bool) { sym := typesymprefix(".eq", t) n := NewName(sym) setNodeNameFunc(n) - n.SetType(functype(nil, []ir.Node{ + n.SetType(functype(nil, []*ir.Field{ anonfield(types.NewPtr(t)), anonfield(types.NewPtr(t)), - }, []ir.Node{ + }, []*ir.Field{ anonfield(types.Types[types.TBOOL]), })) return n, false @@ -3914,7 +3914,7 @@ func wrapCall(n ir.Node, init *ir.Nodes) ir.Node { // origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion. origArgs := make([]ir.Node, n.List().Len()) - t := ir.Nod(ir.OTFUNC, nil, nil) + var funcArgs []*ir.Field for i, arg := range n.List().Slice() { s := lookupN("a", i) if !isBuiltinCall && arg.Op() == ir.OCONVNOP && arg.Type().IsUintptr() && arg.Left().Type().IsUnsafePtr() { @@ -3922,8 +3922,9 @@ func wrapCall(n ir.Node, init *ir.Nodes) ir.Node { arg = arg.Left() n.List().SetIndex(i, arg) } - t.PtrList().Append(symfield(s, arg.Type())) + funcArgs = append(funcArgs, symfield(s, arg.Type())) } + t := ir.NewFuncType(base.Pos, nil, funcArgs, nil) wrapCall_prgen++ sym := lookupN("wrap·", wrapCall_prgen) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 2c13918599..f8e5f7641c 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -110,3 +110,47 @@ func (n *CallPartExpr) Left() Node { return n.X } func (n *CallPartExpr) Right() Node { return n.Method } func (n *CallPartExpr) SetLeft(x Node) { n.X = x } func (n *CallPartExpr) SetRight(x Node) { n.Method = x.(*Name) } + +// A StarExpr is a dereference expression *X. +// It may end up being a value or a type. +type StarExpr struct { + miniExpr + X Node +} + +func NewStarExpr(pos src.XPos, x Node) *StarExpr { + n := &StarExpr{X: x} + n.op = ODEREF + n.pos = pos + return n +} + +func (n *StarExpr) String() string { return fmt.Sprint(n) } +func (n *StarExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *StarExpr) RawCopy() Node { c := *n; return &c } +func (n *StarExpr) Left() Node { return n.X } +func (n *StarExpr) SetLeft(x Node) { n.X = x } + +func (*StarExpr) CanBeNtype() {} + +// SetOTYPE changes n to be an OTYPE node returning t, +// like all the type nodes in type.go. +func (n *StarExpr) SetOTYPE(t *types.Type) { + n.op = OTYPE + n.X = nil + n.typ = t + if t.Nod == nil { + t.Nod = n + } +} + +func (n *StarExpr) DeepCopy(pos src.XPos) Node { + if n.op == OTYPE { + // Can't change types and no node references left. + return n + } + c := SepCopy(n).(*StarExpr) + c.pos = n.posOr(pos) + c.X = DeepCopy(pos, n.X) + return c +} diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index a3999b6da0..c723bad4c9 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -403,10 +403,6 @@ func jconvFmt(n Node, s fmt.State, flag FmtFlag) { fmt.Fprintf(s, " implicit(%v)", n.Implicit()) } - if n.Embedded() { - fmt.Fprintf(s, " embedded") - } - if n.Op() == ONAME { if n.Name().Addrtaken() { fmt.Fprint(s, " addrtaken") @@ -921,13 +917,6 @@ func stmtFmt(n Node, s fmt.State, mode FmtMode) { case ODCL: mode.Fprintf(s, "var %v %v", n.Left().Sym(), n.Left().Type()) - case ODCLFIELD: - if n.Sym() != nil { - mode.Fprintf(s, "%v %v", n.Sym(), n.Left()) - } else { - mode.Fprintf(s, "%v", n.Left()) - } - // Don't export "v = " initializing statements, hope they're always // preceded by the DCL which will be re-parsed and typechecked to reproduce // the "v = " again. @@ -1115,6 +1104,7 @@ var OpPrec = []int{ OSTR2RUNES: 8, OSTRUCTLIT: 8, OTARRAY: 8, + OTSLICE: 8, OTCHAN: 8, OTFUNC: 8, OTINTER: 8, @@ -1176,7 +1166,6 @@ var OpPrec = []int{ OCASE: -1, OCONTINUE: -1, ODCL: -1, - ODCLFIELD: -1, ODEFER: -1, OEMPTY: -1, OFALL: -1, @@ -1294,29 +1283,40 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { } mode.Fprintf(s, "%v", n.Type()) - case OTARRAY: - if n.Left() != nil { - mode.Fprintf(s, "[%v]%v", n.Left(), n.Right()) - return + case OTSLICE: + n := n.(*SliceType) + if n.DDD { + mode.Fprintf(s, "...%v", n.Elem) + } else { + mode.Fprintf(s, "[]%v", n.Elem) // happens before typecheck + } + + case OTARRAY: + n := n.(*ArrayType) + if n.Len == nil { + mode.Fprintf(s, "[...]%v", n.Elem) + } else { + mode.Fprintf(s, "[%v]%v", n.Len, n.Elem) } - mode.Fprintf(s, "[]%v", n.Right()) // happens before typecheck case OTMAP: - mode.Fprintf(s, "map[%v]%v", n.Left(), n.Right()) + n := n.(*MapType) + mode.Fprintf(s, "map[%v]%v", n.Key, n.Elem) case OTCHAN: - switch n.TChanDir() { + n := n.(*ChanType) + switch n.Dir { case types.Crecv: - mode.Fprintf(s, "<-chan %v", n.Left()) + mode.Fprintf(s, "<-chan %v", n.Elem) case types.Csend: - mode.Fprintf(s, "chan<- %v", n.Left()) + mode.Fprintf(s, "chan<- %v", n.Elem) default: - if n.Left() != nil && n.Left().Op() == OTCHAN && n.Left().Sym() == nil && n.Left().TChanDir() == types.Crecv { - mode.Fprintf(s, "chan (%v)", n.Left()) + if n.Elem != nil && n.Elem.Op() == OTCHAN && n.Elem.(*ChanType).Dir == types.Crecv { + mode.Fprintf(s, "chan (%v)", n.Elem) } else { - mode.Fprintf(s, "chan %v", n.Left()) + mode.Fprintf(s, "chan %v", n.Elem) } } @@ -1556,8 +1556,6 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { } exprFmt(n1, s, nprec, mode) } - case ODDD: - mode.Fprintf(s, "...") default: mode.Fprintf(s, "", n.Op()) } diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index 338ded3308..d73ec4ecd5 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -33,6 +33,15 @@ type miniNode struct { esc uint16 } +// posOr returns pos if known, or else n.pos. +// For use in DeepCopy. +func (n *miniNode) posOr(pos src.XPos) src.XPos { + if pos.IsKnown() { + return pos + } + return n.pos +} + // op can be read, but not written. // An embedding implementation can provide a SetOp if desired. // (The panicking SetOp is with the other panics below.) diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 5546488fa7..1bc6bea3b6 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -43,7 +43,7 @@ type Name struct { Vargen int32 Decldepth int32 // declaration loop depth, increased for every loop or label - Ntype Node + Ntype Ntype Heapaddr *Name // temp holding heap address of param // ONAME PAUTOHEAP @@ -160,6 +160,8 @@ func (n *Name) SetOffset(x int64) { n.offset = x } func (n *Name) Iota() int64 { return n.offset } func (n *Name) SetIota(x int64) { n.offset = x } +func (*Name) CanBeNtype() {} + func (n *Name) SetOp(op Op) { switch op { default: @@ -371,6 +373,8 @@ func (p *PkgName) Format(s fmt.State, verb rune) { FmtNode(p, s, verb) } func (p *PkgName) RawCopy() Node { c := *p; return &c } func (p *PkgName) Sym() *types.Sym { return p.sym } +func (*PkgName) CanBeNtype() {} + func NewPkgName(pos src.XPos, sym *types.Sym, pkg *types.Pkg) *PkgName { p := &PkgName{sym: sym, Pkg: pkg} p.op = OPACK diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 653410d175..74557236cc 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -79,12 +79,8 @@ type Node interface { SetImplicit(x bool) IsDDD() bool SetIsDDD(x bool) - Embedded() bool - SetEmbedded(x bool) IndexMapLValue() bool SetIndexMapLValue(x bool) - TChanDir() types.ChanDir - SetTChanDir(x types.ChanDir) ResetAux() HasBreak() bool SetHasBreak(x bool) @@ -205,6 +201,10 @@ func (n *node) Uint64Val() uint64 { panic("node.Uint64Val") } func (n *node) BoolVal() bool { panic("node.BoolVal") } func (n *node) StringVal() string { panic("node.StringVal") } +// node can be Ntype only because of OXDOT of undefined name. +// When that moves into its own syntax, can drop this. +func (n *node) CanBeNtype() {} + func (n *node) SetOp(op Op) { if !okForNod[op] { panic("cannot node.SetOp " + op.String()) @@ -252,20 +252,6 @@ func (n *node) SetIndexMapLValue(b bool) { } } -func (n *node) TChanDir() types.ChanDir { - if n.Op() != OTCHAN { - base.Fatalf("unexpected op: %v", n.Op()) - } - return types.ChanDir(n.aux) -} - -func (n *node) SetTChanDir(dir types.ChanDir) { - if n.Op() != OTCHAN { - base.Fatalf("unexpected op: %v", n.Op()) - } - n.aux = uint8(dir) -} - func IsSynthetic(n Node) bool { name := n.Sym().Name return name[0] == '.' || name[0] == '~' @@ -301,7 +287,6 @@ const ( _, nodeBounded // bounds check unnecessary _, nodeHasCall // expression contains a function call _, nodeLikely // if statement condition likely - _, nodeEmbedded // ODCLFIELD embedded type ) func (n *node) Class() Class { return Class(n.flags.get3(nodeClass)) } @@ -320,7 +305,6 @@ func (n *node) Transient() bool { return n.flags&nodeTransient != 0 } func (n *node) Bounded() bool { return n.flags&nodeBounded != 0 } func (n *node) HasCall() bool { return n.flags&nodeHasCall != 0 } func (n *node) Likely() bool { return n.flags&nodeLikely != 0 } -func (n *node) Embedded() bool { return n.flags&nodeEmbedded != 0 } func (n *node) SetClass(b Class) { n.flags.set3(nodeClass, uint8(b)) } func (n *node) SetWalkdef(b uint8) { n.flags.set2(nodeWalkdef, b) } @@ -336,7 +320,6 @@ func (n *node) SetColas(b bool) { n.flags.set(nodeColas, b) } func (n *node) SetTransient(b bool) { n.flags.set(nodeTransient, b) } func (n *node) SetHasCall(b bool) { n.flags.set(nodeHasCall, b) } func (n *node) SetLikely(b bool) { n.flags.set(nodeLikely, b) } -func (n *node) SetEmbedded(b bool) { n.flags.set(nodeEmbedded, b) } // MarkNonNil marks a pointer n as being guaranteed non-nil, // on all code paths, at all times. @@ -474,7 +457,7 @@ const ( // Used during parsing but don't last. ODCLFUNC // func f() or func (r) f() - ODCLFIELD // struct field, interface field, or func/method argument/return value. + ODCLFIELD // UNUSED: TODO(rsc): Delete. ODCLCONST // const pi = 3.14 ODCLTYPE // type Int int or type Int = int @@ -593,11 +576,11 @@ const ( // OTFUNC: func() - Left is receiver field, List is list of param fields, Rlist is // list of result fields. OTFUNC - OTARRAY // []int, [8]int, [N]int or [...]int - OTSLICE // to be used in future CL + OTARRAY // [8]int or [...]int + OTSLICE // []int // misc - ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}. + ODDD // UNUSED; TODO(rsc): Delete. OINLCALL // intermediary representation of an inlined call. OEFACE // itable and data words of an empty-interface value. OITAB // itable word of an interface value. @@ -1050,6 +1033,8 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { switch op { case ODCLFUNC: return NewFunc(pos) + case ODEREF: + return NewStarExpr(pos, nleft) case OPACK: return NewPkgName(pos, nil, nil) case OEMPTY: @@ -1112,12 +1097,9 @@ var okForNod = [OEND]bool{ OCOPY: true, ODCL: true, ODCLCONST: true, - ODCLFIELD: true, ODCLTYPE: true, - ODDD: true, ODEFER: true, ODELETE: true, - ODEREF: true, ODIV: true, ODOT: true, ODOTINTER: true, @@ -1201,13 +1183,6 @@ var okForNod = [OEND]bool{ OSTRUCTLIT: true, OSUB: true, OSWITCH: true, - OTARRAY: true, - OTCHAN: true, - OTFUNC: true, - OTINTER: true, - OTMAP: true, - OTSTRUCT: true, - OTYPE: true, // TODO: Remove once setTypeNode is gone. OTYPESW: true, OVARDEF: true, OVARKILL: true, diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index 3409424fed..39411ed431 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -7,21 +7,375 @@ package ir import ( "cmd/compile/internal/types" "cmd/internal/src" + "fmt" ) -func TypeNode(t *types.Type) Node { +// Nodes that represent the syntax of a type before type-checking. +// After type-checking, they serve only as shells around a *types.Type. +// Calling TypeNode converts a *types.Type to a Node shell. + +// An Ntype is a Node that syntactically looks like a type. +// It can be the raw syntax for a type before typechecking, +// or it can be an OTYPE with Type() set to a *types.Type. +// Note that syntax doesn't guarantee it's a type: an expression +// like *fmt is an Ntype (we don't know whether names are types yet), +// but at least 1+1 is not an Ntype. +type Ntype interface { + Node + CanBeNtype() +} + +// A miniType is a minimal type syntax Node implementation, +// to be embedded as the first field in a larger node implementation. +type miniType struct { + miniNode + typ *types.Type +} + +func (*miniType) CanBeNtype() {} + +func (n *miniType) Type() *types.Type { return n.typ } + +// setOTYPE changes n to be an OTYPE node returning t. +// Rewriting the node in place this way should not be strictly +// necessary (we should be able to update the uses with +// proper OTYPE nodes), but it's mostly harmless and easy +// to keep doing for now. +// +// setOTYPE also records t.Nod = self if t.Nod is not already set. +// (Some types are shared by multiple OTYPE nodes, so only +// the first such node is used as t.Nod.) +func (n *miniType) setOTYPE(t *types.Type, self Node) { + if n.typ != nil { + panic(n.op.String() + " SetType: type already set") + } + n.op = OTYPE + n.typ = t + + // t.Nod can be non-nil already + // in the case of shared *type.Types, like []byte or interface{}. + if t.Nod == nil { + t.Nod = self + } +} + +func (n *miniType) Sym() *types.Sym { return nil } // for Format OTYPE +func (n *miniType) Implicit() bool { return false } // for Format OTYPE + +// A ChanType represents a chan Elem syntax with the direction Dir. +type ChanType struct { + miniType + Elem Node + Dir types.ChanDir +} + +func NewChanType(pos src.XPos, elem Node, dir types.ChanDir) *ChanType { + n := &ChanType{Elem: elem, Dir: dir} + n.op = OTCHAN + n.pos = pos + return n +} + +func (n *ChanType) String() string { return fmt.Sprint(n) } +func (n *ChanType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ChanType) RawCopy() Node { c := *n; return &c } +func (n *ChanType) SetOTYPE(t *types.Type) { + n.setOTYPE(t, n) + n.Elem = nil +} + +func (n *ChanType) DeepCopy(pos src.XPos) Node { + if n.op == OTYPE { + // Can't change types and no node references left. + return n + } + return NewChanType(n.posOr(pos), DeepCopy(pos, n.Elem), n.Dir) +} + +// A MapType represents a map[Key]Value type syntax.u +type MapType struct { + miniType + Key Node + Elem Node +} + +func NewMapType(pos src.XPos, key, elem Node) *MapType { + n := &MapType{Key: key, Elem: elem} + n.op = OTMAP + n.pos = pos + return n +} + +func (n *MapType) String() string { return fmt.Sprint(n) } +func (n *MapType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *MapType) RawCopy() Node { c := *n; return &c } +func (n *MapType) SetOTYPE(t *types.Type) { + n.setOTYPE(t, n) + n.Key = nil + n.Elem = nil +} + +func (n *MapType) DeepCopy(pos src.XPos) Node { + if n.op == OTYPE { + // Can't change types and no node references left. + return n + } + return NewMapType(n.posOr(pos), DeepCopy(pos, n.Key), DeepCopy(pos, n.Elem)) +} + +// A StructType represents a struct { ... } type syntax. +type StructType struct { + miniType + Fields []*Field +} + +func NewStructType(pos src.XPos, fields []*Field) *StructType { + n := &StructType{Fields: fields} + n.op = OTSTRUCT + n.pos = pos + return n +} + +func (n *StructType) String() string { return fmt.Sprint(n) } +func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *StructType) RawCopy() Node { c := *n; return &c } +func (n *StructType) SetOTYPE(t *types.Type) { + n.setOTYPE(t, n) + n.Fields = nil +} + +func (n *StructType) DeepCopy(pos src.XPos) Node { + if n.op == OTYPE { + // Can't change types and no node references left. + return n + } + return NewStructType(n.posOr(pos), deepCopyFields(pos, n.Fields)) +} + +func deepCopyFields(pos src.XPos, fields []*Field) []*Field { + var out []*Field + for _, f := range fields { + out = append(out, f.deepCopy(pos)) + } + return out +} + +// An InterfaceType represents a struct { ... } type syntax. +type InterfaceType struct { + miniType + Methods []*Field +} + +func NewInterfaceType(pos src.XPos, methods []*Field) *InterfaceType { + n := &InterfaceType{Methods: methods} + n.op = OTINTER + n.pos = pos + return n +} + +func (n *InterfaceType) String() string { return fmt.Sprint(n) } +func (n *InterfaceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *InterfaceType) RawCopy() Node { c := *n; return &c } +func (n *InterfaceType) SetOTYPE(t *types.Type) { + n.setOTYPE(t, n) + n.Methods = nil +} + +func (n *InterfaceType) DeepCopy(pos src.XPos) Node { + if n.op == OTYPE { + // Can't change types and no node references left. + return n + } + return NewInterfaceType(n.posOr(pos), deepCopyFields(pos, n.Methods)) +} + +// A FuncType represents a func(Args) Results type syntax. +type FuncType struct { + miniType + Recv *Field + Params []*Field + Results []*Field +} + +func NewFuncType(pos src.XPos, rcvr *Field, args, results []*Field) *FuncType { + n := &FuncType{Recv: rcvr, Params: args, Results: results} + n.op = OTFUNC + n.pos = pos + return n +} + +func (n *FuncType) String() string { return fmt.Sprint(n) } +func (n *FuncType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *FuncType) RawCopy() Node { c := *n; return &c } + +func (n *FuncType) SetOTYPE(t *types.Type) { + n.setOTYPE(t, n) + n.Recv = nil + n.Params = nil + n.Results = nil +} + +func (n *FuncType) DeepCopy(pos src.XPos) Node { + if n.op == OTYPE { + // Can't change types and no node references left. + return n + } + return NewFuncType(n.posOr(pos), + n.Recv.deepCopy(pos), + deepCopyFields(pos, n.Params), + deepCopyFields(pos, n.Results)) +} + +// A Field is a declared struct field, interface method, or function argument. +// It is not a Node. +type Field struct { + Pos src.XPos + Sym *types.Sym + Ntype Ntype + Type *types.Type + Embedded bool + IsDDD bool + Note string + Decl *Name +} + +func NewField(pos src.XPos, sym *types.Sym, ntyp Ntype, typ *types.Type) *Field { + return &Field{Pos: pos, Sym: sym, Ntype: ntyp, Type: typ} +} + +func (f *Field) String() string { + var typ string + if f.Type != nil { + typ = fmt.Sprint(f.Type) + } else { + typ = fmt.Sprint(f.Ntype) + } + if f.Sym != nil { + return fmt.Sprintf("%v %v", f.Sym, typ) + } + return typ +} + +func (f *Field) deepCopy(pos src.XPos) *Field { + if f == nil { + return nil + } + fpos := pos + if !pos.IsKnown() { + fpos = f.Pos + } + decl := f.Decl + if decl != nil { + decl = DeepCopy(pos, decl).(*Name) + } + ntype := f.Ntype + if ntype != nil { + ntype = DeepCopy(pos, ntype).(Ntype) + } + // No keyed literal here: if a new struct field is added, we want this to stop compiling. + return &Field{fpos, f.Sym, ntype, f.Type, f.Embedded, f.IsDDD, f.Note, decl} +} + +// A SliceType represents a []Elem type syntax. +// If DDD is true, it's the ...Elem at the end of a function list. +type SliceType struct { + miniType + Elem Node + DDD bool +} + +func NewSliceType(pos src.XPos, elem Node) *SliceType { + n := &SliceType{Elem: elem} + n.op = OTSLICE + n.pos = pos + return n +} + +func (n *SliceType) String() string { return fmt.Sprint(n) } +func (n *SliceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SliceType) RawCopy() Node { c := *n; return &c } +func (n *SliceType) SetOTYPE(t *types.Type) { + n.setOTYPE(t, n) + n.Elem = nil +} + +func (n *SliceType) DeepCopy(pos src.XPos) Node { + if n.op == OTYPE { + // Can't change types and no node references left. + return n + } + return NewSliceType(n.posOr(pos), DeepCopy(pos, n.Elem)) +} + +// An ArrayType represents a [Len]Elem type syntax. +// If Len is nil, the type is a [...]Elem in an array literal. +type ArrayType struct { + miniType + Len Node + Elem Node +} + +func NewArrayType(pos src.XPos, size Node, elem Node) *ArrayType { + n := &ArrayType{Len: size, Elem: elem} + n.op = OTARRAY + n.pos = pos + return n +} + +func (n *ArrayType) String() string { return fmt.Sprint(n) } +func (n *ArrayType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ArrayType) RawCopy() Node { c := *n; return &c } + +func (n *ArrayType) DeepCopy(pos src.XPos) Node { + if n.op == OTYPE { + // Can't change types and no node references left. + return n + } + return NewArrayType(n.posOr(pos), DeepCopy(pos, n.Len), DeepCopy(pos, n.Elem)) +} + +func (n *ArrayType) SetOTYPE(t *types.Type) { + n.setOTYPE(t, n) + n.Len = nil + n.Elem = nil +} + +// A typeNode is a Node wrapper for type t. +type typeNode struct { + miniNode + typ *types.Type +} + +func newTypeNode(pos src.XPos, typ *types.Type) *typeNode { + n := &typeNode{typ: typ} + n.pos = pos + n.op = OTYPE + return n +} + +func (n *typeNode) String() string { return fmt.Sprint(n) } +func (n *typeNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *typeNode) RawCopy() Node { c := *n; return &c } +func (n *typeNode) Type() *types.Type { return n.typ } +func (n *typeNode) Sym() *types.Sym { return n.typ.Sym } +func (n *typeNode) CanBeNtype() {} + +// TypeNode returns the Node representing the type t. +func TypeNode(t *types.Type) Ntype { return TypeNodeAt(src.NoXPos, t) } -func TypeNodeAt(pos src.XPos, t *types.Type) Node { - // if we copied another type with *t = *u - // then t->nod might be out of date, so - // check t->nod->type too - if AsNode(t.Nod) == nil || AsNode(t.Nod).Type() != t { - t.Nod = NodAt(pos, OTYPE, nil, nil) - AsNode(t.Nod).SetType(t) - AsNode(t.Nod).SetSym(t.Sym) +// TypeNodeAt returns the Node representing the type t. +// If the node must be created, TypeNodeAt uses the position pos. +// TODO(rsc): Does anyone actually use position on these type nodes? +func TypeNodeAt(pos src.XPos, t *types.Type) Ntype { + // If we copied another type with *t = *u, + // then t.Nod might be out of date, so check t.Nod.Type() too. + n := AsNode(t.Nod) + if n == nil || n.Type() != t { + n := newTypeNode(pos, t) // t.Sym may be nil + t.Nod = n + return n } - - return AsNode(t.Nod) + return n.(Ntype) } From ae1a3378092e25c7a7aa0100c2e29397f7bc2798 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 29 Nov 2020 08:58:39 -0500 Subject: [PATCH 031/212] [dev.regabi] cmd/compile: remove ODCLFIELD and ODDD ops These are plain data now, not nodes (see previous CL). The opcode deletions are not safe for toolstash -cmp, so they are split into a separate CL. Change-Id: Icef8a01e190195a7539a35b92f42835d823e314a Reviewed-on: https://go-review.googlesource.com/c/go/+/274104 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/node.go | 2 - src/cmd/compile/internal/ir/op_string.go | 218 +++++++++++------------ 2 files changed, 108 insertions(+), 112 deletions(-) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 74557236cc..2850704ae1 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -457,7 +457,6 @@ const ( // Used during parsing but don't last. ODCLFUNC // func f() or func (r) f() - ODCLFIELD // UNUSED: TODO(rsc): Delete. ODCLCONST // const pi = 3.14 ODCLTYPE // type Int int or type Int = int @@ -580,7 +579,6 @@ const ( OTSLICE // []int // misc - ODDD // UNUSED; TODO(rsc): Delete. OINLCALL // intermediary representation of an inlined call. OEFACE // itable and data words of an empty-interface value. OITAB // itable word of an interface value. diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index faec164c7b..eefdc0ee59 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -56,119 +56,117 @@ func _() { _ = x[OCOPY-45] _ = x[ODCL-46] _ = x[ODCLFUNC-47] - _ = x[ODCLFIELD-48] - _ = x[ODCLCONST-49] - _ = x[ODCLTYPE-50] - _ = x[ODELETE-51] - _ = x[ODOT-52] - _ = x[ODOTPTR-53] - _ = x[ODOTMETH-54] - _ = x[ODOTINTER-55] - _ = x[OXDOT-56] - _ = x[ODOTTYPE-57] - _ = x[ODOTTYPE2-58] - _ = x[OEQ-59] - _ = x[ONE-60] - _ = x[OLT-61] - _ = x[OLE-62] - _ = x[OGE-63] - _ = x[OGT-64] - _ = x[ODEREF-65] - _ = x[OINDEX-66] - _ = x[OINDEXMAP-67] - _ = x[OKEY-68] - _ = x[OSTRUCTKEY-69] - _ = x[OLEN-70] - _ = x[OMAKE-71] - _ = x[OMAKECHAN-72] - _ = x[OMAKEMAP-73] - _ = x[OMAKESLICE-74] - _ = x[OMAKESLICECOPY-75] - _ = x[OMUL-76] - _ = x[ODIV-77] - _ = x[OMOD-78] - _ = x[OLSH-79] - _ = x[ORSH-80] - _ = x[OAND-81] - _ = x[OANDNOT-82] - _ = x[ONEW-83] - _ = x[ONEWOBJ-84] - _ = x[ONOT-85] - _ = x[OBITNOT-86] - _ = x[OPLUS-87] - _ = x[ONEG-88] - _ = x[OOROR-89] - _ = x[OPANIC-90] - _ = x[OPRINT-91] - _ = x[OPRINTN-92] - _ = x[OPAREN-93] - _ = x[OSEND-94] - _ = x[OSLICE-95] - _ = x[OSLICEARR-96] - _ = x[OSLICESTR-97] - _ = x[OSLICE3-98] - _ = x[OSLICE3ARR-99] - _ = x[OSLICEHEADER-100] - _ = x[ORECOVER-101] - _ = x[ORECV-102] - _ = x[ORUNESTR-103] - _ = x[OSELRECV-104] - _ = x[OSELRECV2-105] - _ = x[OIOTA-106] - _ = x[OREAL-107] - _ = x[OIMAG-108] - _ = x[OCOMPLEX-109] - _ = x[OALIGNOF-110] - _ = x[OOFFSETOF-111] - _ = x[OSIZEOF-112] - _ = x[OMETHEXPR-113] - _ = x[OBLOCK-114] - _ = x[OBREAK-115] - _ = x[OCASE-116] - _ = x[OCONTINUE-117] - _ = x[ODEFER-118] - _ = x[OEMPTY-119] - _ = x[OFALL-120] - _ = x[OFOR-121] - _ = x[OFORUNTIL-122] - _ = x[OGOTO-123] - _ = x[OIF-124] - _ = x[OLABEL-125] - _ = x[OGO-126] - _ = x[ORANGE-127] - _ = x[ORETURN-128] - _ = x[OSELECT-129] - _ = x[OSWITCH-130] - _ = x[OTYPESW-131] - _ = x[OTCHAN-132] - _ = x[OTMAP-133] - _ = x[OTSTRUCT-134] - _ = x[OTINTER-135] - _ = x[OTFUNC-136] - _ = x[OTARRAY-137] - _ = x[OTSLICE-138] - _ = x[ODDD-139] - _ = x[OINLCALL-140] - _ = x[OEFACE-141] - _ = x[OITAB-142] - _ = x[OIDATA-143] - _ = x[OSPTR-144] - _ = x[OCLOSUREREAD-145] - _ = x[OCFUNC-146] - _ = x[OCHECKNIL-147] - _ = x[OVARDEF-148] - _ = x[OVARKILL-149] - _ = x[OVARLIVE-150] - _ = x[ORESULT-151] - _ = x[OINLMARK-152] - _ = x[ORETJMP-153] - _ = x[OGETG-154] - _ = x[OEND-155] + _ = x[ODCLCONST-48] + _ = x[ODCLTYPE-49] + _ = x[ODELETE-50] + _ = x[ODOT-51] + _ = x[ODOTPTR-52] + _ = x[ODOTMETH-53] + _ = x[ODOTINTER-54] + _ = x[OXDOT-55] + _ = x[ODOTTYPE-56] + _ = x[ODOTTYPE2-57] + _ = x[OEQ-58] + _ = x[ONE-59] + _ = x[OLT-60] + _ = x[OLE-61] + _ = x[OGE-62] + _ = x[OGT-63] + _ = x[ODEREF-64] + _ = x[OINDEX-65] + _ = x[OINDEXMAP-66] + _ = x[OKEY-67] + _ = x[OSTRUCTKEY-68] + _ = x[OLEN-69] + _ = x[OMAKE-70] + _ = x[OMAKECHAN-71] + _ = x[OMAKEMAP-72] + _ = x[OMAKESLICE-73] + _ = x[OMAKESLICECOPY-74] + _ = x[OMUL-75] + _ = x[ODIV-76] + _ = x[OMOD-77] + _ = x[OLSH-78] + _ = x[ORSH-79] + _ = x[OAND-80] + _ = x[OANDNOT-81] + _ = x[ONEW-82] + _ = x[ONEWOBJ-83] + _ = x[ONOT-84] + _ = x[OBITNOT-85] + _ = x[OPLUS-86] + _ = x[ONEG-87] + _ = x[OOROR-88] + _ = x[OPANIC-89] + _ = x[OPRINT-90] + _ = x[OPRINTN-91] + _ = x[OPAREN-92] + _ = x[OSEND-93] + _ = x[OSLICE-94] + _ = x[OSLICEARR-95] + _ = x[OSLICESTR-96] + _ = x[OSLICE3-97] + _ = x[OSLICE3ARR-98] + _ = x[OSLICEHEADER-99] + _ = x[ORECOVER-100] + _ = x[ORECV-101] + _ = x[ORUNESTR-102] + _ = x[OSELRECV-103] + _ = x[OSELRECV2-104] + _ = x[OIOTA-105] + _ = x[OREAL-106] + _ = x[OIMAG-107] + _ = x[OCOMPLEX-108] + _ = x[OALIGNOF-109] + _ = x[OOFFSETOF-110] + _ = x[OSIZEOF-111] + _ = x[OMETHEXPR-112] + _ = x[OBLOCK-113] + _ = x[OBREAK-114] + _ = x[OCASE-115] + _ = x[OCONTINUE-116] + _ = x[ODEFER-117] + _ = x[OEMPTY-118] + _ = x[OFALL-119] + _ = x[OFOR-120] + _ = x[OFORUNTIL-121] + _ = x[OGOTO-122] + _ = x[OIF-123] + _ = x[OLABEL-124] + _ = x[OGO-125] + _ = x[ORANGE-126] + _ = x[ORETURN-127] + _ = x[OSELECT-128] + _ = x[OSWITCH-129] + _ = x[OTYPESW-130] + _ = x[OTCHAN-131] + _ = x[OTMAP-132] + _ = x[OTSTRUCT-133] + _ = x[OTINTER-134] + _ = x[OTFUNC-135] + _ = x[OTARRAY-136] + _ = x[OTSLICE-137] + _ = x[OINLCALL-138] + _ = x[OEFACE-139] + _ = x[OITAB-140] + _ = x[OIDATA-141] + _ = x[OSPTR-142] + _ = x[OCLOSUREREAD-143] + _ = x[OCFUNC-144] + _ = x[OCHECKNIL-145] + _ = x[OVARDEF-146] + _ = x[OVARKILL-147] + _ = x[OVARLIVE-148] + _ = x[ORESULT-149] + _ = x[OINLMARK-150] + _ = x[ORETJMP-151] + _ = x[OGETG-152] + _ = x[OEND-153] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEDDDINLCALLEFACEITABIDATASPTRCLOSUREREADCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCLOSUREREADCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 310, 317, 323, 326, 332, 339, 347, 351, 358, 366, 368, 370, 372, 374, 376, 378, 383, 388, 396, 399, 408, 411, 415, 423, 430, 439, 452, 455, 458, 461, 464, 467, 470, 476, 479, 485, 488, 494, 498, 501, 505, 510, 515, 521, 526, 530, 535, 543, 551, 557, 566, 577, 584, 588, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 658, 663, 668, 672, 680, 685, 690, 694, 697, 705, 709, 711, 716, 718, 723, 729, 735, 741, 747, 752, 756, 763, 769, 774, 780, 786, 789, 796, 801, 805, 810, 814, 825, 830, 838, 844, 851, 858, 864, 871, 877, 881, 884} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 309, 315, 318, 324, 331, 339, 343, 350, 358, 360, 362, 364, 366, 368, 370, 375, 380, 388, 391, 400, 403, 407, 415, 422, 431, 444, 447, 450, 453, 456, 459, 462, 468, 471, 477, 480, 486, 490, 493, 497, 502, 507, 513, 518, 522, 527, 535, 543, 549, 558, 569, 576, 580, 587, 594, 602, 606, 610, 614, 621, 628, 636, 642, 650, 655, 660, 664, 672, 677, 682, 686, 689, 697, 701, 703, 708, 710, 715, 721, 727, 733, 739, 744, 748, 755, 761, 766, 772, 778, 785, 790, 794, 799, 803, 814, 819, 827, 833, 840, 847, 853, 860, 866, 870, 873} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { From d6abf298cf1ef56dc8cbec2ee9a18c071bb6eb3c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 28 Nov 2020 17:51:18 -0800 Subject: [PATCH 032/212] test: recognize new gofrontend error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As of https://golang.org/cl/273886: fixedbugs/bug340.go:15:18: error: reference to method ‘x’ in interface with no methods For golang/go#10700 Change-Id: Id29eb0e34bbb524117614229c4c27cfd17dae286 Reviewed-on: https://go-review.googlesource.com/c/go/+/273887 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- test/fixedbugs/bug340.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixedbugs/bug340.go b/test/fixedbugs/bug340.go index 118bbacc22..8c543c98d9 100644 --- a/test/fixedbugs/bug340.go +++ b/test/fixedbugs/bug340.go @@ -12,6 +12,6 @@ func main() { var x interface{} switch t := x.(type) { case 0: // ERROR "type" - t.x = 1 // ERROR "type interface \{\}|reference to undefined field or method" + t.x = 1 // ERROR "type interface \{\}|reference to undefined field or method|interface with no methods" } } From a45e12fd4bd2cc4d5970f374499b603bfb793891 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 28 Nov 2020 18:14:38 -0800 Subject: [PATCH 033/212] test: recognize gofrontend error messages shift1.go:76:16: error: shift of non-integer operand shift1.go:77:16: error: shift of non-integer operand Change-Id: I48584c0b01f9f6912a93b5f9bba55b5803fbeced Reviewed-on: https://go-review.googlesource.com/c/go/+/273888 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- test/shift1.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/shift1.go b/test/shift1.go index df0c032cd5..d6a6c38839 100644 --- a/test/shift1.go +++ b/test/shift1.go @@ -73,8 +73,8 @@ func _() { // non constants arguments trigger a different path f2 := 1.2 s2 := "hi" - _ = f2 << 2 // ERROR "shift of type float64" - _ = s2 << 2 // ERROR "shift of type string" + _ = f2 << 2 // ERROR "shift of type float64|non-integer" + _ = s2 << 2 // ERROR "shift of type string|non-integer" } // shifts in comparisons w/ untyped operands From 848dff6dda4d38d3d2e9ab128954f50d085d9313 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 28 Nov 2020 19:10:57 -0800 Subject: [PATCH 034/212] test: update gofrontend expected errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This matches the error messages after CL 273890. syntax/semi4.go:11:9: error: unexpected semicolon or newline, expecting ‘{’ after for clause syntax/semi4.go:10:13: error: reference to undefined name ‘x’ syntax/semi4.go:12:17: error: reference to undefined name ‘z’ Change-Id: Ic88ff6e27d50bf70f5b2114383b84c42c0682f39 Reviewed-on: https://go-review.googlesource.com/c/go/+/273891 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- test/syntax/semi4.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/syntax/semi4.go b/test/syntax/semi4.go index f21431b3f5..08c354751b 100644 --- a/test/syntax/semi4.go +++ b/test/syntax/semi4.go @@ -8,5 +8,5 @@ package main func main() { for x // GCCGO_ERROR "undefined" - { // ERROR "unexpected {, expecting for loop condition" - z + { // ERROR "unexpected {, expecting for loop condition|expecting .*{.* after for clause" + z // GCCGO_ERROR "undefined" From 7b192f33cf8e1391769353687e5b698d9f677109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Mon, 23 Nov 2020 05:47:51 +0000 Subject: [PATCH 035/212] cmd/go: remove trailing whitespace from test script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Noticed while skimming through recent master commits. Change-Id: I42a99ea7d71c05fc5b6107627105375a21920f5e Reviewed-on: https://go-review.googlesource.com/c/go/+/271990 Trust: Daniel Martí Reviewed-by: Jay Conrod Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/testdata/script/mod_gonoproxy.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/mod_gonoproxy.txt b/src/cmd/go/testdata/script/mod_gonoproxy.txt index 546605da21..204786969f 100644 --- a/src/cmd/go/testdata/script/mod_gonoproxy.txt +++ b/src/cmd/go/testdata/script/mod_gonoproxy.txt @@ -21,7 +21,7 @@ go get -d rsc.io/quote # Download .info files needed for 'go list -m all' later. # TODO(#42723): either 'go list -m' should not read these files, # or 'go get' and 'go mod tidy' should download them. -go list -m all +go list -m all stdout '^golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c$' # When GOPROXY is not empty but contains no entries, an error should be reported. From 4f42a9b76b2ca2c261a4afec986b9518a61626ee Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Sat, 21 Nov 2020 14:48:26 +0800 Subject: [PATCH 036/212] net: add note about disabling loopback in ListenMulticastUDP() Fixes #41752 Change-Id: I83520d2303e5fd2e5f6329f092b40e73c13771a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/271908 Reviewed-by: Ian Lance Taylor Trust: Dmitri Shuralyov --- src/net/udpsock.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/net/udpsock.go b/src/net/udpsock.go index ec2bcfa607..571e099abd 100644 --- a/src/net/udpsock.go +++ b/src/net/udpsock.go @@ -259,6 +259,9 @@ func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error) { // ListenMulticastUDP is just for convenience of simple, small // applications. There are golang.org/x/net/ipv4 and // golang.org/x/net/ipv6 packages for general purpose uses. +// +// Note that ListenMulticastUDP will set the IP_MULTICAST_LOOP socket option +// to 0 under IPPROTO_IP, to disable loopback of multicast packets. func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) { switch network { case "udp", "udp4", "udp6": From d2b436d95d99cb3ff587bf0d2e893a8d027f8292 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 30 Nov 2020 15:46:33 -0500 Subject: [PATCH 037/212] cmd/go: fix infinite loop in modload.keepSums Fixes #42891 Change-Id: I0cce4204a1c4959b896188a2ab3719c0507f95e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/274172 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Michael Matloob Reviewed-by: Bryan C. Mills Trust: Jay Conrod --- src/cmd/go/internal/modload/init.go | 2 +- .../go/testdata/script/mod_import_issue42891.txt | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/testdata/script/mod_import_issue42891.txt diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index a9b77c82b3..1c31a5f90a 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -1018,7 +1018,7 @@ func keepSums(addDirect bool) map[module.Version]bool { } } for _, pkg := range loaded.pkgs { - if pkg.testOf != nil || pkg.inStd { + if pkg.testOf != nil || pkg.inStd || module.CheckImportPath(pkg.path) != nil { continue } for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { diff --git a/src/cmd/go/testdata/script/mod_import_issue42891.txt b/src/cmd/go/testdata/script/mod_import_issue42891.txt new file mode 100644 index 0000000000..a78cab29ba --- /dev/null +++ b/src/cmd/go/testdata/script/mod_import_issue42891.txt @@ -0,0 +1,14 @@ +# If an import declaration is an absolute path, most commands should report +# an error instead of going into an infinite loop. +# Verifies golang.org/issue/42891. +go list . +stdout '^m$' + +-- go.mod -- +module m + +go 1.16 +-- m.go -- +package m + +import "/" From c6de5d8d1f56465869a9271753796da35c60f3e6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 30 Nov 2020 13:50:05 -0800 Subject: [PATCH 038/212] [dev.regabi] cmd/compile: simplify export data representation of nil The handling of ONIL and Orig has been a mess for a while, and dates back to how fmt.go used to print out typed nils. That hasn't applied for a while, but we've kept dragging it along to appease toolstash with the intention of someday finally removing it. Today is that day. Change-Id: I9a441628e53068ab1993cd2b67b977574d8117b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/274212 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Russ Cox TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/iexport.go | 6 +----- src/cmd/compile/internal/gc/iimport.go | 17 ++++++++--------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index c9f5d0c85c..f19acb8bc2 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -1201,11 +1201,7 @@ func (w *exportWriter) expr(n ir.Node) { if !n.Type().HasNil() { base.Fatalf("unexpected type for nil: %v", n.Type()) } - if orig := ir.Orig(n); orig != nil && orig != n { - w.expr(orig) - break - } - w.op(ir.OLITERAL) + w.op(ir.ONIL) w.pos(n.Pos()) w.typ(n.Type()) diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index c219b70e0f..57c5e62182 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -809,20 +809,19 @@ func (r *importReader) node() ir.Node { // case OPAREN: // unreachable - unpacked by exporter - // case ONIL: - // unreachable - mapped to OLITERAL + case ir.ONIL: + pos := r.pos() + typ := r.typ() + + n := npos(pos, nodnil()) + n.SetType(typ) + return n case ir.OLITERAL: pos := r.pos() typ := r.typ() - var n ir.Node - if typ.HasNil() { - n = nodnil() - } else { - n = ir.NewLiteral(r.value(typ)) - } - n = npos(pos, n) + n := npos(pos, ir.NewLiteral(r.value(typ))) n.SetType(typ) return n From 7f688d18c0ae6df3e895d21799b8ece7d5941293 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Fri, 27 Nov 2020 00:42:41 -0500 Subject: [PATCH 039/212] runtime: mlock signal stack on macOS/ARM64 Apparently, the macOS ARM64 kernel has a bug where when a signal arrives and the signal stack is not currently faulted in, it may kill the program with a SIGILL. Work around it by mlock the signal stacks. Fixes #42774. Change-Id: I99a4b3fdb6d8af1c945725ddc2c25568d81c510a Reviewed-on: https://go-review.googlesource.com/c/go/+/273686 Trust: Cherry Zhang Reviewed-by: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot --- src/runtime/os_darwin.go | 6 ++++++ src/runtime/sys_darwin.go | 8 ++++++++ src/runtime/sys_darwin_amd64.s | 3 +++ src/runtime/sys_darwin_arm64.s | 6 ++++++ 4 files changed, 23 insertions(+) diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index 3f5bb7cf96..52f3cd1fef 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -283,6 +283,12 @@ func libpreinit() { func mpreinit(mp *m) { mp.gsignal = malg(32 * 1024) // OS X wants >= 8K mp.gsignal.m = mp + if GOOS == "darwin" && GOARCH == "arm64" { + // mlock the signal stack to work around a kernel bug where it may + // SIGILL when the signal stack is not faulted in while a signal + // arrives. See issue 42774. + mlock(unsafe.Pointer(mp.gsignal.stack.hi-physPageSize), physPageSize) + } } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index a7983be2ef..c63ba8c6cd 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -226,6 +226,13 @@ func madvise(addr unsafe.Pointer, n uintptr, flags int32) { } func madvise_trampoline() +//go:nosplit +//go:cgo_unsafe_args +func mlock(addr unsafe.Pointer, n uintptr) { + libcCall(unsafe.Pointer(funcPC(mlock_trampoline)), unsafe.Pointer(&addr)) +} +func mlock_trampoline() + //go:nosplit //go:cgo_unsafe_args func read(fd int32, p unsafe.Pointer, n int32) int32 { @@ -465,6 +472,7 @@ func setNonblock(fd int32) { //go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_error __error "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_usleep usleep "/usr/lib/libSystem.B.dylib" diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index 129e1e1a96..9b5b23901d 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -105,6 +105,9 @@ TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0 POPQ BP RET +TEXT runtime·mlock_trampoline(SB), NOSPLIT, $0 + UNDEF // unimplemented + GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size) TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0 diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s index 88cdb281d4..9d4d116c50 100644 --- a/src/runtime/sys_darwin_arm64.s +++ b/src/runtime/sys_darwin_arm64.s @@ -120,6 +120,12 @@ TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0 BL libc_madvise(SB) RET +TEXT runtime·mlock_trampoline(SB),NOSPLIT,$0 + MOVD 8(R0), R1 // arg 2 len + MOVD 0(R0), R0 // arg 1 addr + BL libc_mlock(SB) + RET + TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0 MOVD 8(R0), R1 // arg 2 new MOVD 16(R0), R2 // arg 3 old From 7c9b6b1ca249c14d358075da9678cd1c20041b21 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 28 Nov 2020 15:28:18 -0500 Subject: [PATCH 040/212] [dev.regabi] cmd/compile: clean up in preparation for statement Nodes Using statement nodes restricts the set of valid SetOp operations, because you can't SetOp across representation. Rewrite various code to avoid crossing those as-yet-unintroduced boundaries. In particular, code like x, y := v.(T) x, y := f() x, y := m[k] x, y := <-c starts out with Op = OAS2, and then it turns into a specific Op OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, and then later in walk is lowered to an OAS2 again. In the middle, the specific forms move the right-hand side from n.Rlist().First() to n.Right(), and then the conversion to OAS2 moves it back. This is unnecessary and makes it hard for these all to share an underlying Node implementation. This CL changes these specific forms to leave the right-hand side in n.Rlist().First(). Similarly, OSELRECV2 is really just a temporary form of OAS2. This CL changes it to use same fields too. Finally, this CL fixes the printing of OAS2 nodes in ir/fmt.go, which formerly printed n.Right() instead of n.Rlist(). This results in a (correct!) update to cmd/compile/internal/logopt's expected output: ~R0 = becomes ~R0 = &y.b. Passes buildall w/ toolstash -cmp. Change-Id: I164aa2e17dc55bfb292024de53d7d250192ad64a Reviewed-on: https://go-review.googlesource.com/c/go/+/274105 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/escape.go | 17 +-- src/cmd/compile/internal/gc/iexport.go | 8 +- src/cmd/compile/internal/gc/initorder.go | 2 +- src/cmd/compile/internal/gc/inl.go | 74 +++++---- src/cmd/compile/internal/gc/noder.go | 19 +-- src/cmd/compile/internal/gc/order.go | 140 +++++++++--------- src/cmd/compile/internal/gc/range.go | 102 ++++++------- src/cmd/compile/internal/gc/select.go | 99 +++++++------ src/cmd/compile/internal/gc/ssa.go | 10 +- src/cmd/compile/internal/gc/typecheck.go | 4 - src/cmd/compile/internal/gc/universe.go | 1 + src/cmd/compile/internal/gc/walk.go | 19 +-- src/cmd/compile/internal/ir/fmt.go | 9 +- src/cmd/compile/internal/ir/node.go | 4 +- .../compile/internal/logopt/logopt_test.go | 4 +- 15 files changed, 243 insertions(+), 269 deletions(-) diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 4cbc5d3851..f2fff02959 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -394,8 +394,8 @@ func (e *Escape) stmt(n ir.Node) { case ir.OSELRECV: e.assign(n.Left(), n.Right(), "selrecv", n) case ir.OSELRECV2: - e.assign(n.Left(), n.Right(), "selrecv", n) - e.assign(n.List().First(), nil, "selrecv", n) + e.assign(n.List().First(), n.Rlist().First(), "selrecv", n) + e.assign(n.List().Second(), nil, "selrecv", n) case ir.ORECV: // TODO(mdempsky): Consider e.discard(n.Left). e.exprSkipInit(e.discardHole(), n) // already visited n.Ninit @@ -412,18 +412,18 @@ func (e *Escape) stmt(n ir.Node) { } case ir.OAS2DOTTYPE: // v, ok = x.(type) - e.assign(n.List().First(), n.Right(), "assign-pair-dot-type", n) + e.assign(n.List().First(), n.Rlist().First(), "assign-pair-dot-type", n) e.assign(n.List().Second(), nil, "assign-pair-dot-type", n) case ir.OAS2MAPR: // v, ok = m[k] - e.assign(n.List().First(), n.Right(), "assign-pair-mapr", n) + e.assign(n.List().First(), n.Rlist().First(), "assign-pair-mapr", n) e.assign(n.List().Second(), nil, "assign-pair-mapr", n) case ir.OAS2RECV: // v, ok = <-ch - e.assign(n.List().First(), n.Right(), "assign-pair-receive", n) + e.assign(n.List().First(), n.Rlist().First(), "assign-pair-receive", n) e.assign(n.List().Second(), nil, "assign-pair-receive", n) case ir.OAS2FUNC: - e.stmts(n.Right().Init()) - e.call(e.addrs(n.List()), n.Right(), nil) + e.stmts(n.Rlist().First().Init()) + e.call(e.addrs(n.List()), n.Rlist().First(), nil) case ir.ORETURN: results := e.curfn.Type().Results().FieldSlice() for i, v := range n.List().Slice() { @@ -709,8 +709,7 @@ func (e *Escape) discards(l ir.Nodes) { // that represents storing into the represented location. func (e *Escape) addr(n ir.Node) EscHole { if n == nil || ir.IsBlank(n) { - // Can happen at least in OSELRECV. - // TODO(mdempsky): Anywhere else? + // Can happen in select case, range, maybe others. return e.discardHole() } diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index f19acb8bc2..d6c50c7285 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -1076,18 +1076,12 @@ func (w *exportWriter) stmt(n ir.Node) { w.expr(n.Right()) } - case ir.OAS2: + case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: w.op(ir.OAS2) w.pos(n.Pos()) w.exprList(n.List()) w.exprList(n.Rlist()) - case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: - w.op(ir.OAS2) - w.pos(n.Pos()) - w.exprList(n.List()) - w.exprList(ir.AsNodes([]ir.Node{n.Right()})) - case ir.ORETURN: w.op(ir.ORETURN) w.pos(n.Pos()) diff --git a/src/cmd/compile/internal/gc/initorder.go b/src/cmd/compile/internal/gc/initorder.go index ea3d74d5ba..87a78ae053 100644 --- a/src/cmd/compile/internal/gc/initorder.go +++ b/src/cmd/compile/internal/gc/initorder.go @@ -256,7 +256,7 @@ func collectDeps(n ir.Node, transitive bool) ir.NodeSet { case ir.OAS: d.inspect(n.Right()) case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: - d.inspect(n.Right()) + d.inspect(n.Rlist().First()) case ir.ODCLFUNC: d.inspectList(n.Body()) default: diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index bbbffebf5c..97ecb9559b 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -520,14 +520,11 @@ func inlcalls(fn *ir.Func) { } // Turn an OINLCALL into a statement. -func inlconv2stmt(n ir.Node) { - n.SetOp(ir.OBLOCK) - - // n->ninit stays - n.PtrList().Set(n.Body().Slice()) - - n.PtrBody().Set(nil) - n.PtrRlist().Set(nil) +func inlconv2stmt(inlcall ir.Node) ir.Node { + n := ir.NodAt(inlcall.Pos(), ir.OBLOCK, nil, nil) + n.SetList(inlcall.Body()) + n.SetInit(inlcall.Init()) + return n } // Turn an OINLCALL into a single valued expression. @@ -600,9 +597,10 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { lno := setlineno(n) inlnodelist(n.Init(), maxCost, inlMap) - for _, n1 := range n.Init().Slice() { + init := n.Init().Slice() + for i, n1 := range init { if n1.Op() == ir.OINLCALL { - inlconv2stmt(n1) + init[i] = inlconv2stmt(n1) } } @@ -614,50 +612,49 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { n.SetRight(inlnode(n.Right(), maxCost, inlMap)) if n.Right() != nil && n.Right().Op() == ir.OINLCALL { if n.Op() == ir.OFOR || n.Op() == ir.OFORUNTIL { - inlconv2stmt(n.Right()) - } else if n.Op() == ir.OAS2FUNC { - n.PtrRlist().Set(inlconv2list(n.Right())) - n.SetRight(nil) - n.SetOp(ir.OAS2) - n.SetTypecheck(0) - n = typecheck(n, ctxStmt) + n.SetRight(inlconv2stmt(n.Right())) } else { n.SetRight(inlconv2expr(n.Right())) } } inlnodelist(n.List(), maxCost, inlMap) + s := n.List().Slice() + convert := inlconv2expr if n.Op() == ir.OBLOCK { - for _, n2 := range n.List().Slice() { - if n2.Op() == ir.OINLCALL { - inlconv2stmt(n2) - } - } - } else { - s := n.List().Slice() - for i1, n1 := range s { - if n1 != nil && n1.Op() == ir.OINLCALL { - s[i1] = inlconv2expr(s[i1]) - } + convert = inlconv2stmt + } + for i, n1 := range s { + if n1 != nil && n1.Op() == ir.OINLCALL { + s[i] = convert(n1) } } inlnodelist(n.Rlist(), maxCost, inlMap) - s := n.Rlist().Slice() - for i1, n1 := range s { + + if n.Op() == ir.OAS2FUNC && n.Rlist().First().Op() == ir.OINLCALL { + n.PtrRlist().Set(inlconv2list(n.Rlist().First())) + n.SetOp(ir.OAS2) + n.SetTypecheck(0) + n = typecheck(n, ctxStmt) + } + + s = n.Rlist().Slice() + for i, n1 := range s { if n1.Op() == ir.OINLCALL { if n.Op() == ir.OIF { - inlconv2stmt(n1) + s[i] = inlconv2stmt(n1) } else { - s[i1] = inlconv2expr(s[i1]) + s[i] = inlconv2expr(n1) } } } inlnodelist(n.Body(), maxCost, inlMap) - for _, n := range n.Body().Slice() { - if n.Op() == ir.OINLCALL { - inlconv2stmt(n) + s = n.Body().Slice() + for i, n1 := range s { + if n1.Op() == ir.OINLCALL { + s[i] = inlconv2stmt(n1) } } @@ -1200,9 +1197,10 @@ func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool) // and each use must redo the inlining. // luckily these are small. inlnodelist(call.Body(), maxCost, inlMap) - for _, n := range call.Body().Slice() { - if n.Op() == ir.OINLCALL { - inlconv2stmt(n) + s := call.Body().Slice() + for i, n1 := range s { + if n1.Op() == ir.OINLCALL { + s[i] = inlconv2stmt(n1) } } diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index e6c78d1afb..98a09f4006 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -1001,20 +1001,17 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node { return n } - n := p.nod(stmt, ir.OAS, nil, nil) // assume common case - rhs := p.exprList(stmt.Rhs) - lhs := p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def) - - if len(lhs) == 1 && len(rhs) == 1 { - // common case - n.SetLeft(lhs[0]) - n.SetRight(rhs[0]) - } else { - n.SetOp(ir.OAS2) - n.PtrList().Set(lhs) + if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 { + n := p.nod(stmt, ir.OAS2, nil, nil) + n.PtrList().Set(p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def)) n.PtrRlist().Set(rhs) + return n } + + n := p.nod(stmt, ir.OAS, nil, nil) + n.SetLeft(p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def)[0]) + n.SetRight(rhs[0]) return n case *syntax.BranchStmt: diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index d4db7be911..66e279d85f 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -103,7 +103,11 @@ func (o *Order) newTemp(t *types.Type, clear bool) ir.Node { // (The other candidate would be map access, but map access // returns a pointer to the result data instead of taking a pointer // to be filled in.) +// TODO(rsc): t == n.Type() always; remove parameter. func (o *Order) copyExpr(n ir.Node, t *types.Type, clear bool) ir.Node { + if t != n.Type() { + panic("copyExpr") + } v := o.newTemp(t, clear) a := ir.Nod(ir.OAS, v, n) a = typecheck(a, ctxStmt) @@ -606,23 +610,19 @@ func (o *Order) stmt(n ir.Node) { // that we can ensure that if op panics // because r is zero, the panic happens before // the map assignment. - - n.SetLeft(o.safeExpr(n.Left())) - - // TODO(rsc): Why is this DeepCopy? - // We should know enough about the form here - // to do something more provably shallower. - l := ir.DeepCopy(src.NoXPos, n.Left()) - if l.Op() == ir.OINDEXMAP { - l.SetIndexMapLValue(false) + // DeepCopy is a big hammer here, but safeExpr + // makes sure there is nothing too deep being copied. + l1 := o.safeExpr(n.Left()) + l2 := ir.DeepCopy(src.NoXPos, l1) + if l1.Op() == ir.OINDEXMAP { + l2.SetIndexMapLValue(false) } - l = o.copyExpr(l, n.Left().Type(), false) - n.SetRight(ir.Nod(n.SubOp(), l, n.Right())) - n.SetRight(typecheck(n.Right(), ctxExpr)) - n.SetRight(o.expr(n.Right(), nil)) - - n.SetOp(ir.OAS) - n.ResetAux() + l2 = o.copyExpr(l2, l2.Type(), false) + r := ir.NodAt(n.Pos(), n.SubOp(), l2, n.Right()) + r = typecheck(r, ctxExpr) + r = o.expr(r, nil) + n = ir.NodAt(n.Pos(), ir.OAS, l1, r) + n = typecheck(n, ctxStmt) } o.mapAssign(n) @@ -639,8 +639,8 @@ func (o *Order) stmt(n ir.Node) { case ir.OAS2FUNC: t := o.markTemp() o.exprList(n.List()) - o.init(n.Right()) - o.call(n.Right()) + o.init(n.Rlist().First()) + o.call(n.Rlist().First()) o.as2(n) o.cleanTemp(t) @@ -654,7 +654,7 @@ func (o *Order) stmt(n ir.Node) { t := o.markTemp() o.exprList(n.List()) - switch r := n.Right(); r.Op() { + switch r := n.Rlist().First(); r.Op() { case ir.ODOTTYPE2, ir.ORECV: r.SetLeft(o.expr(r.Left(), nil)) case ir.OINDEXMAP: @@ -866,38 +866,39 @@ func (o *Order) stmt(n ir.Node) { ir.Dump("select case", r) base.Fatalf("unknown op in select %v", r.Op()) - // If this is case x := <-ch or case x, y := <-ch, the case has - // the ODCL nodes to declare x and y. We want to delay that - // declaration (and possible allocation) until inside the case body. - // Delete the ODCL nodes here and recreate them inside the body below. case ir.OSELRECV, ir.OSELRECV2: - if r.Colas() { - i := 0 - if r.Init().Len() != 0 && r.Init().First().Op() == ir.ODCL && r.Init().First().Left() == r.Left() { - i++ - } - if i < r.Init().Len() && r.Init().Index(i).Op() == ir.ODCL && r.List().Len() != 0 && r.Init().Index(i).Left() == r.List().First() { - i++ - } - if i >= r.Init().Len() { - r.PtrInit().Set(nil) - } + var dst, ok, recv ir.Node + if r.Op() == ir.OSELRECV { + // case x = <-c + // case <-c (dst is ir.BlankNode) + dst, ok, recv = r.Left(), ir.BlankNode, r.Right() + } else { + // case x, ok = <-c + dst, ok, recv = r.List().First(), r.List().Second(), r.Rlist().First() } + // If this is case x := <-ch or case x, y := <-ch, the case has + // the ODCL nodes to declare x and y. We want to delay that + // declaration (and possible allocation) until inside the case body. + // Delete the ODCL nodes here and recreate them inside the body below. + if r.Colas() { + init := r.Init().Slice() + if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].Left() == dst { + init = init[1:] + } + if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].Left() == ok { + init = init[1:] + } + r.PtrInit().Set(init) + } if r.Init().Len() != 0 { ir.DumpList("ninit", r.Init()) base.Fatalf("ninit on select recv") } - // case x = <-c - // case x, ok = <-c - // r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c. - // r->left == N means 'case <-c'. - // c is always evaluated; x and ok are only evaluated when assigned. - r.Right().SetLeft(o.expr(r.Right().Left(), nil)) - - if r.Right().Left().Op() != ir.ONAME { - r.Right().SetLeft(o.copyExpr(r.Right().Left(), r.Right().Left().Type(), false)) + recv.SetLeft(o.expr(recv.Left(), nil)) + if recv.Left().Op() != ir.ONAME { + recv.SetLeft(o.copyExpr(recv.Left(), recv.Left().Type(), false)) } // Introduce temporary for receive and move actual copy into case body. @@ -906,42 +907,41 @@ func (o *Order) stmt(n ir.Node) { // temporary per distinct type, sharing the temp among all receives // with that temp. Similarly one ok bool could be shared among all // the x,ok receives. Not worth doing until there's a clear need. - if r.Left() != nil && ir.IsBlank(r.Left()) { - r.SetLeft(nil) - } - if r.Left() != nil { + if !ir.IsBlank(dst) { // use channel element type for temporary to avoid conversions, // such as in case interfacevalue = <-intchan. // the conversion happens in the OAS instead. - tmp1 := r.Left() - if r.Colas() { - tmp2 := ir.Nod(ir.ODCL, tmp1, nil) - tmp2 = typecheck(tmp2, ctxStmt) - n2.PtrInit().Append(tmp2) + dcl := ir.Nod(ir.ODCL, dst, nil) + dcl = typecheck(dcl, ctxStmt) + n2.PtrInit().Append(dcl) } - r.SetLeft(o.newTemp(r.Right().Left().Type().Elem(), r.Right().Left().Type().Elem().HasPointers())) - tmp2 := ir.Nod(ir.OAS, tmp1, r.Left()) - tmp2 = typecheck(tmp2, ctxStmt) - n2.PtrInit().Append(tmp2) + tmp := o.newTemp(recv.Left().Type().Elem(), recv.Left().Type().Elem().HasPointers()) + as := ir.Nod(ir.OAS, dst, tmp) + as = typecheck(as, ctxStmt) + n2.PtrInit().Append(as) + dst = tmp } - - if r.List().Len() != 0 && ir.IsBlank(r.List().First()) { - r.PtrList().Set(nil) - } - if r.List().Len() != 0 { - tmp1 := r.List().First() + if !ir.IsBlank(ok) { if r.Colas() { - tmp2 := ir.Nod(ir.ODCL, tmp1, nil) - tmp2 = typecheck(tmp2, ctxStmt) - n2.PtrInit().Append(tmp2) + dcl := ir.Nod(ir.ODCL, ok, nil) + dcl = typecheck(dcl, ctxStmt) + n2.PtrInit().Append(dcl) } - r.PtrList().Set1(o.newTemp(types.Types[types.TBOOL], false)) - tmp2 := okas(tmp1, r.List().First()) - tmp2 = typecheck(tmp2, ctxStmt) - n2.PtrInit().Append(tmp2) + tmp := o.newTemp(types.Types[types.TBOOL], false) + as := okas(ok, tmp) + as = typecheck(as, ctxStmt) + n2.PtrInit().Append(as) + ok = tmp + } + + if r.Op() == ir.OSELRECV { + r.SetLeft(dst) + } else { + r.List().SetIndex(0, dst) + r.List().SetIndex(1, ok) } orderBlock(n2.PtrInit(), o.free) @@ -1420,7 +1420,7 @@ func (o *Order) as2(n ir.Node) { func (o *Order) okAs2(n ir.Node) { var tmp1, tmp2 ir.Node if !ir.IsBlank(n.List().First()) { - typ := n.Right().Type() + typ := n.Rlist().First().Type() tmp1 = o.newTemp(typ, typ.HasPointers()) } diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go index d52fad5fec..2f2d7051c3 100644 --- a/src/cmd/compile/internal/gc/range.go +++ b/src/cmd/compile/internal/gc/range.go @@ -157,15 +157,19 @@ func cheapComputableIndex(width int64) bool { // simpler forms. The result must be assigned back to n. // Node n may also be modified in place, and may also be // the returned node. -func walkrange(n ir.Node) ir.Node { - if isMapClear(n) { - m := n.Right() +func walkrange(nrange ir.Node) ir.Node { + if isMapClear(nrange) { + m := nrange.Right() lno := setlineno(m) - n = mapClear(m) + n := mapClear(m) base.Pos = lno return n } + nfor := ir.NodAt(nrange.Pos(), ir.OFOR, nil, nil) + nfor.SetInit(nrange.Init()) + nfor.SetSym(nrange.Sym()) + // variable name conventions: // ohv1, hv1, hv2: hidden (old) val 1, 2 // ha, hit: hidden aggregate, iterator @@ -173,20 +177,19 @@ func walkrange(n ir.Node) ir.Node { // hb: hidden bool // a, v1, v2: not hidden aggregate, val 1, 2 - t := n.Type() + t := nrange.Type() - a := n.Right() + a := nrange.Right() lno := setlineno(a) - n.SetRight(nil) var v1, v2 ir.Node - l := n.List().Len() + l := nrange.List().Len() if l > 0 { - v1 = n.List().First() + v1 = nrange.List().First() } if l > 1 { - v2 = n.List().Second() + v2 = nrange.List().Second() } if ir.IsBlank(v2) { @@ -201,14 +204,8 @@ func walkrange(n ir.Node) ir.Node { base.Fatalf("walkrange: v2 != nil while v1 == nil") } - // n.List has no meaning anymore, clear it - // to avoid erroneous processing by racewalk. - n.PtrList().Set(nil) - var ifGuard ir.Node - translatedLoopOp := ir.OFOR - var body []ir.Node var init []ir.Node switch t.Etype { @@ -216,9 +213,9 @@ func walkrange(n ir.Node) ir.Node { base.Fatalf("walkrange") case types.TARRAY, types.TSLICE: - if arrayClear(n, v1, v2, a) { + if nn := arrayClear(nrange, v1, v2, a); nn != nil { base.Pos = lno - return n + return nn } // order.stmt arranged for a copy of the array/slice variable if needed. @@ -230,8 +227,8 @@ func walkrange(n ir.Node) ir.Node { init = append(init, ir.Nod(ir.OAS, hv1, nil)) init = append(init, ir.Nod(ir.OAS, hn, ir.Nod(ir.OLEN, ha, nil))) - n.SetLeft(ir.Nod(ir.OLT, hv1, hn)) - n.SetRight(ir.Nod(ir.OAS, hv1, ir.Nod(ir.OADD, hv1, nodintconst(1)))) + nfor.SetLeft(ir.Nod(ir.OLT, hv1, hn)) + nfor.SetRight(ir.Nod(ir.OAS, hv1, ir.Nod(ir.OADD, hv1, nodintconst(1)))) // for range ha { body } if v1 == nil { @@ -245,7 +242,7 @@ func walkrange(n ir.Node) ir.Node { } // for v1, v2 := range ha { body } - if cheapComputableIndex(n.Type().Elem().Width) { + if cheapComputableIndex(nrange.Type().Elem().Width) { // v1, v2 = hv1, ha[hv1] tmp := ir.Nod(ir.OINDEX, ha, hv1) tmp.SetBounded(true) @@ -272,9 +269,9 @@ func walkrange(n ir.Node) ir.Node { // Enhance the prove pass to understand this. ifGuard = ir.Nod(ir.OIF, nil, nil) ifGuard.SetLeft(ir.Nod(ir.OLT, hv1, hn)) - translatedLoopOp = ir.OFORUNTIL + nfor.SetOp(ir.OFORUNTIL) - hp := temp(types.NewPtr(n.Type().Elem())) + hp := temp(types.NewPtr(nrange.Type().Elem())) tmp := ir.Nod(ir.OINDEX, ha, nodintconst(0)) tmp.SetBounded(true) init = append(init, ir.Nod(ir.OAS, hp, ir.Nod(ir.OADDR, tmp, nil))) @@ -293,16 +290,15 @@ func walkrange(n ir.Node) ir.Node { // end of the allocation. a = ir.Nod(ir.OAS, hp, addptr(hp, t.Elem().Width)) a = typecheck(a, ctxStmt) - n.PtrList().Set1(a) + nfor.PtrList().Set1(a) case types.TMAP: // order.stmt allocated the iterator for us. // we only use a once, so no copy needed. ha := a - hit := prealloc[n] + hit := prealloc[nrange] th := hit.Type() - n.SetLeft(nil) keysym := th.Field(0).Sym // depends on layout of iterator struct. See reflect.go:hiter elemsym := th.Field(1).Sym // ditto @@ -310,11 +306,11 @@ func walkrange(n ir.Node) ir.Node { fn = substArgTypes(fn, t.Key(), t.Elem(), th) init = append(init, mkcall1(fn, nil, nil, typename(t), ha, ir.Nod(ir.OADDR, hit, nil))) - n.SetLeft(ir.Nod(ir.ONE, nodSym(ir.ODOT, hit, keysym), nodnil())) + nfor.SetLeft(ir.Nod(ir.ONE, nodSym(ir.ODOT, hit, keysym), nodnil())) fn = syslook("mapiternext") fn = substArgTypes(fn, th) - n.SetRight(mkcall1(fn, nil, nil, ir.Nod(ir.OADDR, hit, nil))) + nfor.SetRight(mkcall1(fn, nil, nil, ir.Nod(ir.OADDR, hit, nil))) key := nodSym(ir.ODOT, hit, keysym) key = ir.Nod(ir.ODEREF, key, nil) @@ -335,8 +331,6 @@ func walkrange(n ir.Node) ir.Node { // order.stmt arranged for a copy of the channel variable. ha := a - n.SetLeft(nil) - hv1 := temp(t.Elem()) hv1.SetTypecheck(1) if t.Elem().HasPointers() { @@ -344,12 +338,12 @@ func walkrange(n ir.Node) ir.Node { } hb := temp(types.Types[types.TBOOL]) - n.SetLeft(ir.Nod(ir.ONE, hb, nodbool(false))) + nfor.SetLeft(ir.Nod(ir.ONE, hb, nodbool(false))) a := ir.Nod(ir.OAS2RECV, nil, nil) a.SetTypecheck(1) a.PtrList().Set2(hv1, hb) - a.SetRight(ir.Nod(ir.ORECV, ha, nil)) - n.Left().PtrInit().Set1(a) + a.PtrRlist().Set1(ir.Nod(ir.ORECV, ha, nil)) + nfor.Left().PtrInit().Set1(a) if v1 == nil { body = nil } else { @@ -387,7 +381,7 @@ func walkrange(n ir.Node) ir.Node { init = append(init, ir.Nod(ir.OAS, hv1, nil)) // hv1 < len(ha) - n.SetLeft(ir.Nod(ir.OLT, hv1, ir.Nod(ir.OLEN, ha, nil))) + nfor.SetLeft(ir.Nod(ir.OLT, hv1, ir.Nod(ir.OLEN, ha, nil))) if v1 != nil { // hv1t = hv1 @@ -431,24 +425,25 @@ func walkrange(n ir.Node) ir.Node { } } - n.SetOp(translatedLoopOp) typecheckslice(init, ctxStmt) if ifGuard != nil { ifGuard.PtrInit().Append(init...) ifGuard = typecheck(ifGuard, ctxStmt) } else { - n.PtrInit().Append(init...) + nfor.PtrInit().Append(init...) } - typecheckslice(n.Left().Init().Slice(), ctxStmt) + typecheckslice(nfor.Left().Init().Slice(), ctxStmt) - n.SetLeft(typecheck(n.Left(), ctxExpr)) - n.SetLeft(defaultlit(n.Left(), nil)) - n.SetRight(typecheck(n.Right(), ctxStmt)) + nfor.SetLeft(typecheck(nfor.Left(), ctxExpr)) + nfor.SetLeft(defaultlit(nfor.Left(), nil)) + nfor.SetRight(typecheck(nfor.Right(), ctxStmt)) typecheckslice(body, ctxStmt) - n.PtrBody().Prepend(body...) + nfor.PtrBody().Append(body...) + nfor.PtrBody().Append(nrange.Body().Slice()...) + var n ir.Node = nfor if ifGuard != nil { ifGuard.PtrBody().Set1(n) n = ifGuard @@ -534,31 +529,31 @@ func mapClear(m ir.Node) ir.Node { // in which the evaluation of a is side-effect-free. // // Parameters are as in walkrange: "for v1, v2 = range a". -func arrayClear(n, v1, v2, a ir.Node) bool { +func arrayClear(loop, v1, v2, a ir.Node) ir.Node { if base.Flag.N != 0 || instrumenting { - return false + return nil } if v1 == nil || v2 != nil { - return false + return nil } - if n.Body().Len() != 1 || n.Body().First() == nil { - return false + if loop.Body().Len() != 1 || loop.Body().First() == nil { + return nil } - stmt := n.Body().First() // only stmt in body + stmt := loop.Body().First() // only stmt in body if stmt.Op() != ir.OAS || stmt.Left().Op() != ir.OINDEX { - return false + return nil } if !samesafeexpr(stmt.Left().Left(), a) || !samesafeexpr(stmt.Left().Right(), v1) { - return false + return nil } - elemsize := n.Type().Elem().Width + elemsize := loop.Type().Elem().Width if elemsize <= 0 || !isZero(stmt.Right()) { - return false + return nil } // Convert to @@ -568,8 +563,7 @@ func arrayClear(n, v1, v2, a ir.Node) bool { // memclr{NoHeap,Has}Pointers(hp, hn) // i = len(a) - 1 // } - n.SetOp(ir.OIF) - + n := ir.Nod(ir.OIF, nil, nil) n.PtrBody().Set(nil) n.SetLeft(ir.Nod(ir.ONE, ir.Nod(ir.OLEN, a, nil), nodintconst(0))) @@ -611,7 +605,7 @@ func arrayClear(n, v1, v2, a ir.Node) bool { n.SetLeft(defaultlit(n.Left(), nil)) typecheckslice(n.Body().Slice(), ctxStmt) n = walkstmt(n) - return true + return n } // addptr returns (*T)(uintptr(p) + n). diff --git a/src/cmd/compile/internal/gc/select.go b/src/cmd/compile/internal/gc/select.go index 9668df082a..3afcef69f8 100644 --- a/src/cmd/compile/internal/gc/select.go +++ b/src/cmd/compile/internal/gc/select.go @@ -47,36 +47,30 @@ func typecheckselect(sel ir.Node) { } base.ErrorfAt(pos, "select case must be receive, send or assign recv") - // convert x = <-c into OSELRECV(x, <-c). - // remove implicit conversions; the eventual assignment - // will reintroduce them. case ir.OAS: + // convert x = <-c into OSELRECV(x, <-c). + // remove implicit conversions; the eventual assignment + // will reintroduce them. if (n.Right().Op() == ir.OCONVNOP || n.Right().Op() == ir.OCONVIFACE) && n.Right().Implicit() { n.SetRight(n.Right().Left()) } - if n.Right().Op() != ir.ORECV { base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side") break } - n.SetOp(ir.OSELRECV) - // convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok case ir.OAS2RECV: - if n.Right().Op() != ir.ORECV { + // convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok + if n.Rlist().First().Op() != ir.ORECV { base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side") break } - n.SetOp(ir.OSELRECV2) - n.SetLeft(n.List().First()) - n.PtrList().Set1(n.List().Second()) - // convert <-c into OSELRECV(N, <-c) case ir.ORECV: - n = ir.NodAt(n.Pos(), ir.OSELRECV, nil, n) - + // convert <-c into OSELRECV(_, <-c) + n = ir.NodAt(n.Pos(), ir.OSELRECV, ir.BlankNode, n) n.SetTypecheck(1) ncase.SetLeft(n) @@ -134,28 +128,19 @@ func walkselectcases(cases *ir.Nodes) []ir.Node { case ir.OSEND: // already ok - case ir.OSELRECV, ir.OSELRECV2: - if n.Op() == ir.OSELRECV || n.List().Len() == 0 { - if n.Left() == nil { - n = n.Right() - } else { - n.SetOp(ir.OAS) - } + case ir.OSELRECV: + if ir.IsBlank(n.Left()) { + n = n.Right() break } + n.SetOp(ir.OAS) - if n.Left() == nil { - ir.BlankNode = typecheck(ir.BlankNode, ctxExpr|ctxAssign) - n.SetLeft(ir.BlankNode) + case ir.OSELRECV2: + if ir.IsBlank(n.List().First()) && ir.IsBlank(n.List().Second()) { + n = n.Rlist().First() + break } - - n.SetOp(ir.OAS2) - n.PtrList().Prepend(n.Left()) - n.PtrRlist().Set1(n.Right()) - n.SetRight(nil) - n.SetLeft(nil) - n.SetTypecheck(0) - n = typecheck(n, ctxStmt) + n.SetOp(ir.OAS2RECV) } l = append(l, n) @@ -176,20 +161,30 @@ func walkselectcases(cases *ir.Nodes) []ir.Node { dflt = cas continue } + + // Lower x, _ = <-c to x = <-c. + if n.Op() == ir.OSELRECV2 && ir.IsBlank(n.List().Second()) { + n = ir.NodAt(n.Pos(), ir.OSELRECV, n.List().First(), n.Rlist().First()) + n.SetTypecheck(1) + cas.SetLeft(n) + } + switch n.Op() { case ir.OSEND: n.SetRight(ir.Nod(ir.OADDR, n.Right(), nil)) n.SetRight(typecheck(n.Right(), ctxExpr)) - case ir.OSELRECV, ir.OSELRECV2: - if n.Op() == ir.OSELRECV2 && n.List().Len() == 0 { - n.SetOp(ir.OSELRECV) - } - - if n.Left() != nil { + case ir.OSELRECV: + if !ir.IsBlank(n.Left()) { n.SetLeft(ir.Nod(ir.OADDR, n.Left(), nil)) n.SetLeft(typecheck(n.Left(), ctxExpr)) } + + case ir.OSELRECV2: + if !ir.IsBlank(n.List().First()) { + n.List().SetIndex(0, ir.Nod(ir.OADDR, n.List().First(), nil)) + n.List().SetIndex(0, typecheck(n.List().First(), ctxExpr)) + } } } @@ -204,6 +199,7 @@ func walkselectcases(cases *ir.Nodes) []ir.Node { setlineno(n) r := ir.Nod(ir.OIF, nil, nil) r.PtrInit().Set(cas.Init().Slice()) + var call ir.Node switch n.Op() { default: base.Fatalf("select %v", n.Op()) @@ -211,30 +207,30 @@ func walkselectcases(cases *ir.Nodes) []ir.Node { case ir.OSEND: // if selectnbsend(c, v) { body } else { default body } ch := n.Left() - r.SetLeft(mkcall1(chanfn("selectnbsend", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), ch, n.Right())) + call = mkcall1(chanfn("selectnbsend", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), ch, n.Right()) case ir.OSELRECV: // if selectnbrecv(&v, c) { body } else { default body } ch := n.Right().Left() elem := n.Left() - if elem == nil { + if ir.IsBlank(elem) { elem = nodnil() } - r.SetLeft(mkcall1(chanfn("selectnbrecv", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, ch)) + call = mkcall1(chanfn("selectnbrecv", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, ch) case ir.OSELRECV2: // if selectnbrecv2(&v, &received, c) { body } else { default body } - ch := n.Right().Left() - elem := n.Left() - if elem == nil { + ch := n.Rlist().First().Left() + elem := n.List().First() + if ir.IsBlank(elem) { elem = nodnil() } - receivedp := ir.Nod(ir.OADDR, n.List().First(), nil) + receivedp := ir.Nod(ir.OADDR, n.List().Second(), nil) receivedp = typecheck(receivedp, ctxExpr) - r.SetLeft(mkcall1(chanfn("selectnbrecv2", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, receivedp, ch)) + call = mkcall1(chanfn("selectnbrecv2", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, receivedp, ch) } - r.SetLeft(typecheck(r.Left(), ctxExpr)) + r.SetLeft(typecheck(call, ctxExpr)) r.PtrBody().Set(cas.Body().Slice()) r.PtrRlist().Set(append(dflt.Init().Slice(), dflt.Body().Slice()...)) return []ir.Node{r, ir.Nod(ir.OBREAK, nil, nil)} @@ -288,11 +284,16 @@ func walkselectcases(cases *ir.Nodes) []ir.Node { nsends++ c = n.Left() elem = n.Right() - case ir.OSELRECV, ir.OSELRECV2: + case ir.OSELRECV: nrecvs++ i = ncas - nrecvs c = n.Right().Left() elem = n.Left() + case ir.OSELRECV2: + nrecvs++ + i = ncas - nrecvs + c = n.Rlist().First().Left() + elem = n.List().First() } casorder[i] = cas @@ -305,7 +306,7 @@ func walkselectcases(cases *ir.Nodes) []ir.Node { c = convnop(c, types.Types[types.TUNSAFEPTR]) setField("c", c) - if elem != nil { + if !ir.IsBlank(elem) { elem = convnop(elem, types.Types[types.TUNSAFEPTR]) setField("elem", elem) } @@ -347,7 +348,7 @@ func walkselectcases(cases *ir.Nodes) []ir.Node { r := ir.Nod(ir.OIF, cond, nil) if n := cas.Left(); n != nil && n.Op() == ir.OSELRECV2 { - x := ir.Nod(ir.OAS, n.List().First(), recvOK) + x := ir.Nod(ir.OAS, n.List().Second(), recvOK) x = typecheck(x, ctxStmt) r.PtrBody().Append(x) } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 6d818be132..4be6caa0e3 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1120,9 +1120,9 @@ func (s *state) stmt(n ir.Node) { s.callResult(n.Left(), callGo) case ir.OAS2DOTTYPE: - res, resok := s.dottype(n.Right(), true) + res, resok := s.dottype(n.Rlist().First(), true) deref := false - if !canSSAType(n.Right().Type()) { + if !canSSAType(n.Rlist().First().Type()) { if res.Op != ssa.OpLoad { s.Fatalf("dottype of non-load") } @@ -1142,10 +1142,10 @@ func (s *state) stmt(n ir.Node) { case ir.OAS2FUNC: // We come here only when it is an intrinsic call returning two values. - if !isIntrinsicCall(n.Right()) { - s.Fatalf("non-intrinsic AS2FUNC not expanded %v", n.Right()) + if !isIntrinsicCall(n.Rlist().First()) { + s.Fatalf("non-intrinsic AS2FUNC not expanded %v", n.Rlist().First()) } - v := s.intrinsicCall(n.Right()) + v := s.intrinsicCall(n.Rlist().First()) v1 := s.newValue1(ssa.OpSelect0, n.List().First().Type(), v) v2 := s.newValue1(ssa.OpSelect1, n.List().Second().Type(), v) s.assign(n.List().First(), v1, false, 0) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 19146e2a9e..b5ace76552 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3330,8 +3330,6 @@ func typecheckas2(n ir.Node) { goto mismatch } n.SetOp(ir.OAS2FUNC) - n.SetRight(r) - n.PtrRlist().Set(nil) for i, l := range n.List().Slice() { f := r.Type().Field(i) if f.Type != nil && l.Type() != nil { @@ -3361,8 +3359,6 @@ func typecheckas2(n ir.Node) { n.SetOp(ir.OAS2DOTTYPE) r.SetOp(ir.ODOTTYPE2) } - n.SetRight(r) - n.PtrRlist().Set(nil) if l.Type() != nil { checkassignto(r.Type(), l) } diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index d43545391c..c3c2c0492a 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -144,6 +144,7 @@ func lexinit() { types.Types[types.TBLANK] = types.New(types.TBLANK) ir.AsNode(s.Def).SetType(types.Types[types.TBLANK]) ir.BlankNode = ir.AsNode(s.Def) + ir.BlankNode.SetTypecheck(1) s = ir.BuiltinPkg.Lookup("_") s.Block = -100 diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index e7c88bd329..0a77cfbb38 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -604,11 +604,8 @@ opswitch: if n.Op() == ir.OASOP { // Rewrite x op= y into x = x op y. - n.SetRight(ir.Nod(n.SubOp(), n.Left(), n.Right())) - n.SetRight(typecheck(n.Right(), ctxExpr)) - - n.SetOp(ir.OAS) - n.ResetAux() + n = ir.Nod(ir.OAS, n.Left(), + typecheck(ir.Nod(n.SubOp(), n.Left(), n.Right()), ctxExpr)) } if oaslit(n, init) { @@ -683,12 +680,12 @@ opswitch: case ir.OAS2FUNC: init.AppendNodes(n.PtrInit()) - r := n.Right() + r := n.Rlist().First() walkexprlistsafe(n.List().Slice(), init) r = walkexpr(r, init) if isIntrinsicCall(r) { - n.SetRight(r) + n.PtrRlist().Set1(r) break } init.Append(r) @@ -701,7 +698,7 @@ opswitch: case ir.OAS2RECV: init.AppendNodes(n.PtrInit()) - r := n.Right() + r := n.Rlist().First() walkexprlistsafe(n.List().Slice(), init) r.SetLeft(walkexpr(r.Left(), init)) var n1 ir.Node @@ -720,7 +717,7 @@ opswitch: case ir.OAS2MAPR: init.AppendNodes(n.PtrInit()) - r := n.Right() + r := n.Rlist().First() walkexprlistsafe(n.List().Slice(), init) r.SetLeft(walkexpr(r.Left(), init)) r.SetRight(walkexpr(r.Right(), init)) @@ -759,7 +756,7 @@ opswitch: if ok := n.List().Second(); !ir.IsBlank(ok) && ok.Type().IsBoolean() { r.Type().Field(1).Type = ok.Type() } - n.SetRight(r) + n.PtrRlist().Set1(r) n.SetOp(ir.OAS2FUNC) // don't generate a = *var if a is _ @@ -793,7 +790,7 @@ opswitch: case ir.OAS2DOTTYPE: walkexprlistsafe(n.List().Slice(), init) - n.SetRight(walkexpr(n.Right(), init)) + n.PtrRlist().SetIndex(0, walkexpr(n.Rlist().First(), init)) case ir.OCONVIFACE: n.SetLeft(walkexpr(n.Left(), init)) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index c723bad4c9..4a08cca359 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -939,15 +939,12 @@ func stmtFmt(n Node, s fmt.State, mode FmtMode) { mode.Fprintf(s, "%v %#v= %v", n.Left(), n.SubOp(), n.Right()) - case OAS2: + case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: if n.Colas() && !complexinit { mode.Fprintf(s, "%.v := %.v", n.List(), n.Rlist()) - break + } else { + mode.Fprintf(s, "%.v = %.v", n.List(), n.Rlist()) } - fallthrough - - case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: - mode.Fprintf(s, "%.v = %v", n.List(), n.Right()) case ORETURN: mode.Fprintf(s, "return %.v", n.List()) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 2850704ae1..85f7f92a42 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -520,8 +520,8 @@ const ( ORECOVER // recover() ORECV // <-Left ORUNESTR // Type(Left) (Type is string, Left is rune) - OSELRECV // Left = <-Right.Left: (appears as .Left of OCASE; Right.Op == ORECV) - OSELRECV2 // List = <-Right.Left: (appears as .Left of OCASE; count(List) == 2, Right.Op == ORECV) + OSELRECV // like OAS: Left = Right where Right.Op = ORECV (appears as .Left of OCASE) + OSELRECV2 // like OAS2: List = Rlist where len(List)=2, len(Rlist)=1, Rlist[0].Op = ORECV (appears as .Left of OCASE) OIOTA // iota OREAL // real(Left) OIMAG // imag(Left) diff --git a/src/cmd/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go index 51bab49518..4a6ed2fac9 100644 --- a/src/cmd/compile/internal/logopt/logopt_test.go +++ b/src/cmd/compile/internal/logopt/logopt_test.go @@ -132,7 +132,7 @@ func TestLogOpt(t *testing.T) { // Check at both 1 and 8-byte alignments. t.Run("Copy", func(t *testing.T) { const copyCode = `package x -func s128a1(x *[128]int8) [128]int8 { +func s128a1(x *[128]int8) [128]int8 { return *x } func s127a1(x *[127]int8) [127]int8 { @@ -219,7 +219,7 @@ func s15a8(x *[15]int64) [15]int64 { `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from \u0026y.b (address-of)"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":9},"end":{"line":4,"character":9}}},"message":"inlineLoc"},`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from ~R0 = \u003cN\u003e (assign-pair)"},`+ + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from ~R0 = \u0026y.b (assign-pair)"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: flow: ~r2 = ~R0:"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: from return (*int)(~R0) (return)"}]}`) }) From 5fc192af56dd1a9977bf73175ab9e32232b4a14d Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 29 Nov 2020 11:16:20 -0500 Subject: [PATCH 041/212] [dev.regabi] cmd/compile: clean up Order.copyExpr TODO Just a little cleaner to read. Passes buildall w/ toolstash -cmp. Change-Id: I27b9f09bf6756f74f1c01794444518ded1a7d625 Reviewed-on: https://go-review.googlesource.com/c/go/+/274106 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/order.go | 65 +++++++++++++++------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 66e279d85f..83cfb44474 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -93,21 +93,26 @@ func (o *Order) newTemp(t *types.Type, clear bool) ir.Node { // copyExpr behaves like newTemp but also emits // code to initialize the temporary to the value n. -// -// The clear argument is provided for use when the evaluation -// of tmp = n turns into a function call that is passed a pointer -// to the temporary as the output space. If the call blocks before -// tmp has been written, the garbage collector will still treat the -// temporary as live, so we must zero it before entering that call. +func (o *Order) copyExpr(n ir.Node) ir.Node { + return o.copyExpr1(n, false) +} + +// copyExprClear is like copyExpr but clears the temp before assignment. +// It is provided for use when the evaluation of tmp = n turns into +// a function call that is passed a pointer to the temporary as the output space. +// If the call blocks before tmp has been written, +// the garbage collector will still treat the temporary as live, +// so we must zero it before entering that call. // Today, this only happens for channel receive operations. // (The other candidate would be map access, but map access // returns a pointer to the result data instead of taking a pointer // to be filled in.) -// TODO(rsc): t == n.Type() always; remove parameter. -func (o *Order) copyExpr(n ir.Node, t *types.Type, clear bool) ir.Node { - if t != n.Type() { - panic("copyExpr") - } +func (o *Order) copyExprClear(n ir.Node) ir.Node { + return o.copyExpr1(n, true) +} + +func (o *Order) copyExpr1(n ir.Node, clear bool) ir.Node { + t := n.Type() v := o.newTemp(t, clear) a := ir.Nod(ir.OAS, v, n) a = typecheck(a, ctxStmt) @@ -137,7 +142,7 @@ func (o *Order) cheapExpr(n ir.Node) ir.Node { return typecheck(a, ctxExpr) } - return o.copyExpr(n, n.Type(), false) + return o.copyExpr(n) } // safeExpr returns a safe version of n. @@ -224,7 +229,7 @@ func (o *Order) addrTemp(n ir.Node) ir.Node { if isaddrokay(n) { return n } - return o.copyExpr(n, n.Type(), false) + return o.copyExpr(n) } // mapKeyTemp prepares n to be a key in a map runtime call and returns n. @@ -493,7 +498,7 @@ func (o *Order) call(n ir.Node) { // by copying it into a temp and marking that temp // still alive when we pop the temp stack. if arg.Op() == ir.OCONVNOP && arg.Left().Type().IsUnsafePtr() { - x := o.copyExpr(arg.Left(), arg.Left().Type(), false) + x := o.copyExpr(arg.Left()) arg.SetLeft(x) x.Name().SetAddrtaken(true) // ensure SSA keeps the x variable n.PtrBody().Append(typecheck(ir.Nod(ir.OVARLIVE, x, nil), ctxStmt)) @@ -555,10 +560,10 @@ func (o *Order) mapAssign(n ir.Node) { switch { case m.Op() == ir.OINDEXMAP: if !ir.IsAutoTmp(m.Left()) { - m.SetLeft(o.copyExpr(m.Left(), m.Left().Type(), false)) + m.SetLeft(o.copyExpr(m.Left())) } if !ir.IsAutoTmp(m.Right()) { - m.SetRight(o.copyExpr(m.Right(), m.Right().Type(), false)) + m.SetRight(o.copyExpr(m.Right())) } fallthrough case instrumenting && n.Op() == ir.OAS2FUNC && !ir.IsBlank(m): @@ -617,7 +622,7 @@ func (o *Order) stmt(n ir.Node) { if l1.Op() == ir.OINDEXMAP { l2.SetIndexMapLValue(false) } - l2 = o.copyExpr(l2, l2.Type(), false) + l2 = o.copyExpr(l2) r := ir.NodAt(n.Pos(), n.SubOp(), l2, n.Right()) r = typecheck(r, ctxExpr) r = o.expr(r, nil) @@ -802,7 +807,7 @@ func (o *Order) stmt(n ir.Node) { r = typecheck(r, ctxExpr) } - n.SetRight(o.copyExpr(r, r.Type(), false)) + n.SetRight(o.copyExpr(r)) case types.TMAP: if isMapClear(n) { @@ -817,7 +822,7 @@ func (o *Order) stmt(n ir.Node) { // TODO(rsc): Make tmp = literal expressions reuse tmp. // For maps tmp is just one word so it hardly matters. r := n.Right() - n.SetRight(o.copyExpr(r, r.Type(), false)) + n.SetRight(o.copyExpr(r)) // prealloc[n] is the temp for the iterator. // hiter contains pointers and needs to be zeroed. @@ -898,7 +903,7 @@ func (o *Order) stmt(n ir.Node) { recv.SetLeft(o.expr(recv.Left(), nil)) if recv.Left().Op() != ir.ONAME { - recv.SetLeft(o.copyExpr(recv.Left(), recv.Left().Type(), false)) + recv.SetLeft(o.copyExpr(recv.Left())) } // Introduce temporary for receive and move actual copy into case body. @@ -956,11 +961,11 @@ func (o *Order) stmt(n ir.Node) { r.SetLeft(o.expr(r.Left(), nil)) if !ir.IsAutoTmp(r.Left()) { - r.SetLeft(o.copyExpr(r.Left(), r.Left().Type(), false)) + r.SetLeft(o.copyExpr(r.Left())) } r.SetRight(o.expr(r.Right(), nil)) if !ir.IsAutoTmp(r.Right()) { - r.SetRight(o.copyExpr(r.Right(), r.Right().Type(), false)) + r.SetRight(o.copyExpr(r.Right())) } } } @@ -988,7 +993,7 @@ func (o *Order) stmt(n ir.Node) { if instrumenting { // Force copying to the stack so that (chan T)(nil) <- x // is still instrumented as a read of x. - n.SetRight(o.copyExpr(n.Right(), n.Right().Type(), false)) + n.SetRight(o.copyExpr(n.Right())) } else { n.SetRight(o.addrTemp(n.Right())) } @@ -1134,7 +1139,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { // key must be addressable n.SetRight(o.mapKeyTemp(n.Left().Type(), n.Right())) if needCopy { - n = o.copyExpr(n, n.Type(), false) + n = o.copyExpr(n) } // concrete type (not interface) argument might need an addressable @@ -1159,7 +1164,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { o.init(n.Left()) o.call(n.Left()) if lhs == nil || lhs.Op() != ir.ONAME || instrumenting { - n = o.copyExpr(n, n.Type(), false) + n = o.copyExpr(n) } } else { n.SetLeft(o.expr(n.Left(), nil)) @@ -1229,7 +1234,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { } if lhs == nil || lhs.Op() != ir.ONAME || instrumenting { - n = o.copyExpr(n, n.Type(), false) + n = o.copyExpr(n) } case ir.OAPPEND: @@ -1242,7 +1247,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { } if lhs == nil || lhs.Op() != ir.ONAME && !samesafeexpr(lhs, n.List().First()) { - n = o.copyExpr(n, n.Type(), false) + n = o.copyExpr(n) } case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR: @@ -1256,7 +1261,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { max = o.cheapExpr(max) n.SetSliceBounds(low, high, max) if lhs == nil || lhs.Op() != ir.ONAME && !samesafeexpr(lhs, n.Left()) { - n = o.copyExpr(n, n.Type(), false) + n = o.copyExpr(n) } case ir.OCLOSURE: @@ -1283,12 +1288,12 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { case ir.ODOTTYPE, ir.ODOTTYPE2: n.SetLeft(o.expr(n.Left(), nil)) if !isdirectiface(n.Type()) || instrumenting { - n = o.copyExpr(n, n.Type(), true) + n = o.copyExprClear(n) } case ir.ORECV: n.SetLeft(o.expr(n.Left(), nil)) - n = o.copyExpr(n, n.Type(), true) + n = o.copyExprClear(n) case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: n.SetLeft(o.expr(n.Left(), nil)) From b7f67b75d2fe94098afb618adc1badc12ce6e21c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 29 Nov 2020 21:11:07 -0500 Subject: [PATCH 042/212] [dev.regabi] cmd/compile: clean up in preparation for expression Nodes Using expression nodes restricts the set of valid SetOp operations, because you can't SetOp across representation. Rewrite various code to avoid crossing those as-yet-unintroduced boundaries. This also includes choosing a single representation for any given Op. For example, OCLOSE starts out as an OCALL, so it starts with a List of one node and then moves that node to Left. That's no good with real data structures, so the code picks a single canonical implementation and prepares it during the conversion from one Op to the next. In this case, the conversion of an OCALL to an OCLOSE now creates a new node with Left initialized from the start. This pattern repeats. Passes buildall w/ toolstash -cmp. Change-Id: I55a0872c614d883cac9d64976c46aeeaa639e25d Reviewed-on: https://go-review.googlesource.com/c/go/+/274107 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/sinit.go | 8 +- src/cmd/compile/internal/gc/subr.go | 2 +- src/cmd/compile/internal/gc/typecheck.go | 185 ++++++++++------------- src/cmd/compile/internal/gc/walk.go | 7 +- 4 files changed, 85 insertions(+), 117 deletions(-) diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index ff3d3281dd..8146f30377 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -686,8 +686,7 @@ func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) { a = ir.Nod(ir.OADDR, a, nil) } else { - a = ir.Nod(ir.ONEW, nil, nil) - a.PtrList().Set1(ir.TypeNode(t)) + a = ir.Nod(ir.ONEW, ir.TypeNode(t), nil) } a = ir.Nod(ir.OAS, vauto, a) @@ -889,9 +888,8 @@ func anylit(n ir.Node, var_ ir.Node, init *ir.Nodes) { r = ir.Nod(ir.OADDR, n.Right(), nil) r = typecheck(r, ctxExpr) } else { - r = ir.Nod(ir.ONEW, nil, nil) - r.SetTypecheck(1) - r.SetType(t) + r = ir.Nod(ir.ONEW, ir.TypeNode(n.Left().Type()), nil) + r = typecheck(r, ctxExpr) r.SetEsc(n.Esc()) } diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index b1c9d24d99..0163653d3b 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -1472,7 +1472,7 @@ func ifaceData(pos src.XPos, n ir.Node, t *types.Type) ir.Node { if t.IsInterface() { base.Fatalf("ifaceData interface: %v", t) } - ptr := nodlSym(pos, ir.OIDATA, n, nil) + ptr := ir.NodAt(pos, ir.OIDATA, n, nil) if isdirectiface(t) { ptr.SetType(t) ptr.SetTypecheck(1) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index b5ace76552..f021ea48b1 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1065,7 +1065,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetRight(assignconv(n.Right(), t.Key(), "map index")) n.SetType(t.Elem()) n.SetOp(ir.OINDEXMAP) - n.ResetAux() + n.SetIndexMapLValue(false) } case ir.ORECV: @@ -1099,27 +1099,22 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetLeft(defaultlit(n.Left(), nil)) t := n.Left().Type() if t == nil { - n.SetType(nil) return n } if !t.IsChan() { base.Errorf("invalid operation: %v (send to non-chan type %v)", n, t) - n.SetType(nil) return n } if !t.ChanDir().CanSend() { base.Errorf("invalid operation: %v (send to receive-only type %v)", n, t) - n.SetType(nil) return n } n.SetRight(assignconv(n.Right(), t.Elem(), "send")) if n.Right().Type() == nil { - n.SetType(nil) return n } - n.SetType(nil) case ir.OSLICEHEADER: // Errors here are Fatalf instead of Errorf because only the compiler @@ -1299,9 +1294,44 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } // builtin: OLEN, OCAP, etc. - n.SetOp(l.SubOp()) - n.SetLeft(n.Right()) - n.SetRight(nil) + switch l.SubOp() { + default: + base.Fatalf("unknown builtin %v", l) + return n + + case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: + n.SetOp(l.SubOp()) + n.SetLeft(nil) + + case ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL: + typecheckargs(n) + fallthrough + case ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: + arg, ok := needOneArg(n, "%v", n.Op()) + if !ok { + n.SetType(nil) + return n + } + old := n + n = ir.NodAt(n.Pos(), l.SubOp(), arg, nil) + n = addinit(n, old.Init().Slice()) // typecheckargs can add to old.Init + if l.SubOp() == ir.ONEW { + // Bug-compatibility with earlier version. + // This extra node is unnecessary but raises the inlining cost by 1. + n.SetList(old.List()) + } + + case ir.OCOMPLEX, ir.OCOPY: + typecheckargs(n) + arg1, arg2, ok := needTwoArgs(n) + if !ok { + n.SetType(nil) + return n + } + old := n + n = ir.NodAt(n.Pos(), l.SubOp(), arg1, arg2) + n = addinit(n, old.Init().Slice()) // typecheckargs can add to old.Init + } n = typecheck1(n, top) return n } @@ -1319,15 +1349,14 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // pick off before type-checking arguments ok |= ctxExpr - // turn CALL(type, arg) into CONV(arg) w/ type - n.SetLeft(nil) - - n.SetOp(ir.OCONV) - n.SetType(l.Type()) - if !onearg(n, "conversion to %v", l.Type()) { + arg, ok := needOneArg(n, "conversion to %v", l.Type()) + if !ok { n.SetType(nil) return n } + + n = ir.NodAt(n.Pos(), ir.OCONV, arg, nil) + n.SetType(l.Type()) n = typecheck1(n, top) return n } @@ -1406,19 +1435,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: ok |= ctxExpr - if !onearg(n, "%v", n.Op()) { - n.SetType(nil) - return n - } n.SetType(types.Types[types.TUINTPTR]) case ir.OCAP, ir.OLEN: ok |= ctxExpr - if !onearg(n, "%v", n.Op()) { - n.SetType(nil) - return n - } - n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) n.SetLeft(implicitstar(n.Left())) @@ -1445,11 +1465,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { case ir.OREAL, ir.OIMAG: ok |= ctxExpr - if !onearg(n, "%v", n.Op()) { - n.SetType(nil) - return n - } - n.SetLeft(typecheck(n.Left(), ctxExpr)) l := n.Left() t := l.Type() @@ -1474,13 +1489,8 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { case ir.OCOMPLEX: ok |= ctxExpr - typecheckargs(n) - if !twoarg(n) { - n.SetType(nil) - return n - } - l := n.Left() - r := n.Right() + l := typecheck(n.Left(), ctxExpr) + r := typecheck(n.Right(), ctxExpr) if l.Type() == nil || r.Type() == nil { n.SetType(nil) return n @@ -1518,10 +1528,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(t) case ir.OCLOSE: - if !onearg(n, "%v", n.Op()) { - n.SetType(nil) - return n - } n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) l := n.Left() @@ -1638,17 +1644,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { case ir.OCOPY: ok |= ctxStmt | ctxExpr - typecheckargs(n) - if !twoarg(n) { - n.SetType(nil) - return n - } n.SetType(types.Types[types.TINT]) - if n.Left().Type() == nil || n.Right().Type() == nil { - n.SetType(nil) - return n - } + n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) + n.SetRight(typecheck(n.Right(), ctxExpr)) n.SetRight(defaultlit(n.Right(), nil)) if n.Left().Type() == nil || n.Right().Type() == nil { n.SetType(nil) @@ -1746,6 +1745,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } i := 1 + var nn ir.Node switch t.Etype { default: base.Errorf("cannot make type %v", t) @@ -1782,10 +1782,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } - - n.SetLeft(l) - n.SetRight(r) - n.SetOp(ir.OMAKESLICE) + nn = ir.NodAt(n.Pos(), ir.OMAKESLICE, l, r) case types.TMAP: if i < len(args) { @@ -1801,11 +1798,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } - n.SetLeft(l) } else { - n.SetLeft(nodintconst(0)) + l = nodintconst(0) } - n.SetOp(ir.OMAKEMAP) + nn = ir.NodAt(n.Pos(), ir.OMAKEMAP, l, nil) + nn.SetEsc(n.Esc()) case types.TCHAN: l = nil @@ -1822,44 +1819,35 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } - n.SetLeft(l) } else { - n.SetLeft(nodintconst(0)) + l = nodintconst(0) } - n.SetOp(ir.OMAKECHAN) + nn = ir.NodAt(n.Pos(), ir.OMAKECHAN, l, nil) } if i < len(args) { base.Errorf("too many arguments to make(%v)", t) - n.SetOp(ir.OMAKE) n.SetType(nil) return n } - n.SetType(t) + nn.SetType(t) + n = nn case ir.ONEW: ok |= ctxExpr - args := n.List() - if args.Len() == 0 { - base.Errorf("missing argument to new") - n.SetType(nil) - return n + if n.Left() == nil { + // Fatalf because the OCALL above checked for us, + // so this must be an internally-generated mistake. + base.Fatalf("missing argument to new") } - - l := args.First() + l := n.Left() l = typecheck(l, ctxType) t := l.Type() if t == nil { n.SetType(nil) return n } - if args.Len() > 1 { - base.Errorf("too many arguments to new(%v)", t) - n.SetType(nil) - return n - } - n.SetLeft(l) n.SetType(types.NewPtr(t)) @@ -1878,10 +1866,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { case ir.OPANIC: ok |= ctxStmt - if !onearg(n, "panic") { - n.SetType(nil) - return n - } n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), types.Types[types.TINTER])) if n.Left().Type() == nil { @@ -2286,45 +2270,32 @@ func implicitstar(n ir.Node) ir.Node { return n } -func onearg(n ir.Node, f string, args ...interface{}) bool { - if n.Left() != nil { - return true - } +func needOneArg(n ir.Node, f string, args ...interface{}) (ir.Node, bool) { if n.List().Len() == 0 { p := fmt.Sprintf(f, args...) base.Errorf("missing argument to %s: %v", p, n) - return false + return nil, false } if n.List().Len() > 1 { p := fmt.Sprintf(f, args...) base.Errorf("too many arguments to %s: %v", p, n) - n.SetLeft(n.List().First()) - n.PtrList().Set(nil) - return false + return n.List().First(), false } - n.SetLeft(n.List().First()) - n.PtrList().Set(nil) - return true + return n.List().First(), true } -func twoarg(n ir.Node) bool { - if n.Left() != nil { - return true - } +func needTwoArgs(n ir.Node) (ir.Node, ir.Node, bool) { if n.List().Len() != 2 { if n.List().Len() < 2 { base.Errorf("not enough arguments in call to %v", n) } else { base.Errorf("too many arguments in call to %v", n) } - return false + return nil, nil, false } - n.SetLeft(n.List().First()) - n.SetRight(n.List().Second()) - n.PtrList().Set(nil) - return true + return n.List().First(), n.List().Second(), true } func lookdot1(errnode ir.Node, s *types.Sym, t *types.Type, fs *types.Fields, dostrcmp int) *types.Field { @@ -2411,21 +2382,19 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) { return n } - n.SetOp(ir.OMETHEXPR) - n.SetRight(NewName(n.Sym())) - n.SetSym(methodSym(t, n.Sym())) - n.SetType(methodfunc(m.Type, n.Left().Type())) - n.SetOffset(0) - n.SetClass(ir.PFUNC) - n.SetOpt(m) - // methodSym already marked n.Sym as a function. + me := ir.NodAt(n.Pos(), ir.OMETHEXPR, n.Left(), NewName(n.Sym())) + me.SetSym(methodSym(t, n.Sym())) + me.SetType(methodfunc(m.Type, n.Left().Type())) + me.SetOffset(0) + me.SetClass(ir.PFUNC) + me.SetOpt(m) // Issue 25065. Make sure that we emit the symbol for a local method. if base.Ctxt.Flag_dynlink && !inimport && (t.Sym == nil || t.Sym.Pkg == ir.LocalPkg) { - makefuncsym(n.Sym()) + makefuncsym(me.Sym()) } - return n + return me } // isMethodApplicable reports whether method m can be called on a diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 0a77cfbb38..511cdd3685 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1515,9 +1515,10 @@ opswitch: } // Slice the [n]byte to a []byte. - n.SetOp(ir.OSLICEARR) - n.SetLeft(p) - n = walkexpr(n, init) + slice := ir.NodAt(n.Pos(), ir.OSLICEARR, p, nil) + slice.SetType(n.Type()) + slice.SetTypecheck(1) + n = walkexpr(slice, init) break } From 2bc814cd18b582030f25d22e0a3e80d4d30b19cf Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 30 Nov 2020 14:16:39 -0500 Subject: [PATCH 043/212] [dev.regabi] cmd/compile: clean up ONEW node The list is no longer needed and can be deleted. Doing so reduces the inlining cost of any function containing an explicit call to new by 1 point, so this change is not toolstash -cmp safe. Change-Id: Id29e115d68e466a353708ab4b8c1021e9c85a628 Reviewed-on: https://go-review.googlesource.com/c/go/+/274132 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/typecheck.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index f021ea48b1..874594d764 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1315,11 +1315,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { old := n n = ir.NodAt(n.Pos(), l.SubOp(), arg, nil) n = addinit(n, old.Init().Slice()) // typecheckargs can add to old.Init - if l.SubOp() == ir.ONEW { - // Bug-compatibility with earlier version. - // This extra node is unnecessary but raises the inlining cost by 1. - n.SetList(old.List()) - } case ir.OCOMPLEX, ir.OCOPY: typecheckargs(n) From ffa68716a0d50acd29a8eae7874c7e8d02f757ca Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 29 Nov 2020 21:23:47 -0500 Subject: [PATCH 044/212] [dev.regabi] cmd/compile: add custom statement Node implementations These are fairly rote implementations of structs appropriate to each Op (or group of Ops). The names of these are unknown except to ir.NodAt for now. A later, automated change will introduce direct use of the types throughout package gc. Passes buildall w/ toolstash -cmp. Change-Id: Ie9835fcd2b214fda5b2149e187af369d76534487 Reviewed-on: https://go-review.googlesource.com/c/go/+/274108 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/node.go | 78 ++-- src/cmd/compile/internal/ir/stmt.go | 535 +++++++++++++++++++++++++++- 2 files changed, 578 insertions(+), 35 deletions(-) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 85f7f92a42..a4d19c39f8 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -1029,22 +1029,60 @@ func Nod(op Op, nleft, nright Node) Node { func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { var n *node switch op { + case OAS, OSELRECV: + n := NewAssignStmt(pos, nleft, nright) + n.SetOp(op) + return n + case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2: + n := NewAssignListStmt(pos, nil, nil) + n.SetOp(op) + return n + case OASOP: + return NewAssignOpStmt(pos, OXXX, nleft, nright) + case OBLOCK: + return NewBlockStmt(pos, nil) + case OBREAK, OCONTINUE, OFALL, OGOTO, ORETJMP: + return NewBranchStmt(pos, op, nil) + case OCASE: + return NewCaseStmt(pos, nil, nil) + case ODCL, ODCLCONST, ODCLTYPE: + return NewDecl(pos, op, nleft) case ODCLFUNC: return NewFunc(pos) + case ODEFER: + return NewDeferStmt(pos, nleft) case ODEREF: return NewStarExpr(pos, nleft) - case OPACK: - return NewPkgName(pos, nil, nil) case OEMPTY: return NewEmptyStmt(pos) - case OBREAK, OCONTINUE, OFALL, OGOTO: - return NewBranchStmt(pos, op, nil) + case OFOR: + return NewForStmt(pos, nil, nleft, nright, nil) + case OGO: + return NewGoStmt(pos, nleft) + case OIF: + return NewIfStmt(pos, nleft, nil, nil) + case OINLMARK: + return NewInlineMarkStmt(pos, types.BADWIDTH) + case OLABEL: + return NewLabelStmt(pos, nil) case OLITERAL, OTYPE, OIOTA: n := newNameAt(pos, nil) n.SetOp(op) return n - case OLABEL: - return NewLabelStmt(pos, nil) + case OPACK: + return NewPkgName(pos, nil, nil) + case ORANGE: + return NewRangeStmt(pos, nil, nright, nil) + case ORETURN: + return NewReturnStmt(pos, nil) + case OSELECT: + return NewSelectStmt(pos, nil) + case OSEND: + return NewSendStmt(pos, nleft, nright) + case OSWITCH: + return NewSwitchStmt(pos, nleft, nil) + case OTYPESW: + return NewTypeSwitchGuard(pos, nleft, nright) default: n = new(node) } @@ -1067,15 +1105,7 @@ var okForNod = [OEND]bool{ OANDNOT: true, OAPPEND: true, OARRAYLIT: true, - OAS: true, - OAS2: true, - OAS2DOTTYPE: true, - OAS2FUNC: true, - OAS2MAPR: true, - OAS2RECV: true, - OASOP: true, OBITNOT: true, - OBLOCK: true, OBYTES2STR: true, OBYTES2STRTMP: true, OCALL: true, @@ -1083,7 +1113,6 @@ var okForNod = [OEND]bool{ OCALLINTER: true, OCALLMETH: true, OCAP: true, - OCASE: true, OCFUNC: true, OCHECKNIL: true, OCLOSE: true, @@ -1093,10 +1122,6 @@ var okForNod = [OEND]bool{ OCONVIFACE: true, OCONVNOP: true, OCOPY: true, - ODCL: true, - ODCLCONST: true, - ODCLTYPE: true, - ODEFER: true, ODELETE: true, ODIV: true, ODOT: true, @@ -1107,22 +1132,16 @@ var okForNod = [OEND]bool{ ODOTTYPE2: true, OEFACE: true, OEQ: true, - OFOR: true, - OFORUNTIL: true, OGE: true, OGETG: true, - OGO: true, OGT: true, OIDATA: true, - OIF: true, OIMAG: true, OINDEX: true, OINDEXMAP: true, OINLCALL: true, - OINLMARK: true, OITAB: true, OKEY: true, - OLABEL: true, OLE: true, OLEN: true, OLSH: true, @@ -1151,20 +1170,13 @@ var okForNod = [OEND]bool{ OPRINT: true, OPRINTN: true, OPTRLIT: true, - ORANGE: true, OREAL: true, ORECOVER: true, ORECV: true, ORESULT: true, - ORETJMP: true, - ORETURN: true, ORSH: true, ORUNES2STR: true, ORUNESTR: true, - OSELECT: true, - OSELRECV: true, - OSELRECV2: true, - OSEND: true, OSIZEOF: true, OSLICE: true, OSLICE3: true, @@ -1180,8 +1192,6 @@ var okForNod = [OEND]bool{ OSTRUCTKEY: true, OSTRUCTLIT: true, OSUB: true, - OSWITCH: true, - OTYPESW: true, OVARDEF: true, OVARKILL: true, OVARLIVE: true, diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 5b89ff27a4..2516835513 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -10,6 +10,31 @@ import ( "fmt" ) +// A Decl is a declaration of a const, type, or var. (A declared func is a Func.) +// (This is not technically a statement but it's not worth its own file.) +type Decl struct { + miniNode + X Node // the thing being declared +} + +func NewDecl(pos src.XPos, op Op, x Node) *Decl { + n := &Decl{X: x} + n.pos = pos + switch op { + default: + panic("invalid Decl op " + op.String()) + case ODCL, ODCLCONST, ODCLTYPE: + n.op = op + } + return n +} + +func (n *Decl) String() string { return fmt.Sprint(n) } +func (n *Decl) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *Decl) RawCopy() Node { c := *n; return &c } +func (n *Decl) Left() Node { return n.X } +func (n *Decl) SetLeft(x Node) { n.X = x } + // A miniStmt is a miniNode with extra fields common to statements. type miniStmt struct { miniNode @@ -22,7 +47,148 @@ func (n *miniStmt) PtrInit() *Nodes { return &n.init } func (n *miniStmt) HasCall() bool { return n.bits&miniHasCall != 0 } func (n *miniStmt) SetHasCall(b bool) { n.bits.set(miniHasCall, b) } +// An AssignListStmt is an assignment statement with +// more than one item on at least one side: Lhs = Rhs. +// If Def is true, the assignment is a :=. +type AssignListStmt struct { + miniStmt + Lhs Nodes + Def bool + Rhs Nodes + offset int64 // for initorder +} + +func NewAssignListStmt(pos src.XPos, lhs, rhs []Node) *AssignListStmt { + n := &AssignListStmt{} + n.pos = pos + n.op = OAS2 + n.Lhs.Set(lhs) + n.Rhs.Set(rhs) + n.offset = types.BADWIDTH + return n +} + +func (n *AssignListStmt) String() string { return fmt.Sprint(n) } +func (n *AssignListStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AssignListStmt) RawCopy() Node { c := *n; return &c } + +func (n *AssignListStmt) List() Nodes { return n.Lhs } +func (n *AssignListStmt) PtrList() *Nodes { return &n.Lhs } +func (n *AssignListStmt) SetList(x Nodes) { n.Lhs = x } +func (n *AssignListStmt) Rlist() Nodes { return n.Rhs } +func (n *AssignListStmt) PtrRlist() *Nodes { return &n.Rhs } +func (n *AssignListStmt) SetRlist(x Nodes) { n.Rhs = x } +func (n *AssignListStmt) Colas() bool { return n.Def } +func (n *AssignListStmt) SetColas(x bool) { n.Def = x } +func (n *AssignListStmt) Offset() int64 { return n.offset } +func (n *AssignListStmt) SetOffset(x int64) { n.offset = x } + +func (n *AssignListStmt) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2: + n.op = op + } +} + +// An AssignStmt is a simple assignment statement: X = Y. +// If Def is true, the assignment is a :=. +type AssignStmt struct { + miniStmt + X Node + Def bool + Y Node + offset int64 // for initorder +} + +func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt { + n := &AssignStmt{X: x, Y: y} + n.pos = pos + n.op = OAS + n.offset = types.BADWIDTH + return n +} + +func (n *AssignStmt) String() string { return fmt.Sprint(n) } +func (n *AssignStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AssignStmt) RawCopy() Node { c := *n; return &c } + +func (n *AssignStmt) Left() Node { return n.X } +func (n *AssignStmt) SetLeft(x Node) { n.X = x } +func (n *AssignStmt) Right() Node { return n.Y } +func (n *AssignStmt) SetRight(y Node) { n.Y = y } +func (n *AssignStmt) Colas() bool { return n.Def } +func (n *AssignStmt) SetColas(x bool) { n.Def = x } +func (n *AssignStmt) Offset() int64 { return n.offset } +func (n *AssignStmt) SetOffset(x int64) { n.offset = x } + +func (n *AssignStmt) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OAS, OSELRECV: + n.op = op + } +} + +// An AssignOpStmt is an AsOp= assignment statement: X AsOp= Y. +type AssignOpStmt struct { + miniStmt + typ *types.Type + X Node + AsOp Op // OADD etc + Y Node + IncDec bool // actually ++ or -- +} + +func NewAssignOpStmt(pos src.XPos, op Op, x, y Node) *AssignOpStmt { + n := &AssignOpStmt{AsOp: op, X: x, Y: y} + n.pos = pos + n.op = OASOP + return n +} + +func (n *AssignOpStmt) String() string { return fmt.Sprint(n) } +func (n *AssignOpStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AssignOpStmt) RawCopy() Node { c := *n; return &c } + +func (n *AssignOpStmt) Left() Node { return n.X } +func (n *AssignOpStmt) SetLeft(x Node) { n.X = x } +func (n *AssignOpStmt) Right() Node { return n.Y } +func (n *AssignOpStmt) SetRight(y Node) { n.Y = y } +func (n *AssignOpStmt) SubOp() Op { return n.AsOp } +func (n *AssignOpStmt) SetSubOp(x Op) { n.AsOp = x } +func (n *AssignOpStmt) Implicit() bool { return n.IncDec } +func (n *AssignOpStmt) SetImplicit(b bool) { n.IncDec = b } +func (n *AssignOpStmt) Type() *types.Type { return n.typ } +func (n *AssignOpStmt) SetType(x *types.Type) { n.typ = x } + +// A BlockStmt is a block: { List }. +type BlockStmt struct { + miniStmt + list Nodes +} + +func NewBlockStmt(pos src.XPos, list []Node) *BlockStmt { + n := &BlockStmt{} + n.pos = pos + n.op = OBLOCK + n.list.Set(list) + return n +} + +func (n *BlockStmt) String() string { return fmt.Sprint(n) } +func (n *BlockStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *BlockStmt) RawCopy() Node { c := *n; return &c } +func (n *BlockStmt) List() Nodes { return n.list } +func (n *BlockStmt) PtrList() *Nodes { return &n.list } +func (n *BlockStmt) SetList(x Nodes) { n.list = x } + // A BranchStmt is a break, continue, fallthrough, or goto statement. +// +// For back-end code generation, Op may also be RETJMP (return+jump), +// in which case the label names another function entirely. type BranchStmt struct { miniStmt Label *types.Sym // label if present @@ -30,7 +196,7 @@ type BranchStmt struct { func NewBranchStmt(pos src.XPos, op Op, label *types.Sym) *BranchStmt { switch op { - case OBREAK, OCONTINUE, OFALL, OGOTO: + case OBREAK, OCONTINUE, OFALL, OGOTO, ORETJMP: // ok default: panic("NewBranch " + op.String()) @@ -47,6 +213,59 @@ func (n *BranchStmt) RawCopy() Node { c := *n; return &c } func (n *BranchStmt) Sym() *types.Sym { return n.Label } func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym } +// A CaseStmt is a case statement in a switch or select: case List: Body. +type CaseStmt struct { + miniStmt + Vars Nodes // declared variable for this case in type switch + list Nodes // list of expressions for switch, early select + Comm Node // communication case (Exprs[0]) after select is type-checked + body Nodes +} + +func NewCaseStmt(pos src.XPos, list, body []Node) *CaseStmt { + n := &CaseStmt{} + n.pos = pos + n.op = OCASE + n.list.Set(list) + n.body.Set(body) + return n +} + +func (n *CaseStmt) String() string { return fmt.Sprint(n) } +func (n *CaseStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *CaseStmt) RawCopy() Node { c := *n; return &c } +func (n *CaseStmt) List() Nodes { return n.list } +func (n *CaseStmt) PtrList() *Nodes { return &n.list } +func (n *CaseStmt) SetList(x Nodes) { n.list = x } +func (n *CaseStmt) Body() Nodes { return n.body } +func (n *CaseStmt) PtrBody() *Nodes { return &n.body } +func (n *CaseStmt) SetBody(x Nodes) { n.body = x } +func (n *CaseStmt) Rlist() Nodes { return n.Vars } +func (n *CaseStmt) PtrRlist() *Nodes { return &n.Vars } +func (n *CaseStmt) SetRlist(x Nodes) { n.Vars = x } +func (n *CaseStmt) Left() Node { return n.Comm } +func (n *CaseStmt) SetLeft(x Node) { n.Comm = x } + +// A DeferStmt is a defer statement: defer Call. +type DeferStmt struct { + miniStmt + Call Node +} + +func NewDeferStmt(pos src.XPos, call Node) *DeferStmt { + n := &DeferStmt{Call: call} + n.pos = pos + n.op = ODEFER + return n +} + +func (n *DeferStmt) String() string { return fmt.Sprint(n) } +func (n *DeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *DeferStmt) RawCopy() Node { c := *n; return &c } + +func (n *DeferStmt) Left() Node { return n.Call } +func (n *DeferStmt) SetLeft(x Node) { n.Call = x } + // An EmptyStmt is an empty statement type EmptyStmt struct { miniStmt @@ -63,6 +282,123 @@ func (n *EmptyStmt) String() string { return fmt.Sprint(n) } func (n *EmptyStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *EmptyStmt) RawCopy() Node { c := *n; return &c } +// A ForStmt is a non-range for loop: for Init; Cond; Post { Body } +// Op can be OFOR or OFORUNTIL (!Cond). +type ForStmt struct { + miniStmt + Label *types.Sym + Cond Node + Post Node + Late Nodes + body Nodes + hasBreak bool +} + +func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStmt { + n := &ForStmt{Cond: cond, Post: post} + n.pos = pos + n.op = OFOR + n.init.Set(init) + n.body.Set(body) + return n +} + +func (n *ForStmt) String() string { return fmt.Sprint(n) } +func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ForStmt) RawCopy() Node { c := *n; return &c } +func (n *ForStmt) Sym() *types.Sym { return n.Label } +func (n *ForStmt) SetSym(x *types.Sym) { n.Label = x } +func (n *ForStmt) Left() Node { return n.Cond } +func (n *ForStmt) SetLeft(x Node) { n.Cond = x } +func (n *ForStmt) Right() Node { return n.Post } +func (n *ForStmt) SetRight(x Node) { n.Post = x } +func (n *ForStmt) Body() Nodes { return n.body } +func (n *ForStmt) PtrBody() *Nodes { return &n.body } +func (n *ForStmt) SetBody(x Nodes) { n.body = x } +func (n *ForStmt) List() Nodes { return n.Late } +func (n *ForStmt) PtrList() *Nodes { return &n.Late } +func (n *ForStmt) SetList(x Nodes) { n.Late = x } +func (n *ForStmt) HasBreak() bool { return n.hasBreak } +func (n *ForStmt) SetHasBreak(b bool) { n.hasBreak = b } + +func (n *ForStmt) SetOp(op Op) { + if op != OFOR && op != OFORUNTIL { + panic(n.no("SetOp " + op.String())) + } + n.op = op +} + +// A GoStmt is a go statement: go Call. +type GoStmt struct { + miniStmt + Call Node +} + +func NewGoStmt(pos src.XPos, call Node) *GoStmt { + n := &GoStmt{Call: call} + n.pos = pos + n.op = OGO + return n +} + +func (n *GoStmt) String() string { return fmt.Sprint(n) } +func (n *GoStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *GoStmt) RawCopy() Node { c := *n; return &c } + +func (n *GoStmt) Left() Node { return n.Call } +func (n *GoStmt) SetLeft(x Node) { n.Call = x } + +// A IfStmt is a return statement: if Init; Cond { Then } else { Else }. +type IfStmt struct { + miniStmt + Cond Node + body Nodes + Else Nodes + likely bool // code layout hint +} + +func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt { + n := &IfStmt{Cond: cond} + n.pos = pos + n.op = OIF + n.body.Set(body) + n.Else.Set(els) + return n +} + +func (n *IfStmt) String() string { return fmt.Sprint(n) } +func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *IfStmt) RawCopy() Node { c := *n; return &c } +func (n *IfStmt) Left() Node { return n.Cond } +func (n *IfStmt) SetLeft(x Node) { n.Cond = x } +func (n *IfStmt) Body() Nodes { return n.body } +func (n *IfStmt) PtrBody() *Nodes { return &n.body } +func (n *IfStmt) SetBody(x Nodes) { n.body = x } +func (n *IfStmt) Rlist() Nodes { return n.Else } +func (n *IfStmt) PtrRlist() *Nodes { return &n.Else } +func (n *IfStmt) SetRlist(x Nodes) { n.Else = x } +func (n *IfStmt) Likely() bool { return n.likely } +func (n *IfStmt) SetLikely(x bool) { n.likely = x } + +// An InlineMarkStmt is a marker placed just before an inlined body. +type InlineMarkStmt struct { + miniStmt + Index int64 +} + +func NewInlineMarkStmt(pos src.XPos, index int64) *InlineMarkStmt { + n := &InlineMarkStmt{Index: index} + n.pos = pos + n.op = OINLMARK + return n +} + +func (n *InlineMarkStmt) String() string { return fmt.Sprint(n) } +func (n *InlineMarkStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *InlineMarkStmt) RawCopy() Node { c := *n; return &c } +func (n *InlineMarkStmt) Offset() int64 { return n.Index } +func (n *InlineMarkStmt) SetOffset(x int64) { n.Index = x } + // A LabelStmt is a label statement (just the label, not including the statement it labels). type LabelStmt struct { miniStmt @@ -81,3 +417,200 @@ func (n *LabelStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *LabelStmt) RawCopy() Node { c := *n; return &c } func (n *LabelStmt) Sym() *types.Sym { return n.Label } func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x } + +// A RangeStmt is a range loop: for Vars = range X { Stmts } +// Op can be OFOR or OFORUNTIL (!Cond). +type RangeStmt struct { + miniStmt + Label *types.Sym + Vars Nodes // TODO(rsc): Replace with Key, Value Node + Def bool + X Node + body Nodes + hasBreak bool + typ *types.Type // TODO(rsc): Remove - use X.Type() instead +} + +func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt { + n := &RangeStmt{X: x} + n.pos = pos + n.op = ORANGE + n.Vars.Set(vars) + n.body.Set(body) + return n +} + +func (n *RangeStmt) String() string { return fmt.Sprint(n) } +func (n *RangeStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *RangeStmt) RawCopy() Node { c := *n; return &c } +func (n *RangeStmt) Sym() *types.Sym { return n.Label } +func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x } +func (n *RangeStmt) Right() Node { return n.X } +func (n *RangeStmt) SetRight(x Node) { n.X = x } +func (n *RangeStmt) Body() Nodes { return n.body } +func (n *RangeStmt) PtrBody() *Nodes { return &n.body } +func (n *RangeStmt) SetBody(x Nodes) { n.body = x } +func (n *RangeStmt) List() Nodes { return n.Vars } +func (n *RangeStmt) PtrList() *Nodes { return &n.Vars } +func (n *RangeStmt) SetList(x Nodes) { n.Vars = x } +func (n *RangeStmt) HasBreak() bool { return n.hasBreak } +func (n *RangeStmt) SetHasBreak(b bool) { n.hasBreak = b } +func (n *RangeStmt) Colas() bool { return n.Def } +func (n *RangeStmt) SetColas(b bool) { n.Def = b } +func (n *RangeStmt) Type() *types.Type { return n.typ } +func (n *RangeStmt) SetType(x *types.Type) { n.typ = x } + +// A ReturnStmt is a return statement. +type ReturnStmt struct { + miniStmt + orig Node // for typecheckargs rewrite + Results Nodes // return list +} + +func NewReturnStmt(pos src.XPos, results []Node) *ReturnStmt { + n := &ReturnStmt{} + n.pos = pos + n.op = ORETURN + n.orig = n + n.Results.Set(results) + return n +} + +func (n *ReturnStmt) String() string { return fmt.Sprint(n) } +func (n *ReturnStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ReturnStmt) RawCopy() Node { c := *n; return &c } +func (n *ReturnStmt) Orig() Node { return n.orig } +func (n *ReturnStmt) SetOrig(x Node) { n.orig = x } +func (n *ReturnStmt) List() Nodes { return n.Results } +func (n *ReturnStmt) PtrList() *Nodes { return &n.Results } +func (n *ReturnStmt) SetList(x Nodes) { n.Results = x } +func (n *ReturnStmt) IsDDD() bool { return false } // typecheckargs asks + +// A SelectStmt is a block: { Cases }. +type SelectStmt struct { + miniStmt + Label *types.Sym + Cases Nodes + hasBreak bool + + // TODO(rsc): Instead of recording here, replace with a block? + Compiled Nodes // compiled form, after walkswitch +} + +func NewSelectStmt(pos src.XPos, cases []Node) *SelectStmt { + n := &SelectStmt{} + n.pos = pos + n.op = OSELECT + n.Cases.Set(cases) + return n +} + +func (n *SelectStmt) String() string { return fmt.Sprint(n) } +func (n *SelectStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SelectStmt) RawCopy() Node { c := *n; return &c } +func (n *SelectStmt) List() Nodes { return n.Cases } +func (n *SelectStmt) PtrList() *Nodes { return &n.Cases } +func (n *SelectStmt) SetList(x Nodes) { n.Cases = x } +func (n *SelectStmt) Sym() *types.Sym { return n.Label } +func (n *SelectStmt) SetSym(x *types.Sym) { n.Label = x } +func (n *SelectStmt) HasBreak() bool { return n.hasBreak } +func (n *SelectStmt) SetHasBreak(x bool) { n.hasBreak = x } +func (n *SelectStmt) Body() Nodes { return n.Compiled } +func (n *SelectStmt) PtrBody() *Nodes { return &n.Compiled } +func (n *SelectStmt) SetBody(x Nodes) { n.Compiled = x } + +// A SendStmt is a send statement: X <- Y. +type SendStmt struct { + miniStmt + Chan Node + Value Node +} + +func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt { + n := &SendStmt{Chan: ch, Value: value} + n.pos = pos + n.op = OSEND + return n +} + +func (n *SendStmt) String() string { return fmt.Sprint(n) } +func (n *SendStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SendStmt) RawCopy() Node { c := *n; return &c } + +func (n *SendStmt) Left() Node { return n.Chan } +func (n *SendStmt) SetLeft(x Node) { n.Chan = x } +func (n *SendStmt) Right() Node { return n.Value } +func (n *SendStmt) SetRight(y Node) { n.Value = y } + +// A SwitchStmt is a switch statement: switch Init; Expr { Cases }. +type SwitchStmt struct { + miniStmt + Tag Node + Cases Nodes // list of *CaseStmt + Label *types.Sym + hasBreak bool + + // TODO(rsc): Instead of recording here, replace with a block? + Compiled Nodes // compiled form, after walkswitch +} + +func NewSwitchStmt(pos src.XPos, tag Node, cases []Node) *SwitchStmt { + n := &SwitchStmt{Tag: tag} + n.pos = pos + n.op = OSWITCH + n.Cases.Set(cases) + return n +} + +func (n *SwitchStmt) String() string { return fmt.Sprint(n) } +func (n *SwitchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SwitchStmt) RawCopy() Node { c := *n; return &c } +func (n *SwitchStmt) Left() Node { return n.Tag } +func (n *SwitchStmt) SetLeft(x Node) { n.Tag = x } +func (n *SwitchStmt) List() Nodes { return n.Cases } +func (n *SwitchStmt) PtrList() *Nodes { return &n.Cases } +func (n *SwitchStmt) SetList(x Nodes) { n.Cases = x } +func (n *SwitchStmt) Body() Nodes { return n.Compiled } +func (n *SwitchStmt) PtrBody() *Nodes { return &n.Compiled } +func (n *SwitchStmt) SetBody(x Nodes) { n.Compiled = x } +func (n *SwitchStmt) Sym() *types.Sym { return n.Label } +func (n *SwitchStmt) SetSym(x *types.Sym) { n.Label = x } +func (n *SwitchStmt) HasBreak() bool { return n.hasBreak } +func (n *SwitchStmt) SetHasBreak(x bool) { n.hasBreak = x } + +// A TypeSwitchGuard is the [Name :=] X.(type) in a type switch. +type TypeSwitchGuard struct { + miniNode + name *Name + X Node +} + +func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard { + n := &TypeSwitchGuard{X: x} + if name != nil { + n.name = name.(*Name) + } + n.pos = pos + n.op = OTYPESW + return n +} + +func (n *TypeSwitchGuard) String() string { return fmt.Sprint(n) } +func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *TypeSwitchGuard) RawCopy() Node { c := *n; return &c } + +func (n *TypeSwitchGuard) Left() Node { + if n.name == nil { + return nil + } + return n.name +} +func (n *TypeSwitchGuard) SetLeft(x Node) { + if x == nil { + n.name = nil + return + } + n.name = x.(*Name) +} +func (n *TypeSwitchGuard) Right() Node { return n.X } +func (n *TypeSwitchGuard) SetRight(x Node) { n.X = x } From 41ad4dec991c11d9e1efff27fc0b1568f5981c9c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 30 Nov 2020 09:34:34 -0500 Subject: [PATCH 045/212] [dev.regabi] cmd/compile: fix -h The compile -h flag is *meant* to panic, so you can see the stack trace where the error is being printed. Make it do that again. Change-Id: Ieb0042863582d7a4c5d08d2f866a144962915b06 Reviewed-on: https://go-review.googlesource.com/c/go/+/274116 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/main.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 7bad05265d..718239484b 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -43,6 +43,9 @@ func hidePanic() { // about a panic too; let the user clean up // the code and try again. if err := recover(); err != nil { + if err == "-h" { + panic(err) + } base.ErrorExit() } } From 0f9f27287b6eaac1634248e325aaab848e0dfd55 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 30 Nov 2020 00:01:26 -0800 Subject: [PATCH 046/212] [dev.regabi] cmd/compile: remove types.InitSyms It's not types's responsibility to understand how package initialization is implemented. Instead, have gc keep track of the order that packages were imported, and then look for inittask declarations. Also, use resolve to force importing of the inittask's export data, so that we can get the appropriate linker symbol index. (This is also why this CL doesn't satisfy "toolstash -cmp".) Change-Id: I5b706497d4a8d1c4439178863b4a8dba4da0f5a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/274006 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/init.go | 14 ++++++++++++-- src/cmd/compile/internal/gc/noder.go | 3 +++ src/cmd/compile/internal/types/pkg.go | 6 ------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go index ed0218c0e2..b5fd2e7c75 100644 --- a/src/cmd/compile/internal/gc/init.go +++ b/src/cmd/compile/internal/gc/init.go @@ -27,6 +27,9 @@ func renameinit() *types.Sym { return s } +// List of imported packages, in source code order. See #31636. +var sourceOrderImports []*types.Pkg + // fninit makes an initialization record for the package. // See runtime/proc.go:initTask for its layout. // The 3 tasks for initialization are: @@ -40,8 +43,15 @@ func fninit(n []ir.Node) { var fns []*obj.LSym // functions to call for package initialization // Find imported packages with init tasks. - for _, s := range types.InitSyms { - deps = append(deps, s.Linksym()) + for _, pkg := range sourceOrderImports { + n := resolve(ir.AsNode(pkg.Lookup(".inittask").Def)) + if n == nil { + continue + } + if n.Op() != ir.ONAME || n.Class() != ir.PEXTERN { + base.Fatalf("bad inittask: %v", n) + } + deps = append(deps, n.Sym().Linksym()) } // Make a function that contains all the initialization statements. diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 98a09f4006..6a5afe7687 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -347,6 +347,9 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) { p.importedEmbed = true } + if !ipkg.Direct { + sourceOrderImports = append(sourceOrderImports, ipkg) + } ipkg.Direct = true var my *types.Sym diff --git a/src/cmd/compile/internal/types/pkg.go b/src/cmd/compile/internal/types/pkg.go index bcc6789509..bf90570b53 100644 --- a/src/cmd/compile/internal/types/pkg.go +++ b/src/cmd/compile/internal/types/pkg.go @@ -84,9 +84,6 @@ func (pkg *Pkg) Lookup(name string) *Sym { return s } -// List of .inittask entries in imported packages, in source code order. -var InitSyms []*Sym - // LookupOK looks up name in pkg and reports whether it previously existed. func (pkg *Pkg) LookupOK(name string) (s *Sym, existed bool) { // TODO(gri) remove this check in favor of specialized lookup @@ -101,9 +98,6 @@ func (pkg *Pkg) LookupOK(name string) (s *Sym, existed bool) { Name: name, Pkg: pkg, } - if name == ".inittask" { - InitSyms = append(InitSyms, s) - } pkg.Syms[name] = s return s, false } From 0ecf7696335a3aade9e41843acfd5ab188d2511f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 26 Nov 2020 23:28:11 +0700 Subject: [PATCH 047/212] cmd/compile: do not mark OpSP, OpSB pos for debugging Fixes #42801 Change-Id: I2080ecacc109479f5820035401ce2b26d72e2ef2 Reviewed-on: https://go-review.googlesource.com/c/go/+/273506 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Cherry Zhang Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/func.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index ec2c67c1fa..e6f899a2c7 100644 --- a/src/cmd/compile/internal/ssa/func.go +++ b/src/cmd/compile/internal/ssa/func.go @@ -790,10 +790,10 @@ func (f *Func) spSb() (sp, sb *Value) { } } if sb == nil { - sb = f.Entry.NewValue0(initpos, OpSB, f.Config.Types.Uintptr) + sb = f.Entry.NewValue0(initpos.WithNotStmt(), OpSB, f.Config.Types.Uintptr) } if sp == nil { - sp = f.Entry.NewValue0(initpos, OpSP, f.Config.Types.Uintptr) + sp = f.Entry.NewValue0(initpos.WithNotStmt(), OpSP, f.Config.Types.Uintptr) } return } From 9a5a11adfa0f5ead728641d8fb72244e03239547 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 29 Nov 2020 21:25:47 -0500 Subject: [PATCH 048/212] [dev.regabi] cmd/compile: add custom expression Node implementations These are fairly rote implementations of structs appropriate to each Op (or group of Ops). The names of these are unknown except to ir.NodAt for now. A later, automated change will introduce direct use of the types throughout package gc. (This CL is expressions; the previous one was statements.) This is the last of the Ops that were previously handled by the generic node struct, so that struct and its methods can be and are deleted in this CL. Passes buildall w/ toolstash -cmp. Change-Id: I1703f35f24dcd3f7c5782a278e53c3fe04e87c37 Reviewed-on: https://go-review.googlesource.com/c/go/+/274109 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/fmtmap_test.go | 2 +- src/cmd/compile/internal/ir/dump.go | 4 +- src/cmd/compile/internal/ir/expr.go | 727 ++++++++++++++++++++- src/cmd/compile/internal/ir/fmt.go | 5 - src/cmd/compile/internal/ir/node.go | 504 ++------------ src/cmd/compile/internal/ir/sizeof_test.go | 1 - 6 files changed, 783 insertions(+), 460 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index 32891aea66..09b06c4d93 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -29,7 +29,7 @@ var knownFormats = map[string]string{ "*cmd/compile/internal/ir.Name %+v": "", "*cmd/compile/internal/ir.Name %L": "", "*cmd/compile/internal/ir.Name %v": "", - "*cmd/compile/internal/ir.node %v": "", + "*cmd/compile/internal/ir.SliceExpr %v": "", "*cmd/compile/internal/ssa.Block %s": "", "*cmd/compile/internal/ssa.Block %v": "", "*cmd/compile/internal/ssa.Func %s": "", diff --git a/src/cmd/compile/internal/ir/dump.go b/src/cmd/compile/internal/ir/dump.go index fe1410969f..bff3a40855 100644 --- a/src/cmd/compile/internal/ir/dump.go +++ b/src/cmd/compile/internal/ir/dump.go @@ -200,9 +200,9 @@ func (p *dumper) dump(x reflect.Value, depth int) { typ := x.Type() isNode := false - if n, ok := x.Interface().(node); ok { + if n, ok := x.Interface().(Node); ok { isNode = true - p.printf("%s %s {", n.op.String(), p.addr(x)) + p.printf("%s %s {", n.Op().String(), p.addr(x)) } else { p.printf("%s {", typ) } diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index f8e5f7641c..be9f486682 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -5,6 +5,7 @@ package ir import ( + "cmd/compile/internal/base" "cmd/compile/internal/types" "cmd/internal/src" "fmt" @@ -48,6 +49,182 @@ func (n *miniExpr) Init() Nodes { return n.init } func (n *miniExpr) PtrInit() *Nodes { return &n.init } func (n *miniExpr) SetInit(x Nodes) { n.init = x } +func toNtype(x Node) Ntype { + if x == nil { + return nil + } + if _, ok := x.(Ntype); !ok { + Dump("not Ntype", x) + } + return x.(Ntype) +} + +// An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1]. +type AddStringExpr struct { + miniExpr + list Nodes +} + +func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr { + n := &AddStringExpr{} + n.pos = pos + n.op = OADDSTR + n.list.Set(list) + return n +} + +func (n *AddStringExpr) String() string { return fmt.Sprint(n) } +func (n *AddStringExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AddStringExpr) RawCopy() Node { c := *n; return &c } +func (n *AddStringExpr) List() Nodes { return n.list } +func (n *AddStringExpr) PtrList() *Nodes { return &n.list } +func (n *AddStringExpr) SetList(x Nodes) { n.list = x } + +// An AddrExpr is an address-of expression &X. +// It may end up being a normal address-of or an allocation of a composite literal. +type AddrExpr struct { + miniExpr + X Node + Alloc Node // preallocated storage if any +} + +func NewAddrExpr(pos src.XPos, x Node) *AddrExpr { + n := &AddrExpr{X: x} + n.op = OADDR + n.pos = pos + return n +} + +func (n *AddrExpr) String() string { return fmt.Sprint(n) } +func (n *AddrExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AddrExpr) RawCopy() Node { c := *n; return &c } +func (n *AddrExpr) Left() Node { return n.X } +func (n *AddrExpr) SetLeft(x Node) { n.X = x } +func (n *AddrExpr) Right() Node { return n.Alloc } +func (n *AddrExpr) SetRight(x Node) { n.Alloc = x } + +func (n *AddrExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OADDR, OPTRLIT: + n.op = op + } +} + +// A BinaryExpr is a binary expression X Op Y, +// or Op(X, Y) for builtin functions that do not become calls. +type BinaryExpr struct { + miniExpr + X Node + Y Node +} + +func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr { + n := &BinaryExpr{X: x, Y: y} + n.pos = pos + n.SetOp(op) + return n +} + +func (n *BinaryExpr) String() string { return fmt.Sprint(n) } +func (n *BinaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *BinaryExpr) RawCopy() Node { c := *n; return &c } +func (n *BinaryExpr) Left() Node { return n.X } +func (n *BinaryExpr) SetLeft(x Node) { n.X = x } +func (n *BinaryExpr) Right() Node { return n.Y } +func (n *BinaryExpr) SetRight(y Node) { n.Y = y } + +func (n *BinaryExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OADD, OADDSTR, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, + OLSH, OLT, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSUB, OXOR, + OCOPY, OCOMPLEX, + OEFACE: + n.op = op + } +} + +// A CallExpr is a function call X(Args). +type CallExpr struct { + miniExpr + orig Node + X Node + Args Nodes + Rargs Nodes // TODO(rsc): Delete. + body Nodes // TODO(rsc): Delete. + DDD bool + noInline bool +} + +func NewCallExpr(pos src.XPos, fun Node, args []Node) *CallExpr { + n := &CallExpr{X: fun} + n.pos = pos + n.orig = n + n.op = OCALL + n.Args.Set(args) + return n +} + +func (n *CallExpr) String() string { return fmt.Sprint(n) } +func (n *CallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *CallExpr) RawCopy() Node { c := *n; return &c } +func (n *CallExpr) Orig() Node { return n.orig } +func (n *CallExpr) SetOrig(x Node) { n.orig = x } +func (n *CallExpr) Left() Node { return n.X } +func (n *CallExpr) SetLeft(x Node) { n.X = x } +func (n *CallExpr) List() Nodes { return n.Args } +func (n *CallExpr) PtrList() *Nodes { return &n.Args } +func (n *CallExpr) SetList(x Nodes) { n.Args = x } +func (n *CallExpr) Rlist() Nodes { return n.Rargs } +func (n *CallExpr) PtrRlist() *Nodes { return &n.Rargs } +func (n *CallExpr) SetRlist(x Nodes) { n.Rargs = x } +func (n *CallExpr) IsDDD() bool { return n.DDD } +func (n *CallExpr) SetIsDDD(x bool) { n.DDD = x } +func (n *CallExpr) NoInline() bool { return n.noInline } +func (n *CallExpr) SetNoInline(x bool) { n.noInline = x } +func (n *CallExpr) Body() Nodes { return n.body } +func (n *CallExpr) PtrBody() *Nodes { return &n.body } +func (n *CallExpr) SetBody(x Nodes) { n.body = x } + +func (n *CallExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, + OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER: + n.op = op + } +} + +// A CallPartExpr is a method expression X.Method (uncalled). +type CallPartExpr struct { + miniExpr + fn *Func + X Node + Method *Name +} + +func NewCallPartExpr(pos src.XPos, x Node, method *Name, fn *Func) *CallPartExpr { + n := &CallPartExpr{fn: fn, X: x, Method: method} + n.op = OCALLPART + n.pos = pos + n.typ = fn.Type() + n.fn = fn + return n +} + +func (n *CallPartExpr) String() string { return fmt.Sprint(n) } +func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *CallPartExpr) RawCopy() Node { c := *n; return &c } +func (n *CallPartExpr) Func() *Func { return n.fn } +func (n *CallPartExpr) Left() Node { return n.X } +func (n *CallPartExpr) Right() Node { return n.Method } +func (n *CallPartExpr) SetLeft(x Node) { n.X = x } +func (n *CallPartExpr) SetRight(x Node) { n.Method = x.(*Name) } + // A ClosureExpr is a function literal expression. type ClosureExpr struct { miniExpr @@ -85,31 +262,477 @@ func (n *ClosureRead) RawCopy() Node { c := *n; return &c } func (n *ClosureRead) Type() *types.Type { return n.typ } func (n *ClosureRead) Offset() int64 { return n.offset } -// A CallPartExpr is a method expression X.Method (uncalled). -type CallPartExpr struct { +// A CompLitExpr is a composite literal Type{Vals}. +// Before type-checking, the type is Ntype. +type CompLitExpr struct { miniExpr - fn *Func - X Node - Method *Name + orig Node + Ntype Ntype + list Nodes // initialized values } -func NewCallPartExpr(pos src.XPos, x Node, method *Name, fn *Func) *CallPartExpr { - n := &CallPartExpr{fn: fn, X: x, Method: method} - n.op = OCALLPART +func NewCompLitExpr(pos src.XPos, typ Ntype, list []Node) *CompLitExpr { + n := &CompLitExpr{Ntype: typ} n.pos = pos - n.typ = fn.Type() - n.fn = fn + n.op = OCOMPLIT + n.list.Set(list) + n.orig = n return n } -func (n *CallPartExpr) String() string { return fmt.Sprint(n) } -func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CallPartExpr) RawCopy() Node { c := *n; return &c } -func (n *CallPartExpr) Func() *Func { return n.fn } -func (n *CallPartExpr) Left() Node { return n.X } -func (n *CallPartExpr) Right() Node { return n.Method } -func (n *CallPartExpr) SetLeft(x Node) { n.X = x } -func (n *CallPartExpr) SetRight(x Node) { n.Method = x.(*Name) } +func (n *CompLitExpr) String() string { return fmt.Sprint(n) } +func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *CompLitExpr) RawCopy() Node { c := *n; return &c } +func (n *CompLitExpr) Orig() Node { return n.orig } +func (n *CompLitExpr) SetOrig(x Node) { n.orig = x } +func (n *CompLitExpr) Right() Node { return n.Ntype } +func (n *CompLitExpr) SetRight(x Node) { n.Ntype = toNtype(x) } +func (n *CompLitExpr) List() Nodes { return n.list } +func (n *CompLitExpr) PtrList() *Nodes { return &n.list } +func (n *CompLitExpr) SetList(x Nodes) { n.list = x } + +func (n *CompLitExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT: + n.op = op + } +} + +// A ConvExpr is a conversion Type(X). +// It may end up being a value or a type. +type ConvExpr struct { + miniExpr + orig Node + X Node +} + +func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr { + n := &ConvExpr{X: x} + n.pos = pos + n.typ = typ + n.SetOp(op) + n.orig = n + return n +} + +func (n *ConvExpr) String() string { return fmt.Sprint(n) } +func (n *ConvExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ConvExpr) RawCopy() Node { c := *n; return &c } +func (n *ConvExpr) Orig() Node { return n.orig } +func (n *ConvExpr) SetOrig(x Node) { n.orig = x } +func (n *ConvExpr) Left() Node { return n.X } +func (n *ConvExpr) SetLeft(x Node) { n.X = x } + +func (n *ConvExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR: + n.op = op + } +} + +// An IndexExpr is an index expression X[Y]. +type IndexExpr struct { + miniExpr + X Node + Index Node + Assigned bool +} + +func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr { + n := &IndexExpr{X: x, Index: index} + n.pos = pos + n.op = OINDEX + return n +} + +func (n *IndexExpr) String() string { return fmt.Sprint(n) } +func (n *IndexExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *IndexExpr) RawCopy() Node { c := *n; return &c } +func (n *IndexExpr) Left() Node { return n.X } +func (n *IndexExpr) SetLeft(x Node) { n.X = x } +func (n *IndexExpr) Right() Node { return n.Index } +func (n *IndexExpr) SetRight(y Node) { n.Index = y } +func (n *IndexExpr) IndexMapLValue() bool { return n.Assigned } +func (n *IndexExpr) SetIndexMapLValue(x bool) { n.Assigned = x } + +func (n *IndexExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OINDEX, OINDEXMAP: + n.op = op + } +} + +// A KeyExpr is an X:Y composite literal key. +// After type-checking, a key for a struct sets Sym to the field. +type KeyExpr struct { + miniExpr + Key Node + sym *types.Sym + Value Node + offset int64 +} + +func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr { + n := &KeyExpr{Key: key, Value: value} + n.pos = pos + n.op = OKEY + n.offset = types.BADWIDTH + return n +} + +func (n *KeyExpr) String() string { return fmt.Sprint(n) } +func (n *KeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *KeyExpr) RawCopy() Node { c := *n; return &c } +func (n *KeyExpr) Left() Node { return n.Key } +func (n *KeyExpr) SetLeft(x Node) { n.Key = x } +func (n *KeyExpr) Right() Node { return n.Value } +func (n *KeyExpr) SetRight(y Node) { n.Value = y } +func (n *KeyExpr) Sym() *types.Sym { return n.sym } +func (n *KeyExpr) SetSym(x *types.Sym) { n.sym = x } +func (n *KeyExpr) Offset() int64 { return n.offset } +func (n *KeyExpr) SetOffset(x int64) { n.offset = x } + +func (n *KeyExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OKEY, OSTRUCTKEY: + n.op = op + } +} + +// An InlinedCallExpr is an inlined function call. +type InlinedCallExpr struct { + miniExpr + body Nodes + ReturnVars Nodes +} + +func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { + n := &InlinedCallExpr{} + n.pos = pos + n.op = OINLCALL + n.body.Set(body) + n.ReturnVars.Set(retvars) + return n +} + +func (n *InlinedCallExpr) String() string { return fmt.Sprint(n) } +func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *InlinedCallExpr) RawCopy() Node { c := *n; return &c } +func (n *InlinedCallExpr) Body() Nodes { return n.body } +func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.body } +func (n *InlinedCallExpr) SetBody(x Nodes) { n.body = x } +func (n *InlinedCallExpr) Rlist() Nodes { return n.ReturnVars } +func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars } +func (n *InlinedCallExpr) SetRlist(x Nodes) { n.ReturnVars = x } + +// A MakeExpr is a make expression: make(Type[, Len[, Cap]]). +// Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY, +// but *not* OMAKE (that's a pre-typechecking CallExpr). +type MakeExpr struct { + miniExpr + Len Node + Cap Node +} + +func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr { + n := &MakeExpr{Len: len, Cap: cap} + n.pos = pos + n.SetOp(op) + return n +} + +func (n *MakeExpr) String() string { return fmt.Sprint(n) } +func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *MakeExpr) RawCopy() Node { c := *n; return &c } +func (n *MakeExpr) Left() Node { return n.Len } +func (n *MakeExpr) SetLeft(x Node) { n.Len = x } +func (n *MakeExpr) Right() Node { return n.Cap } +func (n *MakeExpr) SetRight(x Node) { n.Cap = x } + +func (n *MakeExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY: + n.op = op + } +} + +// A MethodExpr is a method expression X.M (where X is an expression, not a type). +type MethodExpr struct { + miniExpr + X Node + M Node + sym *types.Sym + offset int64 + class Class +} + +func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr { + n := &MethodExpr{X: x, M: m} + n.pos = pos + n.op = OMETHEXPR + n.offset = types.BADWIDTH + return n +} + +func (n *MethodExpr) String() string { return fmt.Sprint(n) } +func (n *MethodExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *MethodExpr) RawCopy() Node { c := *n; return &c } +func (n *MethodExpr) Left() Node { return n.X } +func (n *MethodExpr) SetLeft(x Node) { n.X = x } +func (n *MethodExpr) Right() Node { return n.M } +func (n *MethodExpr) SetRight(y Node) { n.M = y } +func (n *MethodExpr) Sym() *types.Sym { return n.sym } +func (n *MethodExpr) SetSym(x *types.Sym) { n.sym = x } +func (n *MethodExpr) Offset() int64 { return n.offset } +func (n *MethodExpr) SetOffset(x int64) { n.offset = x } +func (n *MethodExpr) Class() Class { return n.class } +func (n *MethodExpr) SetClass(x Class) { n.class = x } + +// A NilExpr represents the predefined untyped constant nil. +// (It may be copied and assigned a type, though.) +type NilExpr struct { + miniExpr + sym *types.Sym // TODO: Remove +} + +func NewNilExpr(pos src.XPos) *NilExpr { + n := &NilExpr{} + n.pos = pos + n.op = ONIL + return n +} + +func (n *NilExpr) String() string { return fmt.Sprint(n) } +func (n *NilExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *NilExpr) RawCopy() Node { c := *n; return &c } +func (n *NilExpr) Sym() *types.Sym { return n.sym } +func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x } + +// A ParenExpr is a parenthesized expression (X). +// It may end up being a value or a type. +type ParenExpr struct { + miniExpr + X Node +} + +func NewParenExpr(pos src.XPos, x Node) *ParenExpr { + n := &ParenExpr{X: x} + n.op = OPAREN + n.pos = pos + return n +} + +func (n *ParenExpr) String() string { return fmt.Sprint(n) } +func (n *ParenExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ParenExpr) RawCopy() Node { c := *n; return &c } +func (n *ParenExpr) Left() Node { return n.X } +func (n *ParenExpr) SetLeft(x Node) { n.X = x } + +func (*ParenExpr) CanBeNtype() {} + +// SetOTYPE changes n to be an OTYPE node returning t, +// like all the type nodes in type.go. +func (n *ParenExpr) SetOTYPE(t *types.Type) { + n.op = OTYPE + n.typ = t + if t.Nod == nil { + t.Nod = n + } +} + +// A ResultExpr represents a direct access to a result slot on the stack frame. +type ResultExpr struct { + miniExpr + offset int64 +} + +func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr { + n := &ResultExpr{offset: offset} + n.pos = pos + n.op = ORESULT + n.typ = typ + return n +} + +func (n *ResultExpr) String() string { return fmt.Sprint(n) } +func (n *ResultExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ResultExpr) RawCopy() Node { c := *n; return &c } +func (n *ResultExpr) Offset() int64 { return n.offset } +func (n *ResultExpr) SetOffset(x int64) { n.offset = x } + +// A SelectorExpr is a selector expression X.Sym. +type SelectorExpr struct { + miniExpr + X Node + Sel *types.Sym + offset int64 +} + +func NewSelectorExpr(pos src.XPos, x Node, sel *types.Sym) *SelectorExpr { + n := &SelectorExpr{X: x, Sel: sel} + n.pos = pos + n.op = OXDOT + n.offset = types.BADWIDTH + return n +} + +func (n *SelectorExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT: + n.op = op + } +} + +func (n *SelectorExpr) String() string { return fmt.Sprint(n) } +func (n *SelectorExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SelectorExpr) RawCopy() Node { c := *n; return &c } +func (n *SelectorExpr) Left() Node { return n.X } +func (n *SelectorExpr) SetLeft(x Node) { n.X = x } +func (n *SelectorExpr) Sym() *types.Sym { return n.Sel } +func (n *SelectorExpr) SetSym(x *types.Sym) { n.Sel = x } +func (n *SelectorExpr) Offset() int64 { return n.offset } +func (n *SelectorExpr) SetOffset(x int64) { n.offset = x } + +// Before type-checking, bytes.Buffer is a SelectorExpr. +// After type-checking it becomes a Name. +func (*SelectorExpr) CanBeNtype() {} + +// A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max]. +type SliceExpr struct { + miniExpr + X Node + list Nodes // TODO(rsc): Use separate Nodes +} + +func NewSliceExpr(pos src.XPos, op Op, x Node) *SliceExpr { + n := &SliceExpr{X: x} + n.pos = pos + n.op = op + return n +} + +func (n *SliceExpr) String() string { return fmt.Sprint(n) } +func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SliceExpr) RawCopy() Node { c := *n; return &c } +func (n *SliceExpr) Left() Node { return n.X } +func (n *SliceExpr) SetLeft(x Node) { n.X = x } +func (n *SliceExpr) List() Nodes { return n.list } +func (n *SliceExpr) PtrList() *Nodes { return &n.list } +func (n *SliceExpr) SetList(x Nodes) { n.list = x } + +func (n *SliceExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: + n.op = op + } +} + +// SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max]. +// n must be a slice expression. max is nil if n is a simple slice expression. +func (n *SliceExpr) SliceBounds() (low, high, max Node) { + if n.list.Len() == 0 { + return nil, nil, nil + } + + switch n.Op() { + case OSLICE, OSLICEARR, OSLICESTR: + s := n.list.Slice() + return s[0], s[1], nil + case OSLICE3, OSLICE3ARR: + s := n.list.Slice() + return s[0], s[1], s[2] + } + base.Fatalf("SliceBounds op %v: %v", n.Op(), n) + return nil, nil, nil +} + +// SetSliceBounds sets n's slice bounds, where n is a slice expression. +// n must be a slice expression. If max is non-nil, n must be a full slice expression. +func (n *SliceExpr) SetSliceBounds(low, high, max Node) { + switch n.Op() { + case OSLICE, OSLICEARR, OSLICESTR: + if max != nil { + base.Fatalf("SetSliceBounds %v given three bounds", n.Op()) + } + s := n.list.Slice() + if s == nil { + if low == nil && high == nil { + return + } + n.list.Set2(low, high) + return + } + s[0] = low + s[1] = high + return + case OSLICE3, OSLICE3ARR: + s := n.list.Slice() + if s == nil { + if low == nil && high == nil && max == nil { + return + } + n.list.Set3(low, high, max) + return + } + s[0] = low + s[1] = high + s[2] = max + return + } + base.Fatalf("SetSliceBounds op %v: %v", n.Op(), n) +} + +// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR). +// o must be a slicing op. +func (o Op) IsSlice3() bool { + switch o { + case OSLICE, OSLICEARR, OSLICESTR: + return false + case OSLICE3, OSLICE3ARR: + return true + } + base.Fatalf("IsSlice3 op %v", o) + return false +} + +// A SliceHeader expression constructs a slice header from its parts. +type SliceHeaderExpr struct { + miniExpr + Ptr Node + lenCap Nodes // TODO(rsc): Split into two Node fields +} + +func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr { + n := &SliceHeaderExpr{Ptr: ptr} + n.pos = pos + n.op = OSLICEHEADER + n.typ = typ + n.lenCap.Set2(len, cap) + return n +} + +func (n *SliceHeaderExpr) String() string { return fmt.Sprint(n) } +func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SliceHeaderExpr) RawCopy() Node { c := *n; return &c } +func (n *SliceHeaderExpr) Left() Node { return n.Ptr } +func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x } +func (n *SliceHeaderExpr) List() Nodes { return n.lenCap } +func (n *SliceHeaderExpr) PtrList() *Nodes { return &n.lenCap } +func (n *SliceHeaderExpr) SetList(x Nodes) { n.lenCap = x } // A StarExpr is a dereference expression *X. // It may end up being a value or a type. @@ -154,3 +777,71 @@ func (n *StarExpr) DeepCopy(pos src.XPos) Node { c.X = DeepCopy(pos, n.X) return c } + +// A TypeAssertionExpr is a selector expression X.(Type). +// Before type-checking, the type is Ntype. +type TypeAssertExpr struct { + miniExpr + X Node + Ntype Node // TODO: Should be Ntype, but reused as address of type structure + Itab Nodes // Itab[0] is itab +} + +func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr { + n := &TypeAssertExpr{X: x, Ntype: typ} + n.pos = pos + n.op = ODOTTYPE + return n +} + +func (n *TypeAssertExpr) String() string { return fmt.Sprint(n) } +func (n *TypeAssertExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *TypeAssertExpr) RawCopy() Node { c := *n; return &c } +func (n *TypeAssertExpr) Left() Node { return n.X } +func (n *TypeAssertExpr) SetLeft(x Node) { n.X = x } +func (n *TypeAssertExpr) Right() Node { return n.Ntype } +func (n *TypeAssertExpr) SetRight(x Node) { n.Ntype = x } // TODO: toNtype(x) +func (n *TypeAssertExpr) List() Nodes { return n.Itab } +func (n *TypeAssertExpr) PtrList() *Nodes { return &n.Itab } +func (n *TypeAssertExpr) SetList(x Nodes) { n.Itab = x } + +func (n *TypeAssertExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case ODOTTYPE, ODOTTYPE2: + n.op = op + } +} + +// A UnaryExpr is a unary expression Op X, +// or Op(X) for a builtin function that does not end up being a call. +type UnaryExpr struct { + miniExpr + X Node +} + +func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr { + n := &UnaryExpr{X: x} + n.pos = pos + n.SetOp(op) + return n +} + +func (n *UnaryExpr) String() string { return fmt.Sprint(n) } +func (n *UnaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *UnaryExpr) RawCopy() Node { c := *n; return &c } +func (n *UnaryExpr) Left() Node { return n.X } +func (n *UnaryExpr) SetLeft(x Node) { n.X = x } + +func (n *UnaryExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OBITNOT, ONEG, ONOT, OPLUS, ORECV, + OALIGNOF, OCAP, OCLOSE, OIMAG, OLEN, ONEW, + OOFFSETOF, OPANIC, OREAL, OSIZEOF, + OCHECKNIL, OCFUNC, OIDATA, OITAB, ONEWOBJ, OSPTR, OVARDEF, OVARKILL, OVARLIVE: + n.op = op + } +} diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 4a08cca359..a111471222 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -277,10 +277,6 @@ type fmtNodes struct { func (f *fmtNodes) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } -func (n *node) Format(s fmt.State, verb rune) { - FmtNode(n, s, verb) -} - func FmtNode(n Node, s fmt.State, verb rune) { nodeFormat(n, s, verb, FErr) } @@ -1806,7 +1802,6 @@ func typeFormat(t *types.Type, s fmt.State, verb rune, mode FmtMode) { } } -func (n *node) String() string { return fmt.Sprint(n) } func modeString(n Node, mode FmtMode) string { return mode.Sprint(n) } // "%L" suffix with "(type %T)" where possible diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index a4d19c39f8..9b407b36c0 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -118,140 +118,6 @@ type Node interface { CanBeAnSSASym() } -var _ Node = (*node)(nil) - -// A Node is a single node in the syntax tree. -// Actually the syntax tree is a syntax DAG, because there is only one -// node with Op=ONAME for a given instance of a variable x. -// The same is true for Op=OTYPE and Op=OLITERAL. See Node.mayBeShared. -type node struct { - // Tree structure. - // Generic recursive walks should follow these fields. - left Node - right Node - init Nodes - body Nodes - list Nodes - rlist Nodes - - // most nodes - typ *types.Type - orig Node // original form, for printing, and tracking copies of ONAMEs - - sym *types.Sym // various - opt interface{} - - // Various. Usually an offset into a struct. For example: - // - ONAME nodes that refer to local variables use it to identify their stack frame position. - // - ODOT, ODOTPTR, and ORESULT use it to indicate offset relative to their base address. - // - OSTRUCTKEY uses it to store the named field's offset. - // - Named OLITERALs use it to store their ambient iota value. - // - OINLMARK stores an index into the inlTree data structure. - // - OCLOSURE uses it to store ambient iota value, if any. - // Possibly still more uses. If you find any, document them. - offset int64 - - pos src.XPos - - flags bitset32 - - esc uint16 // EscXXX - - op Op - aux uint8 -} - -func (n *node) Left() Node { return n.left } -func (n *node) SetLeft(x Node) { n.left = x } -func (n *node) Right() Node { return n.right } -func (n *node) SetRight(x Node) { n.right = x } -func (n *node) Orig() Node { return n.orig } -func (n *node) SetOrig(x Node) { n.orig = x } -func (n *node) Type() *types.Type { return n.typ } -func (n *node) SetType(x *types.Type) { n.typ = x } -func (n *node) Func() *Func { return nil } -func (n *node) Name() *Name { return nil } -func (n *node) Sym() *types.Sym { return n.sym } -func (n *node) SetSym(x *types.Sym) { n.sym = x } -func (n *node) Pos() src.XPos { return n.pos } -func (n *node) SetPos(x src.XPos) { n.pos = x } -func (n *node) Offset() int64 { return n.offset } -func (n *node) SetOffset(x int64) { n.offset = x } -func (n *node) Esc() uint16 { return n.esc } -func (n *node) SetEsc(x uint16) { n.esc = x } -func (n *node) Op() Op { return n.op } -func (n *node) Init() Nodes { return n.init } -func (n *node) SetInit(x Nodes) { n.init = x } -func (n *node) PtrInit() *Nodes { return &n.init } -func (n *node) Body() Nodes { return n.body } -func (n *node) SetBody(x Nodes) { n.body = x } -func (n *node) PtrBody() *Nodes { return &n.body } -func (n *node) List() Nodes { return n.list } -func (n *node) SetList(x Nodes) { n.list = x } -func (n *node) PtrList() *Nodes { return &n.list } -func (n *node) Rlist() Nodes { return n.rlist } -func (n *node) SetRlist(x Nodes) { n.rlist = x } -func (n *node) PtrRlist() *Nodes { return &n.rlist } -func (n *node) MarkReadonly() { panic("node.MarkReadOnly") } -func (n *node) Val() constant.Value { panic("node.Val") } -func (n *node) SetVal(constant.Value) { panic("node.SetVal") } -func (n *node) Int64Val() int64 { panic("node.Int64Val") } -func (n *node) CanInt64() bool { return false } -func (n *node) Uint64Val() uint64 { panic("node.Uint64Val") } -func (n *node) BoolVal() bool { panic("node.BoolVal") } -func (n *node) StringVal() string { panic("node.StringVal") } - -// node can be Ntype only because of OXDOT of undefined name. -// When that moves into its own syntax, can drop this. -func (n *node) CanBeNtype() {} - -func (n *node) SetOp(op Op) { - if !okForNod[op] { - panic("cannot node.SetOp " + op.String()) - } - n.op = op -} - -func (n *node) ResetAux() { - n.aux = 0 -} - -func (n *node) SubOp() Op { - switch n.Op() { - case OASOP, ONAME: - default: - base.Fatalf("unexpected op: %v", n.Op()) - } - return Op(n.aux) -} - -func (n *node) SetSubOp(op Op) { - switch n.Op() { - case OASOP, ONAME: - default: - base.Fatalf("unexpected op: %v", n.Op()) - } - n.aux = uint8(op) -} - -func (n *node) IndexMapLValue() bool { - if n.Op() != OINDEXMAP { - base.Fatalf("unexpected op: %v", n.Op()) - } - return n.aux != 0 -} - -func (n *node) SetIndexMapLValue(b bool) { - if n.Op() != OINDEXMAP { - base.Fatalf("unexpected op: %v", n.Op()) - } - if b { - n.aux = 1 - } else { - n.aux = 0 - } -} - func IsSynthetic(n Node) bool { name := n.Sym().Name return name[0] == '.' || name[0] == '~' @@ -266,110 +132,6 @@ func IsAutoTmp(n Node) bool { return n.Name().AutoTemp() } -const ( - nodeClass, _ = iota, 1 << iota // PPARAM, PAUTO, PEXTERN, etc; three bits; first in the list because frequently accessed - _, _ // second nodeClass bit - _, _ // third nodeClass bit - nodeWalkdef, _ // tracks state during typecheckdef; 2 == loop detected; two bits - _, _ // second nodeWalkdef bit - nodeTypecheck, _ // tracks state during typechecking; 2 == loop detected; two bits - _, _ // second nodeTypecheck bit - nodeInitorder, _ // tracks state during init1; two bits - _, _ // second nodeInitorder bit - _, nodeHasBreak - _, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only - _, nodeImplicit // implicit OADDR or ODEREF; ++/-- statement represented as OASOP - _, nodeIsDDD // is the argument variadic - _, nodeDiag // already printed error about this - _, nodeColas // OAS resulting from := - _, nodeNonNil // guaranteed to be non-nil - _, nodeTransient // storage can be reused immediately after this statement - _, nodeBounded // bounds check unnecessary - _, nodeHasCall // expression contains a function call - _, nodeLikely // if statement condition likely -) - -func (n *node) Class() Class { return Class(n.flags.get3(nodeClass)) } -func (n *node) Walkdef() uint8 { return n.flags.get2(nodeWalkdef) } -func (n *node) Typecheck() uint8 { return n.flags.get2(nodeTypecheck) } -func (n *node) Initorder() uint8 { return n.flags.get2(nodeInitorder) } - -func (n *node) HasBreak() bool { return n.flags&nodeHasBreak != 0 } -func (n *node) NoInline() bool { return n.flags&nodeNoInline != 0 } -func (n *node) Implicit() bool { return n.flags&nodeImplicit != 0 } -func (n *node) IsDDD() bool { return n.flags&nodeIsDDD != 0 } -func (n *node) Diag() bool { return n.flags&nodeDiag != 0 } -func (n *node) Colas() bool { return n.flags&nodeColas != 0 } -func (n *node) NonNil() bool { return n.flags&nodeNonNil != 0 } -func (n *node) Transient() bool { return n.flags&nodeTransient != 0 } -func (n *node) Bounded() bool { return n.flags&nodeBounded != 0 } -func (n *node) HasCall() bool { return n.flags&nodeHasCall != 0 } -func (n *node) Likely() bool { return n.flags&nodeLikely != 0 } - -func (n *node) SetClass(b Class) { n.flags.set3(nodeClass, uint8(b)) } -func (n *node) SetWalkdef(b uint8) { n.flags.set2(nodeWalkdef, b) } -func (n *node) SetTypecheck(b uint8) { n.flags.set2(nodeTypecheck, b) } -func (n *node) SetInitorder(b uint8) { n.flags.set2(nodeInitorder, b) } - -func (n *node) SetHasBreak(b bool) { n.flags.set(nodeHasBreak, b) } -func (n *node) SetNoInline(b bool) { n.flags.set(nodeNoInline, b) } -func (n *node) SetImplicit(b bool) { n.flags.set(nodeImplicit, b) } -func (n *node) SetIsDDD(b bool) { n.flags.set(nodeIsDDD, b) } -func (n *node) SetDiag(b bool) { n.flags.set(nodeDiag, b) } -func (n *node) SetColas(b bool) { n.flags.set(nodeColas, b) } -func (n *node) SetTransient(b bool) { n.flags.set(nodeTransient, b) } -func (n *node) SetHasCall(b bool) { n.flags.set(nodeHasCall, b) } -func (n *node) SetLikely(b bool) { n.flags.set(nodeLikely, b) } - -// MarkNonNil marks a pointer n as being guaranteed non-nil, -// on all code paths, at all times. -// During conversion to SSA, non-nil pointers won't have nil checks -// inserted before dereferencing. See state.exprPtr. -func (n *node) MarkNonNil() { - if !n.Type().IsPtr() && !n.Type().IsUnsafePtr() { - base.Fatalf("MarkNonNil(%v), type %v", n, n.Type()) - } - n.flags.set(nodeNonNil, true) -} - -// SetBounded indicates whether operation n does not need safety checks. -// When n is an index or slice operation, n does not need bounds checks. -// When n is a dereferencing operation, n does not need nil checks. -// When n is a makeslice+copy operation, n does not need length and cap checks. -func (n *node) SetBounded(b bool) { - switch n.Op() { - case OINDEX, OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR: - // No bounds checks needed. - case ODOTPTR, ODEREF: - // No nil check needed. - case OMAKESLICECOPY: - // No length and cap checks needed - // since new slice and copied over slice data have same length. - default: - base.Fatalf("SetBounded(%v)", n) - } - n.flags.set(nodeBounded, b) -} - -// Opt returns the optimizer data for the node. -func (n *node) Opt() interface{} { - return n.opt -} - -// SetOpt sets the optimizer data for the node, which must not have been used with SetVal. -// SetOpt(nil) is ignored for Vals to simplify call sites that are clearing Opts. -func (n *node) SetOpt(x interface{}) { - n.opt = x -} - -func (n *node) Iota() int64 { - return n.Offset() -} - -func (n *node) SetIota(x int64) { - n.SetOffset(x) -} - // mayBeShared reports whether n may occur in multiple places in the AST. // Extra care must be taken when mutating such a node. func MayBeShared(n Node) bool { @@ -380,10 +142,6 @@ func MayBeShared(n Node) bool { return false } -// The compiler needs *Node to be assignable to cmd/compile/internal/ssa.Sym. -func (n *node) CanBeAnSSASym() { -} - //go:generate stringer -type=Op -trimprefix=O type Op uint8 @@ -922,91 +680,15 @@ func OrigSym(s *types.Sym) *types.Sym { return s } -// SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max]. -// n must be a slice expression. max is nil if n is a simple slice expression. -func (n *node) SliceBounds() (low, high, max Node) { - if n.List().Len() == 0 { - return nil, nil, nil - } - - switch n.Op() { - case OSLICE, OSLICEARR, OSLICESTR: - s := n.List().Slice() - return s[0], s[1], nil - case OSLICE3, OSLICE3ARR: - s := n.List().Slice() - return s[0], s[1], s[2] - } - base.Fatalf("SliceBounds op %v: %v", n.Op(), n) - return nil, nil, nil -} - -// SetSliceBounds sets n's slice bounds, where n is a slice expression. -// n must be a slice expression. If max is non-nil, n must be a full slice expression. -func (n *node) SetSliceBounds(low, high, max Node) { - switch n.Op() { - case OSLICE, OSLICEARR, OSLICESTR: - if max != nil { - base.Fatalf("SetSliceBounds %v given three bounds", n.Op()) - } - s := n.List().Slice() - if s == nil { - if low == nil && high == nil { - return - } - n.PtrList().Set2(low, high) - return - } - s[0] = low - s[1] = high - return - case OSLICE3, OSLICE3ARR: - s := n.List().Slice() - if s == nil { - if low == nil && high == nil && max == nil { - return - } - n.PtrList().Set3(low, high, max) - return - } - s[0] = low - s[1] = high - s[2] = max - return - } - base.Fatalf("SetSliceBounds op %v: %v", n.Op(), n) -} - -// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR). -// o must be a slicing op. -func (o Op) IsSlice3() bool { - switch o { - case OSLICE, OSLICEARR, OSLICESTR: - return false - case OSLICE3, OSLICE3ARR: - return true - } - base.Fatalf("IsSlice3 op %v", o) - return false -} - func IsConst(n Node, ct constant.Kind) bool { return ConstType(n) == ct } -// rawcopy returns a shallow copy of n. -// Note: copy or sepcopy (rather than rawcopy) is usually the -// correct choice (see comment with Node.copy, below). -func (n *node) RawCopy() Node { - copy := *n - return © -} - // isNil reports whether n represents the universal untyped zero value "nil". func IsNil(n Node) bool { // Check n.Orig because constant propagation may produce typed nil constants, // which don't exist in the Go spec. - return Orig(n).Op() == ONIL + return n != nil && Orig(n).Op() == ONIL } func IsBlank(n Node) bool { @@ -1027,8 +709,26 @@ func Nod(op Op, nleft, nright Node) Node { } func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { - var n *node switch op { + default: + panic("NodAt " + op.String()) + case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, + OLSH, OLT, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSUB, OXOR, + OCOPY, OCOMPLEX, + OEFACE: + return NewBinaryExpr(pos, op, nleft, nright) + case OADDR, OPTRLIT: + return NewAddrExpr(pos, nleft) + case OADDSTR: + return NewAddStringExpr(pos, nil) + case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT: + var typ Ntype + if nright != nil { + typ = nright.(Ntype) + } + n := NewCompLitExpr(pos, typ, nil) + n.SetOp(op) + return n case OAS, OSELRECV: n := NewAssignStmt(pos, nleft, nright) n.SetOp(op) @@ -1039,12 +739,27 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { return n case OASOP: return NewAssignOpStmt(pos, OXXX, nleft, nright) + case OBITNOT, ONEG, ONOT, OPLUS, ORECV, + OALIGNOF, OCAP, OCLOSE, OIMAG, OLEN, ONEW, ONEWOBJ, + OOFFSETOF, OPANIC, OREAL, OSIZEOF, + OCHECKNIL, OCFUNC, OIDATA, OITAB, OSPTR, OVARDEF, OVARKILL, OVARLIVE: + if nright != nil { + panic("unary nright") + } + return NewUnaryExpr(pos, op, nleft) case OBLOCK: return NewBlockStmt(pos, nil) case OBREAK, OCONTINUE, OFALL, OGOTO, ORETJMP: return NewBranchStmt(pos, op, nil) + case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, + OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER: + n := NewCallExpr(pos, nleft, nil) + n.SetOp(op) + return n case OCASE: return NewCaseStmt(pos, nil, nil) + case OCONV, OCONVIFACE, OCONVNOP, ORUNESTR: + return NewConvExpr(pos, op, nil, nleft) case ODCL, ODCLCONST, ODCLTYPE: return NewDecl(pos, op, nleft) case ODCLFUNC: @@ -1053,6 +768,18 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { return NewDeferStmt(pos, nleft) case ODEREF: return NewStarExpr(pos, nleft) + case ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT: + n := NewSelectorExpr(pos, nleft, nil) + n.SetOp(op) + return n + case ODOTTYPE, ODOTTYPE2: + var typ Ntype + if nright != nil { + typ = nright.(Ntype) + } + n := NewTypeAssertExpr(pos, nleft, typ) + n.SetOp(op) + return n case OEMPTY: return NewEmptyStmt(pos) case OFOR: @@ -1061,140 +788,51 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { return NewGoStmt(pos, nleft) case OIF: return NewIfStmt(pos, nleft, nil, nil) + case OINDEX, OINDEXMAP: + n := NewIndexExpr(pos, nleft, nright) + n.SetOp(op) + return n case OINLMARK: return NewInlineMarkStmt(pos, types.BADWIDTH) + case OKEY, OSTRUCTKEY: + n := NewKeyExpr(pos, nleft, nright) + n.SetOp(op) + return n case OLABEL: return NewLabelStmt(pos, nil) case OLITERAL, OTYPE, OIOTA: n := newNameAt(pos, nil) n.SetOp(op) return n + case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY: + return NewMakeExpr(pos, op, nleft, nright) + case OMETHEXPR: + return NewMethodExpr(pos, op, nleft, nright) + case ONIL: + return NewNilExpr(pos) case OPACK: return NewPkgName(pos, nil, nil) + case OPAREN: + return NewParenExpr(pos, nleft) case ORANGE: return NewRangeStmt(pos, nil, nright, nil) + case ORESULT: + return NewResultExpr(pos, nil, types.BADWIDTH) case ORETURN: return NewReturnStmt(pos, nil) case OSELECT: return NewSelectStmt(pos, nil) case OSEND: return NewSendStmt(pos, nleft, nright) + case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: + return NewSliceExpr(pos, op, nleft) + case OSLICEHEADER: + return NewSliceHeaderExpr(pos, nil, nleft, nil, nil) case OSWITCH: return NewSwitchStmt(pos, nleft, nil) case OTYPESW: return NewTypeSwitchGuard(pos, nleft, nright) - default: - n = new(node) + case OINLCALL: + return NewInlinedCallExpr(pos, nil, nil) } - n.SetOp(op) - n.SetLeft(nleft) - n.SetRight(nright) - n.SetPos(pos) - n.SetOffset(types.BADWIDTH) - n.SetOrig(n) - return n -} - -var okForNod = [OEND]bool{ - OADD: true, - OADDR: true, - OADDSTR: true, - OALIGNOF: true, - OAND: true, - OANDAND: true, - OANDNOT: true, - OAPPEND: true, - OARRAYLIT: true, - OBITNOT: true, - OBYTES2STR: true, - OBYTES2STRTMP: true, - OCALL: true, - OCALLFUNC: true, - OCALLINTER: true, - OCALLMETH: true, - OCAP: true, - OCFUNC: true, - OCHECKNIL: true, - OCLOSE: true, - OCOMPLEX: true, - OCOMPLIT: true, - OCONV: true, - OCONVIFACE: true, - OCONVNOP: true, - OCOPY: true, - ODELETE: true, - ODIV: true, - ODOT: true, - ODOTINTER: true, - ODOTMETH: true, - ODOTPTR: true, - ODOTTYPE: true, - ODOTTYPE2: true, - OEFACE: true, - OEQ: true, - OGE: true, - OGETG: true, - OGT: true, - OIDATA: true, - OIMAG: true, - OINDEX: true, - OINDEXMAP: true, - OINLCALL: true, - OITAB: true, - OKEY: true, - OLE: true, - OLEN: true, - OLSH: true, - OLT: true, - OMAKE: true, - OMAKECHAN: true, - OMAKEMAP: true, - OMAKESLICE: true, - OMAKESLICECOPY: true, - OMAPLIT: true, - OMETHEXPR: true, - OMOD: true, - OMUL: true, - ONE: true, - ONEG: true, - ONEW: true, - ONEWOBJ: true, - ONIL: true, - ONOT: true, - OOFFSETOF: true, - OOR: true, - OOROR: true, - OPANIC: true, - OPAREN: true, - OPLUS: true, - OPRINT: true, - OPRINTN: true, - OPTRLIT: true, - OREAL: true, - ORECOVER: true, - ORECV: true, - ORESULT: true, - ORSH: true, - ORUNES2STR: true, - ORUNESTR: true, - OSIZEOF: true, - OSLICE: true, - OSLICE3: true, - OSLICE3ARR: true, - OSLICEARR: true, - OSLICEHEADER: true, - OSLICELIT: true, - OSLICESTR: true, - OSPTR: true, - OSTR2BYTES: true, - OSTR2BYTESTMP: true, - OSTR2RUNES: true, - OSTRUCTKEY: true, - OSTRUCTLIT: true, - OSUB: true, - OVARDEF: true, - OVARKILL: true, - OVARLIVE: true, - OXDOT: true, - OXOR: true, } diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go index 2f31ba8d34..4a133cb999 100644 --- a/src/cmd/compile/internal/ir/sizeof_test.go +++ b/src/cmd/compile/internal/ir/sizeof_test.go @@ -22,7 +22,6 @@ func TestSizeof(t *testing.T) { }{ {Func{}, 168, 288}, {Name{}, 128, 224}, - {node{}, 80, 136}, } for _, tt := range tests { From 45f3b646d42d73a8a54c81ada0ef1ffc11dce592 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 29 Nov 2020 23:06:02 -0500 Subject: [PATCH 049/212] [dev.regabi] cmd/compile: add OSTMTEXPR Op This CL only adds the new constant, which is not safe for toolstash -cmp. Change-Id: I774463a0ab5f57113d67a8888b6ac787be68510c Reviewed-on: https://go-review.googlesource.com/c/go/+/274110 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/node.go | 1 + src/cmd/compile/internal/ir/op_string.go | 87 ++++++++++++------------ 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 9b407b36c0..a93a87fb68 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -288,6 +288,7 @@ const ( OOFFSETOF // unsafe.Offsetof(Left) OSIZEOF // unsafe.Sizeof(Left) OMETHEXPR // method expression + OSTMTEXPR // statement expression (Init; Left) // statements OBLOCK // { List } (block of code) diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index eefdc0ee59..96eee43974 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -121,52 +121,53 @@ func _() { _ = x[OOFFSETOF-110] _ = x[OSIZEOF-111] _ = x[OMETHEXPR-112] - _ = x[OBLOCK-113] - _ = x[OBREAK-114] - _ = x[OCASE-115] - _ = x[OCONTINUE-116] - _ = x[ODEFER-117] - _ = x[OEMPTY-118] - _ = x[OFALL-119] - _ = x[OFOR-120] - _ = x[OFORUNTIL-121] - _ = x[OGOTO-122] - _ = x[OIF-123] - _ = x[OLABEL-124] - _ = x[OGO-125] - _ = x[ORANGE-126] - _ = x[ORETURN-127] - _ = x[OSELECT-128] - _ = x[OSWITCH-129] - _ = x[OTYPESW-130] - _ = x[OTCHAN-131] - _ = x[OTMAP-132] - _ = x[OTSTRUCT-133] - _ = x[OTINTER-134] - _ = x[OTFUNC-135] - _ = x[OTARRAY-136] - _ = x[OTSLICE-137] - _ = x[OINLCALL-138] - _ = x[OEFACE-139] - _ = x[OITAB-140] - _ = x[OIDATA-141] - _ = x[OSPTR-142] - _ = x[OCLOSUREREAD-143] - _ = x[OCFUNC-144] - _ = x[OCHECKNIL-145] - _ = x[OVARDEF-146] - _ = x[OVARKILL-147] - _ = x[OVARLIVE-148] - _ = x[ORESULT-149] - _ = x[OINLMARK-150] - _ = x[ORETJMP-151] - _ = x[OGETG-152] - _ = x[OEND-153] + _ = x[OSTMTEXPR-113] + _ = x[OBLOCK-114] + _ = x[OBREAK-115] + _ = x[OCASE-116] + _ = x[OCONTINUE-117] + _ = x[ODEFER-118] + _ = x[OEMPTY-119] + _ = x[OFALL-120] + _ = x[OFOR-121] + _ = x[OFORUNTIL-122] + _ = x[OGOTO-123] + _ = x[OIF-124] + _ = x[OLABEL-125] + _ = x[OGO-126] + _ = x[ORANGE-127] + _ = x[ORETURN-128] + _ = x[OSELECT-129] + _ = x[OSWITCH-130] + _ = x[OTYPESW-131] + _ = x[OTCHAN-132] + _ = x[OTMAP-133] + _ = x[OTSTRUCT-134] + _ = x[OTINTER-135] + _ = x[OTFUNC-136] + _ = x[OTARRAY-137] + _ = x[OTSLICE-138] + _ = x[OINLCALL-139] + _ = x[OEFACE-140] + _ = x[OITAB-141] + _ = x[OIDATA-142] + _ = x[OSPTR-143] + _ = x[OCLOSUREREAD-144] + _ = x[OCFUNC-145] + _ = x[OCHECKNIL-146] + _ = x[OVARDEF-147] + _ = x[OVARKILL-148] + _ = x[OVARLIVE-149] + _ = x[ORESULT-150] + _ = x[OINLMARK-151] + _ = x[ORETJMP-152] + _ = x[OGETG-153] + _ = x[OEND-154] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCLOSUREREADCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRSTMTEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCLOSUREREADCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 309, 315, 318, 324, 331, 339, 343, 350, 358, 360, 362, 364, 366, 368, 370, 375, 380, 388, 391, 400, 403, 407, 415, 422, 431, 444, 447, 450, 453, 456, 459, 462, 468, 471, 477, 480, 486, 490, 493, 497, 502, 507, 513, 518, 522, 527, 535, 543, 549, 558, 569, 576, 580, 587, 594, 602, 606, 610, 614, 621, 628, 636, 642, 650, 655, 660, 664, 672, 677, 682, 686, 689, 697, 701, 703, 708, 710, 715, 721, 727, 733, 739, 744, 748, 755, 761, 766, 772, 778, 785, 790, 794, 799, 803, 814, 819, 827, 833, 840, 847, 853, 860, 866, 870, 873} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 309, 315, 318, 324, 331, 339, 343, 350, 358, 360, 362, 364, 366, 368, 370, 375, 380, 388, 391, 400, 403, 407, 415, 422, 431, 444, 447, 450, 453, 456, 459, 462, 468, 471, 477, 480, 486, 490, 493, 497, 502, 507, 513, 518, 522, 527, 535, 543, 549, 558, 569, 576, 580, 587, 594, 602, 606, 610, 614, 621, 628, 636, 642, 650, 658, 663, 668, 672, 680, 685, 690, 694, 697, 705, 709, 711, 716, 718, 723, 729, 735, 741, 747, 752, 756, 763, 769, 774, 780, 786, 793, 798, 802, 807, 811, 822, 827, 835, 841, 848, 855, 861, 868, 874, 878, 881} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { From f3741bdf7cab5fc8254bebce00479c0168ace86c Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Mon, 30 Nov 2020 16:32:41 -0800 Subject: [PATCH 050/212] doc/go1.16: add crypto/x509 note about Verify on Windows Updates #42897 Change-Id: Ice25922475405aca3cf2cb1c163462f223ede736 Reviewed-on: https://go-review.googlesource.com/c/go/+/274239 Trust: Roland Shoemaker Reviewed-by: Dmitri Shuralyov --- doc/go1.16.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 6e371b9617..71cd7e259e 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -416,7 +416,9 @@ Do not send CLs removing the interior tags from such phrases.

- TODO: https://golang.org/cl/257257: return additional chains from Verify on Windows + On Windows, Certificate.Verify + will now return all certificate chains that are built by the platform + certificate verifier, instead of just the highest ranked chain.

From a36ba090fd647e741668629527e25c657c40f8f3 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Fri, 27 Nov 2020 02:06:08 +1100 Subject: [PATCH 051/212] cmd/link/internal/amd64: always generate R_X86_64_PLT32 for SDYNIMPORT calls Currently, in the non-DynlinkingGo case with external linking, we generate a R_X86_64_GOTPCREL relocation for the imported symbol. This results in the external linker turning this into a R_X86_64_GLOB_DAT relocation, rather than a R_X86_64_JUMP_SLOT. Always generate R_X86_64_PLT32 for SDYNIMPORT calls so that these calls work correctly. Update #36435 Fixes #42671 Change-Id: I8a28884b7853cb4135053ed817bedc919482f4ad Reviewed-on: https://go-review.googlesource.com/c/go/+/270377 Trust: Joel Sing Run-TryBot: Cherry Zhang Reviewed-by: Cherry Zhang --- src/cmd/link/internal/amd64/asm.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index 360c5338ba..2d09a6160a 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -413,11 +413,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, case objabi.R_CALL: if siz == 4 { if ldr.SymType(r.Xsym) == sym.SDYNIMPORT { - if ctxt.DynlinkingGo() { - out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32) - } else { - out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32) - } + out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32) } else { out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32) } From f5978a09589badb927d3aa96998fc785524cae02 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sun, 22 Nov 2020 11:52:55 +1100 Subject: [PATCH 052/212] cmd/internal/obj/riscv: add tests for BGE/BGEU/BLT/BLTU Add tests for BGE/BGEU/BLT/BLTU branch instructions. Also add pure Go variants of these to ensure that the test data, Go and assembly all match up. Change-Id: I84c68605e116a4e57f6c5c765bf0aaecab84b675 Reviewed-on: https://go-review.googlesource.com/c/go/+/271913 Trust: Joel Sing Reviewed-by: Quey-Liang Kao Reviewed-by: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot --- .../riscv/testdata/testbranch/branch_test.go | 54 ++++++++++++++++++- .../riscv/testdata/testbranch/branch_test.s | 44 +++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go index 803ba8c77c..5412577a05 100644 --- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go +++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go @@ -11,6 +11,8 @@ import ( ) func testBEQZ(a int64) (r bool) +func testBGE(a, b int64) (r bool) +func testBGEU(a, b int64) (r bool) func testBGEZ(a int64) (r bool) func testBGT(a, b int64) (r bool) func testBGTU(a, b int64) (r bool) @@ -18,6 +20,8 @@ func testBGTZ(a int64) (r bool) func testBLE(a, b int64) (r bool) func testBLEU(a, b int64) (r bool) func testBLEZ(a int64) (r bool) +func testBLT(a, b int64) (r bool) +func testBLTU(a, b int64) (r bool) func testBLTZ(a int64) (r bool) func testBNEZ(a int64) (r bool) @@ -29,6 +33,16 @@ func TestBranchCondition(t *testing.T) { fn func(a, b int64) bool want bool }{ + {"BGE", 0, 1, testBGE, false}, + {"BGE", 0, 0, testBGE, true}, + {"BGE", 0, -1, testBGE, true}, + {"BGE", -1, 0, testBGE, false}, + {"BGE", 1, 0, testBGE, true}, + {"BGEU", 0, 1, testBGEU, false}, + {"BGEU", 0, 0, testBGEU, true}, + {"BGEU", 0, -1, testBGEU, false}, + {"BGEU", -1, 0, testBGEU, true}, + {"BGEU", 1, 0, testBGEU, true}, {"BGT", 0, 1, testBGT, true}, {"BGT", 0, 0, testBGT, false}, {"BGT", 0, -1, testBGT, false}, @@ -48,11 +62,49 @@ func TestBranchCondition(t *testing.T) { {"BLEU", 0, 0, testBLEU, true}, {"BLEU", -1, 0, testBLEU, true}, {"BLEU", 1, 0, testBLEU, true}, + {"BLT", 0, 1, testBLT, true}, + {"BLT", 0, -1, testBLT, false}, + {"BLT", 0, 0, testBLT, false}, + {"BLT", -1, 0, testBLT, true}, + {"BLT", 1, 0, testBLT, false}, + {"BLTU", 0, 1, testBLTU, true}, + {"BLTU", 0, -1, testBLTU, true}, + {"BLTU", 0, 0, testBLTU, false}, + {"BLTU", -1, 0, testBLTU, false}, + {"BLTU", 1, 0, testBLTU, false}, } for _, test := range tests { t.Run(test.ins, func(t *testing.T) { + var fn func(a, b int64) bool + switch test.ins { + case "BGE": + fn = func(a, b int64) bool { return a >= b } + case "BGEU": + fn = func(a, b int64) bool { return uint64(a) >= uint64(b) } + case "BGT": + // TODO: Currently reversed. + fn = func(a, b int64) bool { return b > a } + case "BGTU": + // TODO: Currently reversed. + fn = func(a, b int64) bool { return uint64(b) > uint64(a) } + case "BLE": + // TODO: Currently reversed. + fn = func(a, b int64) bool { return b <= a } + case "BLEU": + // TODO: Currently reversed. + fn = func(a, b int64) bool { return uint64(b) <= uint64(a) } + case "BLT": + fn = func(a, b int64) bool { return a < b } + case "BLTU": + fn = func(a, b int64) bool { return uint64(a) < uint64(b) } + default: + t.Fatalf("Unknown instruction %q", test.ins) + } + if got := fn(test.a, test.b); got != test.want { + t.Errorf("Go %v %v, %v = %v, want %v", test.ins, test.a, test.b, got, test.want) + } if got := test.fn(test.a, test.b); got != test.want { - t.Errorf("%v %v, %v = %v, want %v", test.ins, test.a, test.b, got, test.want) + t.Errorf("Assembly %v %v, %v = %v, want %v", test.ins, test.a, test.b, got, test.want) } }) } diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s index 6cff235848..8dd6f563af 100644 --- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s +++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s @@ -16,6 +16,28 @@ b: MOV X6, r+8(FP) RET +// func testBGE(a, b int64) (r bool) +TEXT ·testBGE(SB),NOSPLIT,$0-0 + MOV a+0(FP), X5 + MOV b+8(FP), X6 + MOV $1, X7 + BGE X5, X6, b + MOV $0, X7 +b: + MOV X7, r+16(FP) + RET + +// func testBGEU(a, b int64) (r bool) +TEXT ·testBGEU(SB),NOSPLIT,$0-0 + MOV a+0(FP), X5 + MOV b+8(FP), X6 + MOV $1, X7 + BGEU X5, X6, b + MOV $0, X7 +b: + MOV X7, r+16(FP) + RET + // func testBGEZ(a int64) (r bool) TEXT ·testBGEZ(SB),NOSPLIT,$0-0 MOV a+0(FP), X5 @@ -90,6 +112,28 @@ b: MOV X6, r+8(FP) RET +// func testBLT(a, b int64) (r bool) +TEXT ·testBLT(SB),NOSPLIT,$0-0 + MOV a+0(FP), X5 + MOV b+8(FP), X6 + MOV $1, X7 + BLT X5, X6, b + MOV $0, X7 +b: + MOV X7, r+16(FP) + RET + +// func testBLTU(a, b int64) (r bool) +TEXT ·testBLTU(SB),NOSPLIT,$0-0 + MOV a+0(FP), X5 + MOV b+8(FP), X6 + MOV $1, X7 + BLTU X5, X6, b + MOV $0, X7 +b: + MOV X7, r+16(FP) + RET + // func testBLTZ(a int64) (r bool) TEXT ·testBLTZ(SB),NOSPLIT,$0-0 MOV a+0(FP), X5 From dadfc80bc173ce4475bc76231de5259d797b0522 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 30 Nov 2020 20:34:25 -0800 Subject: [PATCH 053/212] [dev.regabi] cmd/compile: improve findTypeLoop When checking if a defined type is part of a type loop, we can short-circuit if it was defined in another package. We can assume any package we import already successfully compiled, so any types it contains cannot be part of a type loop. This also allows us to simplify the logic for recursing into the type used in the type declaration, because any defined type from this package will have a properly setup node. Change-Id: Ic024814d95533afd9e59f2103c8ddb22bd87e900 Reviewed-on: https://go-review.googlesource.com/c/go/+/274294 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/align.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index 4f8f04d73d..ffae8dc27b 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -190,6 +190,13 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { // recurse on the type expression used in the type // declaration. + // Type imported from package, so it can't be part of + // a type loop (otherwise that package should have + // failed to compile). + if t.Sym.Pkg != ir.LocalPkg { + return false + } + for i, x := range *path { if x == t { *path = (*path)[i:] @@ -198,10 +205,8 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { } *path = append(*path, t) - if n := ir.AsNode(t.Nod); n != nil { - if name := n.Name(); name != nil && name.Ntype != nil && findTypeLoop(name.Ntype.Type(), path) { - return true - } + if findTypeLoop(ir.AsNode(t.Nod).Name().Ntype.Type(), path) { + return true } *path = (*path)[:len(*path)-1] } else { From 4da41fb3f8aa2e81b6ed371b617643042ba5e170 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 30 Nov 2020 21:18:48 -0500 Subject: [PATCH 054/212] [dev.regabi] cmd/compile: use ir.Copy instead of direct use of RawCopy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ONIL export bug happened because the logic about maintaining an “implicit” orig pointer in the comments around ir.Orig only applies to Copy and SepCopy, not to direct use of RawCopy. I'd forgotten those could exist. The sole direct use of RawCopy was for the OLITERAL/ONIL case. The ONIL is now provably indistinguishable from Copy, since NilExpr does not have an explicit Orig field, so for NilExpr RawCopy and Copy are the same. The OLITERAL is not, but we can reconstruct the effect with Copy+SetOrig to be explicit that we need the orig link. The next CL will unexport RawCopy. Also fix a typo in MapType doc comment. Passes buildall w/ toolstash -cmp. Change-Id: I876a85ff188e6d1cd4c0dfa385be32482e0de0d4 Reviewed-on: https://go-review.googlesource.com/c/go/+/274292 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/const.go | 7 ++++++- src/cmd/compile/internal/ir/type.go | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 3c161d8e12..4dee373bfa 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -118,7 +118,12 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir if n.Op() == ir.OLITERAL || n.Op() == ir.ONIL { // Can't always set n.Type directly on OLITERAL nodes. // See discussion on CL 20813. - n = n.RawCopy() + old := n + n = ir.Copy(old) + if old.Op() == ir.OLITERAL { + // Keep untyped constants in their original untyped syntax for error messages. + n.(ir.OrigNode).SetOrig(old) + } } // Nil is technically not a constant, so handle it specially. diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index 39411ed431..519a7291b0 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -92,7 +92,7 @@ func (n *ChanType) DeepCopy(pos src.XPos) Node { return NewChanType(n.posOr(pos), DeepCopy(pos, n.Elem), n.Dir) } -// A MapType represents a map[Key]Value type syntax.u +// A MapType represents a map[Key]Value type syntax. type MapType struct { miniType Key Node From ecff7628ead3b0191f5fe191864ee47fcc90bb92 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 30 Nov 2020 21:20:45 -0500 Subject: [PATCH 055/212] [dev.regabi] cmd/compile: unexport Node.RawCopy RawCopy breaks the invariant that ir.Orig depends on for allowing nodes to omit keeping their own orig fields. Avoid surprises by unexporting it. The only use in package gc was removed in the previous CL. This one is a straight global search and replace RawCopy -> rawCopy. Change-Id: Ia99c0f4665bf7ed4f878cc44456d5fbdf33bab8d Reviewed-on: https://go-review.googlesource.com/c/go/+/274293 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/ir/copy.go | 4 +-- src/cmd/compile/internal/ir/expr.go | 46 ++++++++++++++--------------- src/cmd/compile/internal/ir/func.go | 2 +- src/cmd/compile/internal/ir/mini.go | 2 +- src/cmd/compile/internal/ir/name.go | 4 +-- src/cmd/compile/internal/ir/node.go | 2 +- src/cmd/compile/internal/ir/stmt.go | 40 ++++++++++++------------- src/cmd/compile/internal/ir/type.go | 16 +++++----- 8 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/cmd/compile/internal/ir/copy.go b/src/cmd/compile/internal/ir/copy.go index 7a1611d0d6..a356074bb8 100644 --- a/src/cmd/compile/internal/ir/copy.go +++ b/src/cmd/compile/internal/ir/copy.go @@ -43,7 +43,7 @@ func Orig(n Node) Node { // SepCopy returns a separate shallow copy of n, // breaking any Orig link to any other nodes. func SepCopy(n Node) Node { - n = n.RawCopy() + n = n.rawCopy() if n, ok := n.(OrigNode); ok { n.SetOrig(n) } @@ -57,7 +57,7 @@ func SepCopy(n Node) Node { // The specific semantics surrounding Orig are subtle but right for most uses. // See issues #26855 and #27765 for pitfalls. func Copy(n Node) Node { - copy := n.RawCopy() + copy := n.rawCopy() if n, ok := n.(OrigNode); ok && n.Orig() == n { copy.(OrigNode).SetOrig(copy) } diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index be9f486682..87593520a1 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -75,7 +75,7 @@ func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr { func (n *AddStringExpr) String() string { return fmt.Sprint(n) } func (n *AddStringExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AddStringExpr) RawCopy() Node { c := *n; return &c } +func (n *AddStringExpr) rawCopy() Node { c := *n; return &c } func (n *AddStringExpr) List() Nodes { return n.list } func (n *AddStringExpr) PtrList() *Nodes { return &n.list } func (n *AddStringExpr) SetList(x Nodes) { n.list = x } @@ -97,7 +97,7 @@ func NewAddrExpr(pos src.XPos, x Node) *AddrExpr { func (n *AddrExpr) String() string { return fmt.Sprint(n) } func (n *AddrExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AddrExpr) RawCopy() Node { c := *n; return &c } +func (n *AddrExpr) rawCopy() Node { c := *n; return &c } func (n *AddrExpr) Left() Node { return n.X } func (n *AddrExpr) SetLeft(x Node) { n.X = x } func (n *AddrExpr) Right() Node { return n.Alloc } @@ -129,7 +129,7 @@ func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr { func (n *BinaryExpr) String() string { return fmt.Sprint(n) } func (n *BinaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *BinaryExpr) RawCopy() Node { c := *n; return &c } +func (n *BinaryExpr) rawCopy() Node { c := *n; return &c } func (n *BinaryExpr) Left() Node { return n.X } func (n *BinaryExpr) SetLeft(x Node) { n.X = x } func (n *BinaryExpr) Right() Node { return n.Y } @@ -170,7 +170,7 @@ func NewCallExpr(pos src.XPos, fun Node, args []Node) *CallExpr { func (n *CallExpr) String() string { return fmt.Sprint(n) } func (n *CallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CallExpr) RawCopy() Node { c := *n; return &c } +func (n *CallExpr) rawCopy() Node { c := *n; return &c } func (n *CallExpr) Orig() Node { return n.orig } func (n *CallExpr) SetOrig(x Node) { n.orig = x } func (n *CallExpr) Left() Node { return n.X } @@ -218,7 +218,7 @@ func NewCallPartExpr(pos src.XPos, x Node, method *Name, fn *Func) *CallPartExpr func (n *CallPartExpr) String() string { return fmt.Sprint(n) } func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CallPartExpr) RawCopy() Node { c := *n; return &c } +func (n *CallPartExpr) rawCopy() Node { c := *n; return &c } func (n *CallPartExpr) Func() *Func { return n.fn } func (n *CallPartExpr) Left() Node { return n.X } func (n *CallPartExpr) Right() Node { return n.Method } @@ -240,7 +240,7 @@ func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr { func (n *ClosureExpr) String() string { return fmt.Sprint(n) } func (n *ClosureExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ClosureExpr) RawCopy() Node { c := *n; return &c } +func (n *ClosureExpr) rawCopy() Node { c := *n; return &c } func (n *ClosureExpr) Func() *Func { return n.fn } // A ClosureRead denotes reading a variable stored within a closure struct. @@ -258,7 +258,7 @@ func NewClosureRead(typ *types.Type, offset int64) *ClosureRead { func (n *ClosureRead) String() string { return fmt.Sprint(n) } func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ClosureRead) RawCopy() Node { c := *n; return &c } +func (n *ClosureRead) rawCopy() Node { c := *n; return &c } func (n *ClosureRead) Type() *types.Type { return n.typ } func (n *ClosureRead) Offset() int64 { return n.offset } @@ -282,7 +282,7 @@ func NewCompLitExpr(pos src.XPos, typ Ntype, list []Node) *CompLitExpr { func (n *CompLitExpr) String() string { return fmt.Sprint(n) } func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CompLitExpr) RawCopy() Node { c := *n; return &c } +func (n *CompLitExpr) rawCopy() Node { c := *n; return &c } func (n *CompLitExpr) Orig() Node { return n.orig } func (n *CompLitExpr) SetOrig(x Node) { n.orig = x } func (n *CompLitExpr) Right() Node { return n.Ntype } @@ -319,7 +319,7 @@ func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr { func (n *ConvExpr) String() string { return fmt.Sprint(n) } func (n *ConvExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ConvExpr) RawCopy() Node { c := *n; return &c } +func (n *ConvExpr) rawCopy() Node { c := *n; return &c } func (n *ConvExpr) Orig() Node { return n.orig } func (n *ConvExpr) SetOrig(x Node) { n.orig = x } func (n *ConvExpr) Left() Node { return n.X } @@ -351,7 +351,7 @@ func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr { func (n *IndexExpr) String() string { return fmt.Sprint(n) } func (n *IndexExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *IndexExpr) RawCopy() Node { c := *n; return &c } +func (n *IndexExpr) rawCopy() Node { c := *n; return &c } func (n *IndexExpr) Left() Node { return n.X } func (n *IndexExpr) SetLeft(x Node) { n.X = x } func (n *IndexExpr) Right() Node { return n.Index } @@ -388,7 +388,7 @@ func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr { func (n *KeyExpr) String() string { return fmt.Sprint(n) } func (n *KeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *KeyExpr) RawCopy() Node { c := *n; return &c } +func (n *KeyExpr) rawCopy() Node { c := *n; return &c } func (n *KeyExpr) Left() Node { return n.Key } func (n *KeyExpr) SetLeft(x Node) { n.Key = x } func (n *KeyExpr) Right() Node { return n.Value } @@ -425,7 +425,7 @@ func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { func (n *InlinedCallExpr) String() string { return fmt.Sprint(n) } func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *InlinedCallExpr) RawCopy() Node { c := *n; return &c } +func (n *InlinedCallExpr) rawCopy() Node { c := *n; return &c } func (n *InlinedCallExpr) Body() Nodes { return n.body } func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.body } func (n *InlinedCallExpr) SetBody(x Nodes) { n.body = x } @@ -451,7 +451,7 @@ func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr { func (n *MakeExpr) String() string { return fmt.Sprint(n) } func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *MakeExpr) RawCopy() Node { c := *n; return &c } +func (n *MakeExpr) rawCopy() Node { c := *n; return &c } func (n *MakeExpr) Left() Node { return n.Len } func (n *MakeExpr) SetLeft(x Node) { n.Len = x } func (n *MakeExpr) Right() Node { return n.Cap } @@ -486,7 +486,7 @@ func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr { func (n *MethodExpr) String() string { return fmt.Sprint(n) } func (n *MethodExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *MethodExpr) RawCopy() Node { c := *n; return &c } +func (n *MethodExpr) rawCopy() Node { c := *n; return &c } func (n *MethodExpr) Left() Node { return n.X } func (n *MethodExpr) SetLeft(x Node) { n.X = x } func (n *MethodExpr) Right() Node { return n.M } @@ -514,7 +514,7 @@ func NewNilExpr(pos src.XPos) *NilExpr { func (n *NilExpr) String() string { return fmt.Sprint(n) } func (n *NilExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *NilExpr) RawCopy() Node { c := *n; return &c } +func (n *NilExpr) rawCopy() Node { c := *n; return &c } func (n *NilExpr) Sym() *types.Sym { return n.sym } func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x } @@ -534,7 +534,7 @@ func NewParenExpr(pos src.XPos, x Node) *ParenExpr { func (n *ParenExpr) String() string { return fmt.Sprint(n) } func (n *ParenExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ParenExpr) RawCopy() Node { c := *n; return &c } +func (n *ParenExpr) rawCopy() Node { c := *n; return &c } func (n *ParenExpr) Left() Node { return n.X } func (n *ParenExpr) SetLeft(x Node) { n.X = x } @@ -566,7 +566,7 @@ func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr { func (n *ResultExpr) String() string { return fmt.Sprint(n) } func (n *ResultExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ResultExpr) RawCopy() Node { c := *n; return &c } +func (n *ResultExpr) rawCopy() Node { c := *n; return &c } func (n *ResultExpr) Offset() int64 { return n.offset } func (n *ResultExpr) SetOffset(x int64) { n.offset = x } @@ -597,7 +597,7 @@ func (n *SelectorExpr) SetOp(op Op) { func (n *SelectorExpr) String() string { return fmt.Sprint(n) } func (n *SelectorExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SelectorExpr) RawCopy() Node { c := *n; return &c } +func (n *SelectorExpr) rawCopy() Node { c := *n; return &c } func (n *SelectorExpr) Left() Node { return n.X } func (n *SelectorExpr) SetLeft(x Node) { n.X = x } func (n *SelectorExpr) Sym() *types.Sym { return n.Sel } @@ -625,7 +625,7 @@ func NewSliceExpr(pos src.XPos, op Op, x Node) *SliceExpr { func (n *SliceExpr) String() string { return fmt.Sprint(n) } func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SliceExpr) RawCopy() Node { c := *n; return &c } +func (n *SliceExpr) rawCopy() Node { c := *n; return &c } func (n *SliceExpr) Left() Node { return n.X } func (n *SliceExpr) SetLeft(x Node) { n.X = x } func (n *SliceExpr) List() Nodes { return n.list } @@ -727,7 +727,7 @@ func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *Slic func (n *SliceHeaderExpr) String() string { return fmt.Sprint(n) } func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SliceHeaderExpr) RawCopy() Node { c := *n; return &c } +func (n *SliceHeaderExpr) rawCopy() Node { c := *n; return &c } func (n *SliceHeaderExpr) Left() Node { return n.Ptr } func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x } func (n *SliceHeaderExpr) List() Nodes { return n.lenCap } @@ -750,7 +750,7 @@ func NewStarExpr(pos src.XPos, x Node) *StarExpr { func (n *StarExpr) String() string { return fmt.Sprint(n) } func (n *StarExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *StarExpr) RawCopy() Node { c := *n; return &c } +func (n *StarExpr) rawCopy() Node { c := *n; return &c } func (n *StarExpr) Left() Node { return n.X } func (n *StarExpr) SetLeft(x Node) { n.X = x } @@ -796,7 +796,7 @@ func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr { func (n *TypeAssertExpr) String() string { return fmt.Sprint(n) } func (n *TypeAssertExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *TypeAssertExpr) RawCopy() Node { c := *n; return &c } +func (n *TypeAssertExpr) rawCopy() Node { c := *n; return &c } func (n *TypeAssertExpr) Left() Node { return n.X } func (n *TypeAssertExpr) SetLeft(x Node) { n.X = x } func (n *TypeAssertExpr) Right() Node { return n.Ntype } @@ -830,7 +830,7 @@ func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr { func (n *UnaryExpr) String() string { return fmt.Sprint(n) } func (n *UnaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *UnaryExpr) RawCopy() Node { c := *n; return &c } +func (n *UnaryExpr) rawCopy() Node { c := *n; return &c } func (n *UnaryExpr) Left() Node { return n.X } func (n *UnaryExpr) SetLeft(x Node) { n.X = x } diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 9d2a8ad94b..3fc8597ef0 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -116,7 +116,7 @@ func NewFunc(pos src.XPos) *Func { func (f *Func) String() string { return fmt.Sprint(f) } func (f *Func) Format(s fmt.State, verb rune) { FmtNode(f, s, verb) } -func (f *Func) RawCopy() Node { panic(f.no("RawCopy")) } +func (f *Func) rawCopy() Node { panic(f.no("rawCopy")) } func (f *Func) Func() *Func { return f } func (f *Func) Body() Nodes { return f.body } func (f *Func) PtrBody() *Nodes { return &f.body } diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index d73ec4ecd5..909ca0220d 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -19,7 +19,7 @@ import ( // must at the least provide: // // func (n *MyNode) String() string { return fmt.Sprint(n) } -// func (n *MyNode) RawCopy() Node { c := *n; return &c } +// func (n *MyNode) rawCopy() Node { c := *n; return &c } // func (n *MyNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } // // The embedding struct should also fill in n.op in its constructor, diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 1bc6bea3b6..76abb454ee 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -143,7 +143,7 @@ func newNameAt(pos src.XPos, sym *types.Sym) *Name { func (n *Name) String() string { return fmt.Sprint(n) } func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *Name) RawCopy() Node { c := *n; return &c } +func (n *Name) rawCopy() Node { c := *n; return &c } func (n *Name) Name() *Name { return n } func (n *Name) Sym() *types.Sym { return n.sym } func (n *Name) SetSym(x *types.Sym) { n.sym = x } @@ -370,7 +370,7 @@ type PkgName struct { func (p *PkgName) String() string { return fmt.Sprint(p) } func (p *PkgName) Format(s fmt.State, verb rune) { FmtNode(p, s, verb) } -func (p *PkgName) RawCopy() Node { c := *p; return &c } +func (p *PkgName) rawCopy() Node { c := *p; return &c } func (p *PkgName) Sym() *types.Sym { return p.sym } func (*PkgName) CanBeNtype() {} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index a93a87fb68..a7144eee44 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -28,7 +28,7 @@ type Node interface { SetPos(x src.XPos) // For making copies. Mainly used by Copy and SepCopy. - RawCopy() Node + rawCopy() Node // Abstract graph structure, for generic traversals. Op() Op diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 2516835513..91714e38e3 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -31,7 +31,7 @@ func NewDecl(pos src.XPos, op Op, x Node) *Decl { func (n *Decl) String() string { return fmt.Sprint(n) } func (n *Decl) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *Decl) RawCopy() Node { c := *n; return &c } +func (n *Decl) rawCopy() Node { c := *n; return &c } func (n *Decl) Left() Node { return n.X } func (n *Decl) SetLeft(x Node) { n.X = x } @@ -70,7 +70,7 @@ func NewAssignListStmt(pos src.XPos, lhs, rhs []Node) *AssignListStmt { func (n *AssignListStmt) String() string { return fmt.Sprint(n) } func (n *AssignListStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AssignListStmt) RawCopy() Node { c := *n; return &c } +func (n *AssignListStmt) rawCopy() Node { c := *n; return &c } func (n *AssignListStmt) List() Nodes { return n.Lhs } func (n *AssignListStmt) PtrList() *Nodes { return &n.Lhs } @@ -112,7 +112,7 @@ func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt { func (n *AssignStmt) String() string { return fmt.Sprint(n) } func (n *AssignStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AssignStmt) RawCopy() Node { c := *n; return &c } +func (n *AssignStmt) rawCopy() Node { c := *n; return &c } func (n *AssignStmt) Left() Node { return n.X } func (n *AssignStmt) SetLeft(x Node) { n.X = x } @@ -151,7 +151,7 @@ func NewAssignOpStmt(pos src.XPos, op Op, x, y Node) *AssignOpStmt { func (n *AssignOpStmt) String() string { return fmt.Sprint(n) } func (n *AssignOpStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AssignOpStmt) RawCopy() Node { c := *n; return &c } +func (n *AssignOpStmt) rawCopy() Node { c := *n; return &c } func (n *AssignOpStmt) Left() Node { return n.X } func (n *AssignOpStmt) SetLeft(x Node) { n.X = x } @@ -180,7 +180,7 @@ func NewBlockStmt(pos src.XPos, list []Node) *BlockStmt { func (n *BlockStmt) String() string { return fmt.Sprint(n) } func (n *BlockStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *BlockStmt) RawCopy() Node { c := *n; return &c } +func (n *BlockStmt) rawCopy() Node { c := *n; return &c } func (n *BlockStmt) List() Nodes { return n.list } func (n *BlockStmt) PtrList() *Nodes { return &n.list } func (n *BlockStmt) SetList(x Nodes) { n.list = x } @@ -209,7 +209,7 @@ func NewBranchStmt(pos src.XPos, op Op, label *types.Sym) *BranchStmt { func (n *BranchStmt) String() string { return fmt.Sprint(n) } func (n *BranchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *BranchStmt) RawCopy() Node { c := *n; return &c } +func (n *BranchStmt) rawCopy() Node { c := *n; return &c } func (n *BranchStmt) Sym() *types.Sym { return n.Label } func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym } @@ -233,7 +233,7 @@ func NewCaseStmt(pos src.XPos, list, body []Node) *CaseStmt { func (n *CaseStmt) String() string { return fmt.Sprint(n) } func (n *CaseStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CaseStmt) RawCopy() Node { c := *n; return &c } +func (n *CaseStmt) rawCopy() Node { c := *n; return &c } func (n *CaseStmt) List() Nodes { return n.list } func (n *CaseStmt) PtrList() *Nodes { return &n.list } func (n *CaseStmt) SetList(x Nodes) { n.list = x } @@ -261,7 +261,7 @@ func NewDeferStmt(pos src.XPos, call Node) *DeferStmt { func (n *DeferStmt) String() string { return fmt.Sprint(n) } func (n *DeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *DeferStmt) RawCopy() Node { c := *n; return &c } +func (n *DeferStmt) rawCopy() Node { c := *n; return &c } func (n *DeferStmt) Left() Node { return n.Call } func (n *DeferStmt) SetLeft(x Node) { n.Call = x } @@ -280,7 +280,7 @@ func NewEmptyStmt(pos src.XPos) *EmptyStmt { func (n *EmptyStmt) String() string { return fmt.Sprint(n) } func (n *EmptyStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *EmptyStmt) RawCopy() Node { c := *n; return &c } +func (n *EmptyStmt) rawCopy() Node { c := *n; return &c } // A ForStmt is a non-range for loop: for Init; Cond; Post { Body } // Op can be OFOR or OFORUNTIL (!Cond). @@ -305,7 +305,7 @@ func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStm func (n *ForStmt) String() string { return fmt.Sprint(n) } func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ForStmt) RawCopy() Node { c := *n; return &c } +func (n *ForStmt) rawCopy() Node { c := *n; return &c } func (n *ForStmt) Sym() *types.Sym { return n.Label } func (n *ForStmt) SetSym(x *types.Sym) { n.Label = x } func (n *ForStmt) Left() Node { return n.Cond } @@ -343,7 +343,7 @@ func NewGoStmt(pos src.XPos, call Node) *GoStmt { func (n *GoStmt) String() string { return fmt.Sprint(n) } func (n *GoStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *GoStmt) RawCopy() Node { c := *n; return &c } +func (n *GoStmt) rawCopy() Node { c := *n; return &c } func (n *GoStmt) Left() Node { return n.Call } func (n *GoStmt) SetLeft(x Node) { n.Call = x } @@ -368,7 +368,7 @@ func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt { func (n *IfStmt) String() string { return fmt.Sprint(n) } func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *IfStmt) RawCopy() Node { c := *n; return &c } +func (n *IfStmt) rawCopy() Node { c := *n; return &c } func (n *IfStmt) Left() Node { return n.Cond } func (n *IfStmt) SetLeft(x Node) { n.Cond = x } func (n *IfStmt) Body() Nodes { return n.body } @@ -395,7 +395,7 @@ func NewInlineMarkStmt(pos src.XPos, index int64) *InlineMarkStmt { func (n *InlineMarkStmt) String() string { return fmt.Sprint(n) } func (n *InlineMarkStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *InlineMarkStmt) RawCopy() Node { c := *n; return &c } +func (n *InlineMarkStmt) rawCopy() Node { c := *n; return &c } func (n *InlineMarkStmt) Offset() int64 { return n.Index } func (n *InlineMarkStmt) SetOffset(x int64) { n.Index = x } @@ -414,7 +414,7 @@ func NewLabelStmt(pos src.XPos, label *types.Sym) *LabelStmt { func (n *LabelStmt) String() string { return fmt.Sprint(n) } func (n *LabelStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *LabelStmt) RawCopy() Node { c := *n; return &c } +func (n *LabelStmt) rawCopy() Node { c := *n; return &c } func (n *LabelStmt) Sym() *types.Sym { return n.Label } func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x } @@ -442,7 +442,7 @@ func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt { func (n *RangeStmt) String() string { return fmt.Sprint(n) } func (n *RangeStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *RangeStmt) RawCopy() Node { c := *n; return &c } +func (n *RangeStmt) rawCopy() Node { c := *n; return &c } func (n *RangeStmt) Sym() *types.Sym { return n.Label } func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x } func (n *RangeStmt) Right() Node { return n.X } @@ -478,7 +478,7 @@ func NewReturnStmt(pos src.XPos, results []Node) *ReturnStmt { func (n *ReturnStmt) String() string { return fmt.Sprint(n) } func (n *ReturnStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ReturnStmt) RawCopy() Node { c := *n; return &c } +func (n *ReturnStmt) rawCopy() Node { c := *n; return &c } func (n *ReturnStmt) Orig() Node { return n.orig } func (n *ReturnStmt) SetOrig(x Node) { n.orig = x } func (n *ReturnStmt) List() Nodes { return n.Results } @@ -507,7 +507,7 @@ func NewSelectStmt(pos src.XPos, cases []Node) *SelectStmt { func (n *SelectStmt) String() string { return fmt.Sprint(n) } func (n *SelectStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SelectStmt) RawCopy() Node { c := *n; return &c } +func (n *SelectStmt) rawCopy() Node { c := *n; return &c } func (n *SelectStmt) List() Nodes { return n.Cases } func (n *SelectStmt) PtrList() *Nodes { return &n.Cases } func (n *SelectStmt) SetList(x Nodes) { n.Cases = x } @@ -535,7 +535,7 @@ func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt { func (n *SendStmt) String() string { return fmt.Sprint(n) } func (n *SendStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SendStmt) RawCopy() Node { c := *n; return &c } +func (n *SendStmt) rawCopy() Node { c := *n; return &c } func (n *SendStmt) Left() Node { return n.Chan } func (n *SendStmt) SetLeft(x Node) { n.Chan = x } @@ -564,7 +564,7 @@ func NewSwitchStmt(pos src.XPos, tag Node, cases []Node) *SwitchStmt { func (n *SwitchStmt) String() string { return fmt.Sprint(n) } func (n *SwitchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SwitchStmt) RawCopy() Node { c := *n; return &c } +func (n *SwitchStmt) rawCopy() Node { c := *n; return &c } func (n *SwitchStmt) Left() Node { return n.Tag } func (n *SwitchStmt) SetLeft(x Node) { n.Tag = x } func (n *SwitchStmt) List() Nodes { return n.Cases } @@ -597,7 +597,7 @@ func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard { func (n *TypeSwitchGuard) String() string { return fmt.Sprint(n) } func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *TypeSwitchGuard) RawCopy() Node { c := *n; return &c } +func (n *TypeSwitchGuard) rawCopy() Node { c := *n; return &c } func (n *TypeSwitchGuard) Left() Node { if n.name == nil { diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index 519a7291b0..af8db15e84 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -78,7 +78,7 @@ func NewChanType(pos src.XPos, elem Node, dir types.ChanDir) *ChanType { func (n *ChanType) String() string { return fmt.Sprint(n) } func (n *ChanType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ChanType) RawCopy() Node { c := *n; return &c } +func (n *ChanType) rawCopy() Node { c := *n; return &c } func (n *ChanType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -108,7 +108,7 @@ func NewMapType(pos src.XPos, key, elem Node) *MapType { func (n *MapType) String() string { return fmt.Sprint(n) } func (n *MapType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *MapType) RawCopy() Node { c := *n; return &c } +func (n *MapType) rawCopy() Node { c := *n; return &c } func (n *MapType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Key = nil @@ -138,7 +138,7 @@ func NewStructType(pos src.XPos, fields []*Field) *StructType { func (n *StructType) String() string { return fmt.Sprint(n) } func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *StructType) RawCopy() Node { c := *n; return &c } +func (n *StructType) rawCopy() Node { c := *n; return &c } func (n *StructType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Fields = nil @@ -175,7 +175,7 @@ func NewInterfaceType(pos src.XPos, methods []*Field) *InterfaceType { func (n *InterfaceType) String() string { return fmt.Sprint(n) } func (n *InterfaceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *InterfaceType) RawCopy() Node { c := *n; return &c } +func (n *InterfaceType) rawCopy() Node { c := *n; return &c } func (n *InterfaceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Methods = nil @@ -206,7 +206,7 @@ func NewFuncType(pos src.XPos, rcvr *Field, args, results []*Field) *FuncType { func (n *FuncType) String() string { return fmt.Sprint(n) } func (n *FuncType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *FuncType) RawCopy() Node { c := *n; return &c } +func (n *FuncType) rawCopy() Node { c := *n; return &c } func (n *FuncType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) @@ -293,7 +293,7 @@ func NewSliceType(pos src.XPos, elem Node) *SliceType { func (n *SliceType) String() string { return fmt.Sprint(n) } func (n *SliceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SliceType) RawCopy() Node { c := *n; return &c } +func (n *SliceType) rawCopy() Node { c := *n; return &c } func (n *SliceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -324,7 +324,7 @@ func NewArrayType(pos src.XPos, size Node, elem Node) *ArrayType { func (n *ArrayType) String() string { return fmt.Sprint(n) } func (n *ArrayType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ArrayType) RawCopy() Node { c := *n; return &c } +func (n *ArrayType) rawCopy() Node { c := *n; return &c } func (n *ArrayType) DeepCopy(pos src.XPos) Node { if n.op == OTYPE { @@ -355,7 +355,7 @@ func newTypeNode(pos src.XPos, typ *types.Type) *typeNode { func (n *typeNode) String() string { return fmt.Sprint(n) } func (n *typeNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *typeNode) RawCopy() Node { c := *n; return &c } +func (n *typeNode) rawCopy() Node { c := *n; return &c } func (n *typeNode) Type() *types.Type { return n.typ } func (n *typeNode) Sym() *types.Sym { return n.typ.Sym } func (n *typeNode) CanBeNtype() {} From 2d6ff998edc0f3877ee24d28647a494491742f25 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 29 Nov 2020 14:06:17 -0800 Subject: [PATCH 056/212] [dev.regabi] cmd/compile: process //go:linknames after declarations Allows emitting errors about ineffectual //go:linkname directives. In particular, this exposed: a typo in os2_aix.go; redundant (but harmless) directives for libc_pipe in both os3_solaris.go and syscall2_solaris.go; and a bunch of useless //go:linkname directives in macOS wrapper code. However, because there's also ineffectual directives in the vendored macOS code from x/sys, that can't be an error just yet. So instead we print a warning (including a heads up that it will be promoted to an error in Go 1.17) to prevent backsliding while we fix and re-vendor that code. Passes toolstash-check. Change-Id: I59badeab5df0d8b3abfd14c6066e9bb00e840f73 Reviewed-on: https://go-review.googlesource.com/c/go/+/273986 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/noder.go | 43 ++++--- .../x509/internal/macos/corefoundation.go | 9 -- src/crypto/x509/internal/macos/security.go | 4 - src/go/types/stdlib_test.go | 1 + src/runtime/os2_aix.go | 4 +- src/runtime/syscall2_solaris.go | 2 - src/syscall/mksyscall.pl | 3 - src/syscall/syscall_darwin.go | 3 - src/syscall/syscall_darwin_amd64.go | 1 - src/syscall/syscall_darwin_arm64.go | 1 - src/syscall/zsyscall_darwin_amd64.go | 121 ------------------ src/syscall/zsyscall_darwin_arm64.go | 121 ------------------ test/linkname2.go | 27 ++++ 13 files changed, 58 insertions(+), 282 deletions(-) create mode 100644 test/linkname2.go diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 6a5afe7687..1340068c72 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -75,6 +75,10 @@ func parseFiles(filenames []string) uint { testdclstack() } + for _, p := range noders { + p.processPragmas() + } + ir.LocalPkg.Height = myheight return lines @@ -258,23 +262,27 @@ func (p *noder) node() { xtop = append(xtop, p.decls(p.file.DeclList)...) - for _, n := range p.linknames { + base.Pos = src.NoXPos + clearImports() +} + +func (p *noder) processPragmas() { + for _, l := range p.linknames { if !p.importedUnsafe { - p.errorAt(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"") + p.errorAt(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"") continue } - s := lookup(n.local) - if n.remote != "" { - s.Linkname = n.remote - } else { - // Use the default object symbol name if the - // user didn't provide one. - if base.Ctxt.Pkgpath == "" { - p.errorAt(n.pos, "//go:linkname requires linkname argument or -p compiler flag") - } else { - s.Linkname = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + n.local - } + n := ir.AsNode(lookup(l.local).Def) + if n == nil || n.Op() != ir.ONAME { + // TODO(mdempsky): Change to p.errorAt before Go 1.17 release. + base.WarnfAt(p.makeXPos(l.pos), "//go:linkname must refer to declared function or variable (will be an error in Go 1.17)") + continue } + if n.Sym().Linkname != "" { + p.errorAt(l.pos, "duplicate //go:linkname for %s", l.local) + continue + } + n.Sym().Linkname = l.remote } // The linker expects an ABI0 wrapper for all cgo-exported @@ -290,8 +298,6 @@ func (p *noder) node() { } pragcgobuf = append(pragcgobuf, p.pragcgobuf...) - base.Pos = src.NoXPos - clearImports() } func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) { @@ -1592,6 +1598,13 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P var target string if len(f) == 3 { target = f[2] + } else if base.Ctxt.Pkgpath != "" { + // Use the default object symbol name if the + // user didn't provide one. + target = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + f[1] + } else { + p.error(syntax.Error{Pos: pos, Msg: "//go:linkname requires linkname argument or -p compiler flag"}) + break } p.linknames = append(p.linknames, linkname{pos, f[1], target}) diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go index 9b776d4b85..0572c6ccd8 100644 --- a/src/crypto/x509/internal/macos/corefoundation.go +++ b/src/crypto/x509/internal/macos/corefoundation.go @@ -39,7 +39,6 @@ type CFString CFRef const kCFAllocatorDefault = 0 const kCFStringEncodingUTF8 = 0x08000100 -//go:linkname x509_CFStringCreateWithBytes x509_CFStringCreateWithBytes //go:cgo_import_dynamic x509_CFStringCreateWithBytes CFStringCreateWithBytes "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" // StringToCFString returns a copy of the UTF-8 contents of s as a new CFString. @@ -52,7 +51,6 @@ func StringToCFString(s string) CFString { } func x509_CFStringCreateWithBytes_trampoline() -//go:linkname x509_CFDictionaryGetValueIfPresent x509_CFDictionaryGetValueIfPresent //go:cgo_import_dynamic x509_CFDictionaryGetValueIfPresent CFDictionaryGetValueIfPresent "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) { @@ -67,7 +65,6 @@ func x509_CFDictionaryGetValueIfPresent_trampoline() const kCFNumberSInt32Type = 3 -//go:linkname x509_CFNumberGetValue x509_CFNumberGetValue //go:cgo_import_dynamic x509_CFNumberGetValue CFNumberGetValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFNumberGetValue(num CFRef) (int32, error) { @@ -81,7 +78,6 @@ func CFNumberGetValue(num CFRef) (int32, error) { } func x509_CFNumberGetValue_trampoline() -//go:linkname x509_CFDataGetLength x509_CFDataGetLength //go:cgo_import_dynamic x509_CFDataGetLength CFDataGetLength "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFDataGetLength(data CFRef) int { @@ -90,7 +86,6 @@ func CFDataGetLength(data CFRef) int { } func x509_CFDataGetLength_trampoline() -//go:linkname x509_CFDataGetBytePtr x509_CFDataGetBytePtr //go:cgo_import_dynamic x509_CFDataGetBytePtr CFDataGetBytePtr "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFDataGetBytePtr(data CFRef) uintptr { @@ -99,7 +94,6 @@ func CFDataGetBytePtr(data CFRef) uintptr { } func x509_CFDataGetBytePtr_trampoline() -//go:linkname x509_CFArrayGetCount x509_CFArrayGetCount //go:cgo_import_dynamic x509_CFArrayGetCount CFArrayGetCount "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFArrayGetCount(array CFRef) int { @@ -108,7 +102,6 @@ func CFArrayGetCount(array CFRef) int { } func x509_CFArrayGetCount_trampoline() -//go:linkname x509_CFArrayGetValueAtIndex x509_CFArrayGetValueAtIndex //go:cgo_import_dynamic x509_CFArrayGetValueAtIndex CFArrayGetValueAtIndex "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFArrayGetValueAtIndex(array CFRef, index int) CFRef { @@ -117,7 +110,6 @@ func CFArrayGetValueAtIndex(array CFRef, index int) CFRef { } func x509_CFArrayGetValueAtIndex_trampoline() -//go:linkname x509_CFEqual x509_CFEqual //go:cgo_import_dynamic x509_CFEqual CFEqual "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFEqual(a, b CFRef) bool { @@ -126,7 +118,6 @@ func CFEqual(a, b CFRef) bool { } func x509_CFEqual_trampoline() -//go:linkname x509_CFRelease x509_CFRelease //go:cgo_import_dynamic x509_CFRelease CFRelease "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFRelease(ref CFRef) { diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go index 5e39e93666..3163e3a4f7 100644 --- a/src/crypto/x509/internal/macos/security.go +++ b/src/crypto/x509/internal/macos/security.go @@ -63,7 +63,6 @@ var ErrNoTrustSettings = errors.New("no trust settings found") const errSecNoTrustSettings = -25263 -//go:linkname x509_SecTrustSettingsCopyCertificates x509_SecTrustSettingsCopyCertificates //go:cgo_import_dynamic x509_SecTrustSettingsCopyCertificates SecTrustSettingsCopyCertificates "/System/Library/Frameworks/Security.framework/Versions/A/Security" func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) { @@ -80,7 +79,6 @@ func x509_SecTrustSettingsCopyCertificates_trampoline() const kSecFormatX509Cert int32 = 9 -//go:linkname x509_SecItemExport x509_SecItemExport //go:cgo_import_dynamic x509_SecItemExport SecItemExport "/System/Library/Frameworks/Security.framework/Versions/A/Security" func SecItemExport(cert CFRef) (data CFRef, err error) { @@ -95,7 +93,6 @@ func x509_SecItemExport_trampoline() const errSecItemNotFound = -25300 -//go:linkname x509_SecTrustSettingsCopyTrustSettings x509_SecTrustSettingsCopyTrustSettings //go:cgo_import_dynamic x509_SecTrustSettingsCopyTrustSettings SecTrustSettingsCopyTrustSettings "/System/Library/Frameworks/Security.framework/Versions/A/Security" func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) { @@ -110,7 +107,6 @@ func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain } func x509_SecTrustSettingsCopyTrustSettings_trampoline() -//go:linkname x509_SecPolicyCopyProperties x509_SecPolicyCopyProperties //go:cgo_import_dynamic x509_SecPolicyCopyProperties SecPolicyCopyProperties "/System/Library/Frameworks/Security.framework/Versions/A/Security" func SecPolicyCopyProperties(policy CFRef) CFRef { diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index 669e7bec20..5bd43e688a 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -156,6 +156,7 @@ func TestStdTest(t *testing.T) { testTestDir(t, filepath.Join(runtime.GOROOT(), "test"), "cmplxdivide.go", // also needs file cmplxdivide1.go - ignore "directive.go", // tests compiler rejection of bad directive placement - ignore + "linkname2.go", // go/types doesn't check validity of //go:xxx directives ) } diff --git a/src/runtime/os2_aix.go b/src/runtime/os2_aix.go index 428ff7f225..abd1010be9 100644 --- a/src/runtime/os2_aix.go +++ b/src/runtime/os2_aix.go @@ -18,11 +18,11 @@ import ( //go:cgo_import_dynamic libc___n_pthreads __n_pthreads "libpthread.a/shr_xpg5_64.o" //go:cgo_import_dynamic libc___mod_init __mod_init "libc.a/shr_64.o" -//go:linkname libc___n_pthreads libc___n_pthread +//go:linkname libc___n_pthreads libc___n_pthreads //go:linkname libc___mod_init libc___mod_init var ( - libc___n_pthread, + libc___n_pthreads, libc___mod_init libFunc ) diff --git a/src/runtime/syscall2_solaris.go b/src/runtime/syscall2_solaris.go index e098e8006a..3310489202 100644 --- a/src/runtime/syscall2_solaris.go +++ b/src/runtime/syscall2_solaris.go @@ -15,7 +15,6 @@ import _ "unsafe" // for go:linkname //go:cgo_import_dynamic libc_gethostname gethostname "libc.so" //go:cgo_import_dynamic libc_getpid getpid "libc.so" //go:cgo_import_dynamic libc_ioctl ioctl "libc.so" -//go:cgo_import_dynamic libc_pipe pipe "libc.so" //go:cgo_import_dynamic libc_setgid setgid "libc.so" //go:cgo_import_dynamic libc_setgroups setgroups "libc.so" //go:cgo_import_dynamic libc_setsid setsid "libc.so" @@ -33,7 +32,6 @@ import _ "unsafe" // for go:linkname //go:linkname libc_gethostname libc_gethostname //go:linkname libc_getpid libc_getpid //go:linkname libc_ioctl libc_ioctl -//go:linkname libc_pipe libc_pipe //go:linkname libc_setgid libc_setgid //go:linkname libc_setgroups libc_setgroups //go:linkname libc_setsid libc_setsid diff --git a/src/syscall/mksyscall.pl b/src/syscall/mksyscall.pl index 25b40d7ba2..790df3825b 100755 --- a/src/syscall/mksyscall.pl +++ b/src/syscall/mksyscall.pl @@ -343,9 +343,6 @@ while(<>) { $trampolines{$funcname} = 1; # The assembly trampoline that jumps to the libc routine. $text .= "func ${funcname}_trampoline()\n"; - # Map syscall.funcname to just plain funcname. - # (The jump to this function is in the assembly trampoline, generated by mksyscallasm_darwin.go.) - $text .= "//go:linkname $funcname $funcname\n"; # Tell the linker that funcname can be found in libSystem using varname without the libc_ prefix. my $basename = substr $funcname, 5; $text .= "//go:cgo_import_dynamic $funcname $basename \"/usr/lib/libSystem.B.dylib\"\n\n"; diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go index afdadbf894..162e94479f 100644 --- a/src/syscall/syscall_darwin.go +++ b/src/syscall/syscall_darwin.go @@ -115,7 +115,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { func libc_getfsstat_trampoline() -//go:linkname libc_getfsstat libc_getfsstat //go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib" func setattrlistTimes(path string, times []Timespec) error { @@ -148,7 +147,6 @@ func setattrlistTimes(path string, times []Timespec) error { func libc_setattrlist_trampoline() -//go:linkname libc_setattrlist libc_setattrlist //go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" func utimensat(dirfd int, path string, times *[2]Timespec, flag int) error { @@ -276,7 +274,6 @@ func fdopendir(fd int) (dir uintptr, err error) { func libc_fdopendir_trampoline() -//go:linkname libc_fdopendir libc_fdopendir //go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib" func readlen(fd int, buf *byte, nbuf int) (n int, err error) { diff --git a/src/syscall/syscall_darwin_amd64.go b/src/syscall/syscall_darwin_amd64.go index 23a4e5f996..96fadf7837 100644 --- a/src/syscall/syscall_darwin_amd64.go +++ b/src/syscall/syscall_darwin_amd64.go @@ -56,7 +56,6 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e func libc_sendfile_trampoline() -//go:linkname libc_sendfile libc_sendfile //go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" // Implemented in the runtime package (runtime/sys_darwin_64.go) diff --git a/src/syscall/syscall_darwin_arm64.go b/src/syscall/syscall_darwin_arm64.go index c824f6d89d..d267a4ae6e 100644 --- a/src/syscall/syscall_darwin_arm64.go +++ b/src/syscall/syscall_darwin_arm64.go @@ -56,7 +56,6 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e func libc_sendfile_trampoline() -//go:linkname libc_sendfile libc_sendfile //go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" // Implemented in the runtime package (runtime/sys_darwin_64.go) diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go index 093739ebc7..ee726fb24d 100644 --- a/src/syscall/zsyscall_darwin_amd64.go +++ b/src/syscall/zsyscall_darwin_amd64.go @@ -20,7 +20,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { func libc_getgroups_trampoline() -//go:linkname libc_getgroups libc_getgroups //go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -35,7 +34,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) { func libc_setgroups_trampoline() -//go:linkname libc_setgroups libc_setgroups //go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -51,7 +49,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err func libc_wait4_trampoline() -//go:linkname libc_wait4 libc_wait4 //go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -67,7 +64,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { func libc_accept_trampoline() -//go:linkname libc_accept libc_accept //go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -82,7 +78,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_bind_trampoline() -//go:linkname libc_bind libc_bind //go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -97,7 +92,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_connect_trampoline() -//go:linkname libc_connect libc_connect //go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -113,7 +107,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) { func libc_socket_trampoline() -//go:linkname libc_socket libc_socket //go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -128,7 +121,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen func libc_getsockopt_trampoline() -//go:linkname libc_getsockopt libc_getsockopt //go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -143,7 +135,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) func libc_setsockopt_trampoline() -//go:linkname libc_setsockopt libc_setsockopt //go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -158,7 +149,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getpeername_trampoline() -//go:linkname libc_getpeername libc_getpeername //go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -173,7 +163,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getsockname_trampoline() -//go:linkname libc_getsockname libc_getsockname //go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -188,7 +177,6 @@ func Shutdown(s int, how int) (err error) { func libc_shutdown_trampoline() -//go:linkname libc_shutdown libc_shutdown //go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -203,7 +191,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { func libc_socketpair_trampoline() -//go:linkname libc_socketpair libc_socketpair //go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -225,7 +212,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl func libc_recvfrom_trampoline() -//go:linkname libc_recvfrom libc_recvfrom //go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -246,7 +232,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( func libc_sendto_trampoline() -//go:linkname libc_sendto libc_sendto //go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -262,7 +247,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_recvmsg_trampoline() -//go:linkname libc_recvmsg libc_recvmsg //go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -278,7 +262,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_sendmsg_trampoline() -//go:linkname libc_sendmsg libc_sendmsg //go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -294,7 +277,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne func libc_kevent_trampoline() -//go:linkname libc_kevent libc_kevent //go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -314,7 +296,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) { func libc_utimes_trampoline() -//go:linkname libc_utimes libc_utimes //go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -329,7 +310,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) { func libc_futimes_trampoline() -//go:linkname libc_futimes libc_futimes //go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -345,7 +325,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { func libc_fcntl_trampoline() -//go:linkname libc_fcntl libc_fcntl //go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -360,7 +339,6 @@ func pipe(p *[2]int32) (err error) { func libc_pipe_trampoline() -//go:linkname libc_pipe libc_pipe //go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -375,7 +353,6 @@ func kill(pid int, signum int, posix int) (err error) { func libc_kill_trampoline() -//go:linkname libc_kill libc_kill //go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -395,7 +372,6 @@ func Access(path string, mode uint32) (err error) { func libc_access_trampoline() -//go:linkname libc_access libc_access //go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -410,7 +386,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { func libc_adjtime_trampoline() -//go:linkname libc_adjtime libc_adjtime //go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -430,7 +405,6 @@ func Chdir(path string) (err error) { func libc_chdir_trampoline() -//go:linkname libc_chdir libc_chdir //go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -450,7 +424,6 @@ func Chflags(path string, flags int) (err error) { func libc_chflags_trampoline() -//go:linkname libc_chflags libc_chflags //go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -470,7 +443,6 @@ func Chmod(path string, mode uint32) (err error) { func libc_chmod_trampoline() -//go:linkname libc_chmod libc_chmod //go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -490,7 +462,6 @@ func Chown(path string, uid int, gid int) (err error) { func libc_chown_trampoline() -//go:linkname libc_chown libc_chown //go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -510,7 +481,6 @@ func Chroot(path string) (err error) { func libc_chroot_trampoline() -//go:linkname libc_chroot libc_chroot //go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -525,7 +495,6 @@ func Close(fd int) (err error) { func libc_close_trampoline() -//go:linkname libc_close libc_close //go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -540,7 +509,6 @@ func closedir(dir uintptr) (err error) { func libc_closedir_trampoline() -//go:linkname libc_closedir libc_closedir //go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -556,7 +524,6 @@ func Dup(fd int) (nfd int, err error) { func libc_dup_trampoline() -//go:linkname libc_dup libc_dup //go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -571,7 +538,6 @@ func Dup2(from int, to int) (err error) { func libc_dup2_trampoline() -//go:linkname libc_dup2 libc_dup2 //go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -596,7 +562,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) { func libc_exchangedata_trampoline() -//go:linkname libc_exchangedata libc_exchangedata //go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -611,7 +576,6 @@ func Fchdir(fd int) (err error) { func libc_fchdir_trampoline() -//go:linkname libc_fchdir libc_fchdir //go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -626,7 +590,6 @@ func Fchflags(fd int, flags int) (err error) { func libc_fchflags_trampoline() -//go:linkname libc_fchflags libc_fchflags //go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -641,7 +604,6 @@ func Fchmod(fd int, mode uint32) (err error) { func libc_fchmod_trampoline() -//go:linkname libc_fchmod libc_fchmod //go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -656,7 +618,6 @@ func Fchown(fd int, uid int, gid int) (err error) { func libc_fchown_trampoline() -//go:linkname libc_fchown libc_fchown //go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -671,7 +632,6 @@ func Flock(fd int, how int) (err error) { func libc_flock_trampoline() -//go:linkname libc_flock libc_flock //go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -687,7 +647,6 @@ func Fpathconf(fd int, name int) (val int, err error) { func libc_fpathconf_trampoline() -//go:linkname libc_fpathconf libc_fpathconf //go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -702,7 +661,6 @@ func Fsync(fd int) (err error) { func libc_fsync_trampoline() -//go:linkname libc_fsync libc_fsync //go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -717,7 +675,6 @@ func Ftruncate(fd int, length int64) (err error) { func libc_ftruncate_trampoline() -//go:linkname libc_ftruncate libc_ftruncate //go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -730,7 +687,6 @@ func Getdtablesize() (size int) { func libc_getdtablesize_trampoline() -//go:linkname libc_getdtablesize libc_getdtablesize //go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -743,7 +699,6 @@ func Getegid() (egid int) { func libc_getegid_trampoline() -//go:linkname libc_getegid libc_getegid //go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -756,7 +711,6 @@ func Geteuid() (uid int) { func libc_geteuid_trampoline() -//go:linkname libc_geteuid libc_geteuid //go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -769,7 +723,6 @@ func Getgid() (gid int) { func libc_getgid_trampoline() -//go:linkname libc_getgid libc_getgid //go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -785,7 +738,6 @@ func Getpgid(pid int) (pgid int, err error) { func libc_getpgid_trampoline() -//go:linkname libc_getpgid libc_getpgid //go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -798,7 +750,6 @@ func Getpgrp() (pgrp int) { func libc_getpgrp_trampoline() -//go:linkname libc_getpgrp libc_getpgrp //go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -811,7 +762,6 @@ func Getpid() (pid int) { func libc_getpid_trampoline() -//go:linkname libc_getpid libc_getpid //go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -824,7 +774,6 @@ func Getppid() (ppid int) { func libc_getppid_trampoline() -//go:linkname libc_getppid libc_getppid //go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -840,7 +789,6 @@ func Getpriority(which int, who int) (prio int, err error) { func libc_getpriority_trampoline() -//go:linkname libc_getpriority libc_getpriority //go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -855,7 +803,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) { func libc_getrlimit_trampoline() -//go:linkname libc_getrlimit libc_getrlimit //go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -870,7 +817,6 @@ func Getrusage(who int, rusage *Rusage) (err error) { func libc_getrusage_trampoline() -//go:linkname libc_getrusage libc_getrusage //go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -886,7 +832,6 @@ func Getsid(pid int) (sid int, err error) { func libc_getsid_trampoline() -//go:linkname libc_getsid libc_getsid //go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -899,7 +844,6 @@ func Getuid() (uid int) { func libc_getuid_trampoline() -//go:linkname libc_getuid libc_getuid //go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -912,7 +856,6 @@ func Issetugid() (tainted bool) { func libc_issetugid_trampoline() -//go:linkname libc_issetugid libc_issetugid //go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -928,7 +871,6 @@ func Kqueue() (fd int, err error) { func libc_kqueue_trampoline() -//go:linkname libc_kqueue libc_kqueue //go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -948,7 +890,6 @@ func Lchown(path string, uid int, gid int) (err error) { func libc_lchown_trampoline() -//go:linkname libc_lchown libc_lchown //go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -973,7 +914,6 @@ func Link(path string, link string) (err error) { func libc_link_trampoline() -//go:linkname libc_link libc_link //go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -988,7 +928,6 @@ func Listen(s int, backlog int) (err error) { func libc_listen_trampoline() -//go:linkname libc_listen libc_listen //go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1008,7 +947,6 @@ func Mkdir(path string, mode uint32) (err error) { func libc_mkdir_trampoline() -//go:linkname libc_mkdir libc_mkdir //go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1028,7 +966,6 @@ func Mkfifo(path string, mode uint32) (err error) { func libc_mkfifo_trampoline() -//go:linkname libc_mkfifo libc_mkfifo //go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1048,7 +985,6 @@ func Mknod(path string, mode uint32, dev int) (err error) { func libc_mknod_trampoline() -//go:linkname libc_mknod libc_mknod //go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1069,7 +1005,6 @@ func Mlock(b []byte) (err error) { func libc_mlock_trampoline() -//go:linkname libc_mlock libc_mlock //go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1084,7 +1019,6 @@ func Mlockall(flags int) (err error) { func libc_mlockall_trampoline() -//go:linkname libc_mlockall libc_mlockall //go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1105,7 +1039,6 @@ func Mprotect(b []byte, prot int) (err error) { func libc_mprotect_trampoline() -//go:linkname libc_mprotect libc_mprotect //go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1126,7 +1059,6 @@ func Munlock(b []byte) (err error) { func libc_munlock_trampoline() -//go:linkname libc_munlock libc_munlock //go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1141,7 +1073,6 @@ func Munlockall() (err error) { func libc_munlockall_trampoline() -//go:linkname libc_munlockall libc_munlockall //go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1162,7 +1093,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { func libc_open_trampoline() -//go:linkname libc_open libc_open //go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1183,7 +1113,6 @@ func Pathconf(path string, name int) (val int, err error) { func libc_pathconf_trampoline() -//go:linkname libc_pathconf libc_pathconf //go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1205,7 +1134,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { func libc_pread_trampoline() -//go:linkname libc_pread libc_pread //go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1227,7 +1155,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { func libc_pwrite_trampoline() -//go:linkname libc_pwrite libc_pwrite //go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1249,7 +1176,6 @@ func read(fd int, p []byte) (n int, err error) { func libc_read_trampoline() -//go:linkname libc_read libc_read //go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1262,7 +1188,6 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { func libc_readdir_r_trampoline() -//go:linkname libc_readdir_r libc_readdir_r //go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1289,7 +1214,6 @@ func Readlink(path string, buf []byte) (n int, err error) { func libc_readlink_trampoline() -//go:linkname libc_readlink libc_readlink //go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1314,7 +1238,6 @@ func Rename(from string, to string) (err error) { func libc_rename_trampoline() -//go:linkname libc_rename libc_rename //go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1334,7 +1257,6 @@ func Revoke(path string) (err error) { func libc_revoke_trampoline() -//go:linkname libc_revoke libc_revoke //go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1354,7 +1276,6 @@ func Rmdir(path string) (err error) { func libc_rmdir_trampoline() -//go:linkname libc_rmdir libc_rmdir //go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1370,7 +1291,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func libc_lseek_trampoline() -//go:linkname libc_lseek libc_lseek //go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1385,7 +1305,6 @@ func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { func libc_select_trampoline() -//go:linkname libc_select libc_select //go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1400,7 +1319,6 @@ func Setegid(egid int) (err error) { func libc_setegid_trampoline() -//go:linkname libc_setegid libc_setegid //go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1415,7 +1333,6 @@ func Seteuid(euid int) (err error) { func libc_seteuid_trampoline() -//go:linkname libc_seteuid libc_seteuid //go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1430,7 +1347,6 @@ func Setgid(gid int) (err error) { func libc_setgid_trampoline() -//go:linkname libc_setgid libc_setgid //go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1450,7 +1366,6 @@ func Setlogin(name string) (err error) { func libc_setlogin_trampoline() -//go:linkname libc_setlogin libc_setlogin //go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1465,7 +1380,6 @@ func Setpgid(pid int, pgid int) (err error) { func libc_setpgid_trampoline() -//go:linkname libc_setpgid libc_setpgid //go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1480,7 +1394,6 @@ func Setpriority(which int, who int, prio int) (err error) { func libc_setpriority_trampoline() -//go:linkname libc_setpriority libc_setpriority //go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1495,7 +1408,6 @@ func Setprivexec(flag int) (err error) { func libc_setprivexec_trampoline() -//go:linkname libc_setprivexec libc_setprivexec //go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1510,7 +1422,6 @@ func Setregid(rgid int, egid int) (err error) { func libc_setregid_trampoline() -//go:linkname libc_setregid libc_setregid //go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1525,7 +1436,6 @@ func Setreuid(ruid int, euid int) (err error) { func libc_setreuid_trampoline() -//go:linkname libc_setreuid libc_setreuid //go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1540,7 +1450,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) { func libc_setrlimit_trampoline() -//go:linkname libc_setrlimit libc_setrlimit //go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1556,7 +1465,6 @@ func Setsid() (pid int, err error) { func libc_setsid_trampoline() -//go:linkname libc_setsid libc_setsid //go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1571,7 +1479,6 @@ func Settimeofday(tp *Timeval) (err error) { func libc_settimeofday_trampoline() -//go:linkname libc_settimeofday libc_settimeofday //go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1586,7 +1493,6 @@ func Setuid(uid int) (err error) { func libc_setuid_trampoline() -//go:linkname libc_setuid libc_setuid //go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1611,7 +1517,6 @@ func Symlink(path string, link string) (err error) { func libc_symlink_trampoline() -//go:linkname libc_symlink libc_symlink //go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1626,7 +1531,6 @@ func Sync() (err error) { func libc_sync_trampoline() -//go:linkname libc_sync libc_sync //go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1646,7 +1550,6 @@ func Truncate(path string, length int64) (err error) { func libc_truncate_trampoline() -//go:linkname libc_truncate libc_truncate //go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1659,7 +1562,6 @@ func Umask(newmask int) (oldmask int) { func libc_umask_trampoline() -//go:linkname libc_umask libc_umask //go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1679,7 +1581,6 @@ func Undelete(path string) (err error) { func libc_undelete_trampoline() -//go:linkname libc_undelete libc_undelete //go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1699,7 +1600,6 @@ func Unlink(path string) (err error) { func libc_unlink_trampoline() -//go:linkname libc_unlink libc_unlink //go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1719,7 +1619,6 @@ func Unmount(path string, flags int) (err error) { func libc_unmount_trampoline() -//go:linkname libc_unmount libc_unmount //go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1741,7 +1640,6 @@ func write(fd int, p []byte) (n int, err error) { func libc_write_trampoline() -//go:linkname libc_write libc_write //go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1763,7 +1661,6 @@ func writev(fd int, iovecs []Iovec) (cnt uintptr, err error) { func libc_writev_trampoline() -//go:linkname libc_writev libc_writev //go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1779,7 +1676,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( func libc_mmap_trampoline() -//go:linkname libc_mmap libc_mmap //go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1794,7 +1690,6 @@ func munmap(addr uintptr, length uintptr) (err error) { func libc_munmap_trampoline() -//go:linkname libc_munmap libc_munmap //go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1810,7 +1705,6 @@ func fork() (pid int, err error) { func libc_fork_trampoline() -//go:linkname libc_fork libc_fork //go:cgo_import_dynamic libc_fork fork "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1825,7 +1719,6 @@ func ioctl(fd int, req int, arg int) (err error) { func libc_ioctl_trampoline() -//go:linkname libc_ioctl libc_ioctl //go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1850,7 +1743,6 @@ func execve(path *byte, argv **byte, envp **byte) (err error) { func libc_execve_trampoline() -//go:linkname libc_execve libc_execve //go:cgo_import_dynamic libc_execve execve "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1865,7 +1757,6 @@ func exit(res int) (err error) { func libc_exit_trampoline() -//go:linkname libc_exit libc_exit //go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1886,7 +1777,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) func libc_sysctl_trampoline() -//go:linkname libc_sysctl libc_sysctl //go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1917,7 +1807,6 @@ func unlinkat(fd int, path string, flags int) (err error) { func libc_unlinkat_trampoline() -//go:linkname libc_unlinkat libc_unlinkat //go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1938,7 +1827,6 @@ func openat(fd int, path string, flags int, perm uint32) (fdret int, err error) func libc_openat_trampoline() -//go:linkname libc_openat libc_openat //go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1960,7 +1848,6 @@ func getcwd(buf []byte) (n int, err error) { func libc_getcwd_trampoline() -//go:linkname libc_getcwd libc_getcwd //go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1975,7 +1862,6 @@ func Fstat(fd int, stat *Stat_t) (err error) { func libc_fstat64_trampoline() -//go:linkname libc_fstat64 libc_fstat64 //go:cgo_import_dynamic libc_fstat64 fstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1990,7 +1876,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { func libc_fstatfs64_trampoline() -//go:linkname libc_fstatfs64 libc_fstatfs64 //go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2005,7 +1890,6 @@ func Gettimeofday(tp *Timeval) (err error) { func libc_gettimeofday_trampoline() -//go:linkname libc_gettimeofday libc_gettimeofday //go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2025,7 +1909,6 @@ func Lstat(path string, stat *Stat_t) (err error) { func libc_lstat64_trampoline() -//go:linkname libc_lstat64 libc_lstat64 //go:cgo_import_dynamic libc_lstat64 lstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2045,7 +1928,6 @@ func Stat(path string, stat *Stat_t) (err error) { func libc_stat64_trampoline() -//go:linkname libc_stat64 libc_stat64 //go:cgo_import_dynamic libc_stat64 stat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2065,7 +1947,6 @@ func Statfs(path string, stat *Statfs_t) (err error) { func libc_statfs64_trampoline() -//go:linkname libc_statfs64 libc_statfs64 //go:cgo_import_dynamic libc_statfs64 statfs64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2085,7 +1966,6 @@ func fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { func libc_fstatat64_trampoline() -//go:linkname libc_fstatat64 libc_fstatat64 //go:cgo_import_dynamic libc_fstatat64 fstatat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2101,5 +1981,4 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func libc_ptrace_trampoline() -//go:linkname libc_ptrace libc_ptrace //go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" diff --git a/src/syscall/zsyscall_darwin_arm64.go b/src/syscall/zsyscall_darwin_arm64.go index 7698b2503e..ac530f3108 100644 --- a/src/syscall/zsyscall_darwin_arm64.go +++ b/src/syscall/zsyscall_darwin_arm64.go @@ -20,7 +20,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { func libc_getgroups_trampoline() -//go:linkname libc_getgroups libc_getgroups //go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -35,7 +34,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) { func libc_setgroups_trampoline() -//go:linkname libc_setgroups libc_setgroups //go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -51,7 +49,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err func libc_wait4_trampoline() -//go:linkname libc_wait4 libc_wait4 //go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -67,7 +64,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { func libc_accept_trampoline() -//go:linkname libc_accept libc_accept //go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -82,7 +78,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_bind_trampoline() -//go:linkname libc_bind libc_bind //go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -97,7 +92,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_connect_trampoline() -//go:linkname libc_connect libc_connect //go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -113,7 +107,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) { func libc_socket_trampoline() -//go:linkname libc_socket libc_socket //go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -128,7 +121,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen func libc_getsockopt_trampoline() -//go:linkname libc_getsockopt libc_getsockopt //go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -143,7 +135,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) func libc_setsockopt_trampoline() -//go:linkname libc_setsockopt libc_setsockopt //go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -158,7 +149,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getpeername_trampoline() -//go:linkname libc_getpeername libc_getpeername //go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -173,7 +163,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getsockname_trampoline() -//go:linkname libc_getsockname libc_getsockname //go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -188,7 +177,6 @@ func Shutdown(s int, how int) (err error) { func libc_shutdown_trampoline() -//go:linkname libc_shutdown libc_shutdown //go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -203,7 +191,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { func libc_socketpair_trampoline() -//go:linkname libc_socketpair libc_socketpair //go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -225,7 +212,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl func libc_recvfrom_trampoline() -//go:linkname libc_recvfrom libc_recvfrom //go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -246,7 +232,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( func libc_sendto_trampoline() -//go:linkname libc_sendto libc_sendto //go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -262,7 +247,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_recvmsg_trampoline() -//go:linkname libc_recvmsg libc_recvmsg //go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -278,7 +262,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_sendmsg_trampoline() -//go:linkname libc_sendmsg libc_sendmsg //go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -294,7 +277,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne func libc_kevent_trampoline() -//go:linkname libc_kevent libc_kevent //go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -314,7 +296,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) { func libc_utimes_trampoline() -//go:linkname libc_utimes libc_utimes //go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -329,7 +310,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) { func libc_futimes_trampoline() -//go:linkname libc_futimes libc_futimes //go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -345,7 +325,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { func libc_fcntl_trampoline() -//go:linkname libc_fcntl libc_fcntl //go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -360,7 +339,6 @@ func pipe(p *[2]int32) (err error) { func libc_pipe_trampoline() -//go:linkname libc_pipe libc_pipe //go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -375,7 +353,6 @@ func kill(pid int, signum int, posix int) (err error) { func libc_kill_trampoline() -//go:linkname libc_kill libc_kill //go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -395,7 +372,6 @@ func Access(path string, mode uint32) (err error) { func libc_access_trampoline() -//go:linkname libc_access libc_access //go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -410,7 +386,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { func libc_adjtime_trampoline() -//go:linkname libc_adjtime libc_adjtime //go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -430,7 +405,6 @@ func Chdir(path string) (err error) { func libc_chdir_trampoline() -//go:linkname libc_chdir libc_chdir //go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -450,7 +424,6 @@ func Chflags(path string, flags int) (err error) { func libc_chflags_trampoline() -//go:linkname libc_chflags libc_chflags //go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -470,7 +443,6 @@ func Chmod(path string, mode uint32) (err error) { func libc_chmod_trampoline() -//go:linkname libc_chmod libc_chmod //go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -490,7 +462,6 @@ func Chown(path string, uid int, gid int) (err error) { func libc_chown_trampoline() -//go:linkname libc_chown libc_chown //go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -510,7 +481,6 @@ func Chroot(path string) (err error) { func libc_chroot_trampoline() -//go:linkname libc_chroot libc_chroot //go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -525,7 +495,6 @@ func Close(fd int) (err error) { func libc_close_trampoline() -//go:linkname libc_close libc_close //go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -540,7 +509,6 @@ func closedir(dir uintptr) (err error) { func libc_closedir_trampoline() -//go:linkname libc_closedir libc_closedir //go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -556,7 +524,6 @@ func Dup(fd int) (nfd int, err error) { func libc_dup_trampoline() -//go:linkname libc_dup libc_dup //go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -571,7 +538,6 @@ func Dup2(from int, to int) (err error) { func libc_dup2_trampoline() -//go:linkname libc_dup2 libc_dup2 //go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -596,7 +562,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) { func libc_exchangedata_trampoline() -//go:linkname libc_exchangedata libc_exchangedata //go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -611,7 +576,6 @@ func Fchdir(fd int) (err error) { func libc_fchdir_trampoline() -//go:linkname libc_fchdir libc_fchdir //go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -626,7 +590,6 @@ func Fchflags(fd int, flags int) (err error) { func libc_fchflags_trampoline() -//go:linkname libc_fchflags libc_fchflags //go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -641,7 +604,6 @@ func Fchmod(fd int, mode uint32) (err error) { func libc_fchmod_trampoline() -//go:linkname libc_fchmod libc_fchmod //go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -656,7 +618,6 @@ func Fchown(fd int, uid int, gid int) (err error) { func libc_fchown_trampoline() -//go:linkname libc_fchown libc_fchown //go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -671,7 +632,6 @@ func Flock(fd int, how int) (err error) { func libc_flock_trampoline() -//go:linkname libc_flock libc_flock //go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -687,7 +647,6 @@ func Fpathconf(fd int, name int) (val int, err error) { func libc_fpathconf_trampoline() -//go:linkname libc_fpathconf libc_fpathconf //go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -702,7 +661,6 @@ func Fsync(fd int) (err error) { func libc_fsync_trampoline() -//go:linkname libc_fsync libc_fsync //go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -717,7 +675,6 @@ func Ftruncate(fd int, length int64) (err error) { func libc_ftruncate_trampoline() -//go:linkname libc_ftruncate libc_ftruncate //go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -730,7 +687,6 @@ func Getdtablesize() (size int) { func libc_getdtablesize_trampoline() -//go:linkname libc_getdtablesize libc_getdtablesize //go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -743,7 +699,6 @@ func Getegid() (egid int) { func libc_getegid_trampoline() -//go:linkname libc_getegid libc_getegid //go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -756,7 +711,6 @@ func Geteuid() (uid int) { func libc_geteuid_trampoline() -//go:linkname libc_geteuid libc_geteuid //go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -769,7 +723,6 @@ func Getgid() (gid int) { func libc_getgid_trampoline() -//go:linkname libc_getgid libc_getgid //go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -785,7 +738,6 @@ func Getpgid(pid int) (pgid int, err error) { func libc_getpgid_trampoline() -//go:linkname libc_getpgid libc_getpgid //go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -798,7 +750,6 @@ func Getpgrp() (pgrp int) { func libc_getpgrp_trampoline() -//go:linkname libc_getpgrp libc_getpgrp //go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -811,7 +762,6 @@ func Getpid() (pid int) { func libc_getpid_trampoline() -//go:linkname libc_getpid libc_getpid //go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -824,7 +774,6 @@ func Getppid() (ppid int) { func libc_getppid_trampoline() -//go:linkname libc_getppid libc_getppid //go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -840,7 +789,6 @@ func Getpriority(which int, who int) (prio int, err error) { func libc_getpriority_trampoline() -//go:linkname libc_getpriority libc_getpriority //go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -855,7 +803,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) { func libc_getrlimit_trampoline() -//go:linkname libc_getrlimit libc_getrlimit //go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -870,7 +817,6 @@ func Getrusage(who int, rusage *Rusage) (err error) { func libc_getrusage_trampoline() -//go:linkname libc_getrusage libc_getrusage //go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -886,7 +832,6 @@ func Getsid(pid int) (sid int, err error) { func libc_getsid_trampoline() -//go:linkname libc_getsid libc_getsid //go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -899,7 +844,6 @@ func Getuid() (uid int) { func libc_getuid_trampoline() -//go:linkname libc_getuid libc_getuid //go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -912,7 +856,6 @@ func Issetugid() (tainted bool) { func libc_issetugid_trampoline() -//go:linkname libc_issetugid libc_issetugid //go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -928,7 +871,6 @@ func Kqueue() (fd int, err error) { func libc_kqueue_trampoline() -//go:linkname libc_kqueue libc_kqueue //go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -948,7 +890,6 @@ func Lchown(path string, uid int, gid int) (err error) { func libc_lchown_trampoline() -//go:linkname libc_lchown libc_lchown //go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -973,7 +914,6 @@ func Link(path string, link string) (err error) { func libc_link_trampoline() -//go:linkname libc_link libc_link //go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -988,7 +928,6 @@ func Listen(s int, backlog int) (err error) { func libc_listen_trampoline() -//go:linkname libc_listen libc_listen //go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1008,7 +947,6 @@ func Mkdir(path string, mode uint32) (err error) { func libc_mkdir_trampoline() -//go:linkname libc_mkdir libc_mkdir //go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1028,7 +966,6 @@ func Mkfifo(path string, mode uint32) (err error) { func libc_mkfifo_trampoline() -//go:linkname libc_mkfifo libc_mkfifo //go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1048,7 +985,6 @@ func Mknod(path string, mode uint32, dev int) (err error) { func libc_mknod_trampoline() -//go:linkname libc_mknod libc_mknod //go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1069,7 +1005,6 @@ func Mlock(b []byte) (err error) { func libc_mlock_trampoline() -//go:linkname libc_mlock libc_mlock //go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1084,7 +1019,6 @@ func Mlockall(flags int) (err error) { func libc_mlockall_trampoline() -//go:linkname libc_mlockall libc_mlockall //go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1105,7 +1039,6 @@ func Mprotect(b []byte, prot int) (err error) { func libc_mprotect_trampoline() -//go:linkname libc_mprotect libc_mprotect //go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1126,7 +1059,6 @@ func Munlock(b []byte) (err error) { func libc_munlock_trampoline() -//go:linkname libc_munlock libc_munlock //go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1141,7 +1073,6 @@ func Munlockall() (err error) { func libc_munlockall_trampoline() -//go:linkname libc_munlockall libc_munlockall //go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1162,7 +1093,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { func libc_open_trampoline() -//go:linkname libc_open libc_open //go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1183,7 +1113,6 @@ func Pathconf(path string, name int) (val int, err error) { func libc_pathconf_trampoline() -//go:linkname libc_pathconf libc_pathconf //go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1205,7 +1134,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { func libc_pread_trampoline() -//go:linkname libc_pread libc_pread //go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1227,7 +1155,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { func libc_pwrite_trampoline() -//go:linkname libc_pwrite libc_pwrite //go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1249,7 +1176,6 @@ func read(fd int, p []byte) (n int, err error) { func libc_read_trampoline() -//go:linkname libc_read libc_read //go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1262,7 +1188,6 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { func libc_readdir_r_trampoline() -//go:linkname libc_readdir_r libc_readdir_r //go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1289,7 +1214,6 @@ func Readlink(path string, buf []byte) (n int, err error) { func libc_readlink_trampoline() -//go:linkname libc_readlink libc_readlink //go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1314,7 +1238,6 @@ func Rename(from string, to string) (err error) { func libc_rename_trampoline() -//go:linkname libc_rename libc_rename //go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1334,7 +1257,6 @@ func Revoke(path string) (err error) { func libc_revoke_trampoline() -//go:linkname libc_revoke libc_revoke //go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1354,7 +1276,6 @@ func Rmdir(path string) (err error) { func libc_rmdir_trampoline() -//go:linkname libc_rmdir libc_rmdir //go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1370,7 +1291,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func libc_lseek_trampoline() -//go:linkname libc_lseek libc_lseek //go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1385,7 +1305,6 @@ func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { func libc_select_trampoline() -//go:linkname libc_select libc_select //go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1400,7 +1319,6 @@ func Setegid(egid int) (err error) { func libc_setegid_trampoline() -//go:linkname libc_setegid libc_setegid //go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1415,7 +1333,6 @@ func Seteuid(euid int) (err error) { func libc_seteuid_trampoline() -//go:linkname libc_seteuid libc_seteuid //go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1430,7 +1347,6 @@ func Setgid(gid int) (err error) { func libc_setgid_trampoline() -//go:linkname libc_setgid libc_setgid //go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1450,7 +1366,6 @@ func Setlogin(name string) (err error) { func libc_setlogin_trampoline() -//go:linkname libc_setlogin libc_setlogin //go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1465,7 +1380,6 @@ func Setpgid(pid int, pgid int) (err error) { func libc_setpgid_trampoline() -//go:linkname libc_setpgid libc_setpgid //go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1480,7 +1394,6 @@ func Setpriority(which int, who int, prio int) (err error) { func libc_setpriority_trampoline() -//go:linkname libc_setpriority libc_setpriority //go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1495,7 +1408,6 @@ func Setprivexec(flag int) (err error) { func libc_setprivexec_trampoline() -//go:linkname libc_setprivexec libc_setprivexec //go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1510,7 +1422,6 @@ func Setregid(rgid int, egid int) (err error) { func libc_setregid_trampoline() -//go:linkname libc_setregid libc_setregid //go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1525,7 +1436,6 @@ func Setreuid(ruid int, euid int) (err error) { func libc_setreuid_trampoline() -//go:linkname libc_setreuid libc_setreuid //go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1540,7 +1450,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) { func libc_setrlimit_trampoline() -//go:linkname libc_setrlimit libc_setrlimit //go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1556,7 +1465,6 @@ func Setsid() (pid int, err error) { func libc_setsid_trampoline() -//go:linkname libc_setsid libc_setsid //go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1571,7 +1479,6 @@ func Settimeofday(tp *Timeval) (err error) { func libc_settimeofday_trampoline() -//go:linkname libc_settimeofday libc_settimeofday //go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1586,7 +1493,6 @@ func Setuid(uid int) (err error) { func libc_setuid_trampoline() -//go:linkname libc_setuid libc_setuid //go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1611,7 +1517,6 @@ func Symlink(path string, link string) (err error) { func libc_symlink_trampoline() -//go:linkname libc_symlink libc_symlink //go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1626,7 +1531,6 @@ func Sync() (err error) { func libc_sync_trampoline() -//go:linkname libc_sync libc_sync //go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1646,7 +1550,6 @@ func Truncate(path string, length int64) (err error) { func libc_truncate_trampoline() -//go:linkname libc_truncate libc_truncate //go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1659,7 +1562,6 @@ func Umask(newmask int) (oldmask int) { func libc_umask_trampoline() -//go:linkname libc_umask libc_umask //go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1679,7 +1581,6 @@ func Undelete(path string) (err error) { func libc_undelete_trampoline() -//go:linkname libc_undelete libc_undelete //go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1699,7 +1600,6 @@ func Unlink(path string) (err error) { func libc_unlink_trampoline() -//go:linkname libc_unlink libc_unlink //go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1719,7 +1619,6 @@ func Unmount(path string, flags int) (err error) { func libc_unmount_trampoline() -//go:linkname libc_unmount libc_unmount //go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1741,7 +1640,6 @@ func write(fd int, p []byte) (n int, err error) { func libc_write_trampoline() -//go:linkname libc_write libc_write //go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1763,7 +1661,6 @@ func writev(fd int, iovecs []Iovec) (cnt uintptr, err error) { func libc_writev_trampoline() -//go:linkname libc_writev libc_writev //go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1779,7 +1676,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( func libc_mmap_trampoline() -//go:linkname libc_mmap libc_mmap //go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1794,7 +1690,6 @@ func munmap(addr uintptr, length uintptr) (err error) { func libc_munmap_trampoline() -//go:linkname libc_munmap libc_munmap //go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1810,7 +1705,6 @@ func fork() (pid int, err error) { func libc_fork_trampoline() -//go:linkname libc_fork libc_fork //go:cgo_import_dynamic libc_fork fork "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1825,7 +1719,6 @@ func ioctl(fd int, req int, arg int) (err error) { func libc_ioctl_trampoline() -//go:linkname libc_ioctl libc_ioctl //go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1850,7 +1743,6 @@ func execve(path *byte, argv **byte, envp **byte) (err error) { func libc_execve_trampoline() -//go:linkname libc_execve libc_execve //go:cgo_import_dynamic libc_execve execve "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1865,7 +1757,6 @@ func exit(res int) (err error) { func libc_exit_trampoline() -//go:linkname libc_exit libc_exit //go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1886,7 +1777,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) func libc_sysctl_trampoline() -//go:linkname libc_sysctl libc_sysctl //go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1917,7 +1807,6 @@ func unlinkat(fd int, path string, flags int) (err error) { func libc_unlinkat_trampoline() -//go:linkname libc_unlinkat libc_unlinkat //go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1938,7 +1827,6 @@ func openat(fd int, path string, flags int, perm uint32) (fdret int, err error) func libc_openat_trampoline() -//go:linkname libc_openat libc_openat //go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1960,7 +1848,6 @@ func getcwd(buf []byte) (n int, err error) { func libc_getcwd_trampoline() -//go:linkname libc_getcwd libc_getcwd //go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1975,7 +1862,6 @@ func Fstat(fd int, stat *Stat_t) (err error) { func libc_fstat_trampoline() -//go:linkname libc_fstat libc_fstat //go:cgo_import_dynamic libc_fstat fstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1990,7 +1876,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { func libc_fstatfs_trampoline() -//go:linkname libc_fstatfs libc_fstatfs //go:cgo_import_dynamic libc_fstatfs fstatfs "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2005,7 +1890,6 @@ func Gettimeofday(tp *Timeval) (err error) { func libc_gettimeofday_trampoline() -//go:linkname libc_gettimeofday libc_gettimeofday //go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2025,7 +1909,6 @@ func Lstat(path string, stat *Stat_t) (err error) { func libc_lstat_trampoline() -//go:linkname libc_lstat libc_lstat //go:cgo_import_dynamic libc_lstat lstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2045,7 +1928,6 @@ func Stat(path string, stat *Stat_t) (err error) { func libc_stat_trampoline() -//go:linkname libc_stat libc_stat //go:cgo_import_dynamic libc_stat stat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2065,7 +1947,6 @@ func Statfs(path string, stat *Statfs_t) (err error) { func libc_statfs_trampoline() -//go:linkname libc_statfs libc_statfs //go:cgo_import_dynamic libc_statfs statfs "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2085,7 +1966,6 @@ func fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { func libc_fstatat_trampoline() -//go:linkname libc_fstatat libc_fstatat //go:cgo_import_dynamic libc_fstatat fstatat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2101,5 +1981,4 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func libc_ptrace_trampoline() -//go:linkname libc_ptrace libc_ptrace //go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" diff --git a/test/linkname2.go b/test/linkname2.go new file mode 100644 index 0000000000..cb7f9be345 --- /dev/null +++ b/test/linkname2.go @@ -0,0 +1,27 @@ +// errorcheck + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests that errors are reported for misuse of linkname. +package p + +import _ "unsafe" + +type t int + +var x, y int + +//go:linkname x ok + +// ERROR "//go:linkname requires linkname argument or -p compiler flag" +// ERROR "//go:linkname must refer to declared function or variable" +// ERROR "//go:linkname must refer to declared function or variable" +// ERROR "duplicate //go:linkname for x" + +//line linkname2.go:18 +//go:linkname y +//go:linkname nonexist nonexist +//go:linkname t notvarfunc +//go:linkname x duplicate From f2311462ab6f2359006f42b7febd19ce95a9bbcf Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 1 Dec 2020 01:01:59 -0800 Subject: [PATCH 057/212] [dev.regabi] cmd/compile: cleanup type-checking of defined types The code for type-checking defined types was scattered between typecheckdef, typecheckdeftype, and setUnderlying. There was redundant work between them, and setUnderlying also needed to redo a lot of work because of its brute-force solution of just copying all Type fields. This CL reorders things so as many of the defined type's fields are set in advance (in typecheckdeftype), and then setUnderlying only copies over the details actually needed from the underlying type. Incidentally, this evidently improves our error handling for an existing test case, by allowing us to report an additional error. Passes toolstash/buildall. Change-Id: Id59a24341e7e960edd1f7366c3e2356da91b9fe7 Reviewed-on: https://go-review.googlesource.com/c/go/+/274432 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/typecheck.go | 78 +++++++++++------------- test/fixedbugs/issue28079b.go | 2 +- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 874594d764..d9ec06c531 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3434,33 +3434,28 @@ func setUnderlying(t, underlying *types.Type) { return } - n := ir.AsNode(t.Nod) ft := t.ForwardType() - cache := t.Cache // TODO(mdempsky): Fix Type rekinding. - *t = *underlying + t.Etype = underlying.Etype + t.Extra = underlying.Extra + t.Width = underlying.Width + t.Align = underlying.Align + t.Orig = underlying.Orig - // Restore unnecessarily clobbered attributes. - t.Nod = n - t.Sym = n.Sym() - if n.Name() != nil { - t.Vargen = n.Name().Vargen + if underlying.NotInHeap() { + t.SetNotInHeap(true) + } + if underlying.Broke() { + t.SetBroke(true) } - t.Cache = cache - t.SetDeferwidth(false) // spec: "The declared type does not inherit any methods bound // to the existing type, but the method set of an interface // type [...] remains unchanged." - if !t.IsInterface() { - *t.Methods() = types.Fields{} - *t.AllMethods() = types.Fields{} - } - - // Propagate go:notinheap pragma from the Name to the Type. - if n.Name() != nil && n.Name().Pragma()&ir.NotInHeap != 0 { - t.SetNotInHeap(true) + if t.IsInterface() { + *t.Methods() = *underlying.Methods() + *t.AllMethods() = *underlying.AllMethods() } // Update types waiting on this type. @@ -3476,24 +3471,38 @@ func setUnderlying(t, underlying *types.Type) { } } -func typecheckdeftype(n ir.Node) { +func typecheckdeftype(n *ir.Name) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckdeftype", n)(nil) } + t := types.New(types.TFORW) + t.Sym = n.Sym() + t.Vargen = n.Vargen + t.Nod = n + if n.Pragma()&ir.NotInHeap != 0 { + t.SetNotInHeap(true) + } + + n.SetType(t) n.SetTypecheck(1) - n.Name().Ntype = typecheckNtype(n.Name().Ntype) - t := n.Name().Ntype.Type() - if t == nil { + n.SetWalkdef(1) + + defercheckwidth() + errorsBefore := base.Errors() + n.Ntype = typecheckNtype(n.Ntype) + if underlying := n.Ntype.Type(); underlying != nil { + setUnderlying(t, underlying) + } else { n.SetDiag(true) n.SetType(nil) - } else if n.Type() == nil { - n.SetDiag(true) - } else { - // copy new type and clear fields - // that don't come along. - setUnderlying(n.Type(), t) } + if t.Etype == types.TFORW && base.Errors() > errorsBefore { + // Something went wrong during type-checking, + // but it was reported. Silence future errors. + t.SetBroke(true) + } + resumecheckwidth() } func typecheckdef(n ir.Node) { @@ -3655,20 +3664,7 @@ func typecheckdef(n ir.Node) { } // regular type declaration - defercheckwidth() - n.SetWalkdef(1) - t := types.New(types.TFORW) - t.Nod = n - t.Sym = n.Sym() - n.SetType(t) - errorsBefore := base.Errors() typecheckdeftype(n) - if n.Type().Etype == types.TFORW && base.Errors() > errorsBefore { - // Something went wrong during type-checking, - // but it was reported. Silence future errors. - n.Type().SetBroke(true) - } - resumecheckwidth() } ret: diff --git a/test/fixedbugs/issue28079b.go b/test/fixedbugs/issue28079b.go index 47cc16dfb2..9ff221baff 100644 --- a/test/fixedbugs/issue28079b.go +++ b/test/fixedbugs/issue28079b.go @@ -13,5 +13,5 @@ import "unsafe" type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound" func f() { - _ = complex(1< Date: Tue, 1 Dec 2020 01:31:29 -0800 Subject: [PATCH 058/212] [dev.regabi] cmd/compile: move setUnderlying to package types Now that setUnderlying is decoupled from Nodes, it can be moved into package types, where it really belongs. [git-generate] cd src/cmd/compile/internal/gc rf ' mv setUnderlying SetUnderlying mv SetUnderlying typex.go mv typex.go cmd/compile/internal/types ' cd ../types rf ' mv typex.go type.go ' Change-Id: I76e2d4d8a6df599f24a731c4d8e5774ec83a119c Reviewed-on: https://go-review.googlesource.com/c/go/+/274433 Trust: Matthew Dempsky Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/iimport.go | 2 +- src/cmd/compile/internal/gc/typecheck.go | 46 +----------------------- src/cmd/compile/internal/types/type.go | 45 +++++++++++++++++++++++ 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 57c5e62182..0696d05c11 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -316,7 +316,7 @@ func (r *importReader) doDecl(n ir.Node) { // after the underlying type has been assigned. defercheckwidth() underlying := r.typ() - setUnderlying(t, underlying) + types.SetUnderlying(t, underlying) resumecheckwidth() if underlying.IsInterface() { diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index d9ec06c531..6858b51699 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3427,50 +3427,6 @@ func checkMapKeys() { mapqueue = nil } -func setUnderlying(t, underlying *types.Type) { - if underlying.Etype == types.TFORW { - // This type isn't computed yet; when it is, update n. - underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t) - return - } - - ft := t.ForwardType() - - // TODO(mdempsky): Fix Type rekinding. - t.Etype = underlying.Etype - t.Extra = underlying.Extra - t.Width = underlying.Width - t.Align = underlying.Align - t.Orig = underlying.Orig - - if underlying.NotInHeap() { - t.SetNotInHeap(true) - } - if underlying.Broke() { - t.SetBroke(true) - } - - // spec: "The declared type does not inherit any methods bound - // to the existing type, but the method set of an interface - // type [...] remains unchanged." - if t.IsInterface() { - *t.Methods() = *underlying.Methods() - *t.AllMethods() = *underlying.AllMethods() - } - - // Update types waiting on this type. - for _, w := range ft.Copyto { - setUnderlying(w, t) - } - - // Double-check use of type as embedded type. - if ft.Embedlineno.IsKnown() { - if t.IsPtr() || t.IsUnsafePtr() { - base.ErrorfAt(ft.Embedlineno, "embedded type cannot be a pointer") - } - } -} - func typecheckdeftype(n *ir.Name) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckdeftype", n)(nil) @@ -3492,7 +3448,7 @@ func typecheckdeftype(n *ir.Name) { errorsBefore := base.Errors() n.Ntype = typecheckNtype(n.Ntype) if underlying := n.Ntype.Type(); underlying != nil { - setUnderlying(t, underlying) + types.SetUnderlying(t, underlying) } else { n.SetDiag(true) n.SetType(nil) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 8499a36edc..2a65b713be 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -5,6 +5,7 @@ package types import ( + "cmd/compile/internal/base" "cmd/internal/obj" "cmd/internal/src" "fmt" @@ -1517,3 +1518,47 @@ var ( TypeVoid = newSSA("void") TypeInt128 = newSSA("int128") ) + +func SetUnderlying(t, underlying *Type) { + if underlying.Etype == TFORW { + // This type isn't computed yet; when it is, update n. + underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t) + return + } + + ft := t.ForwardType() + + // TODO(mdempsky): Fix Type rekinding. + t.Etype = underlying.Etype + t.Extra = underlying.Extra + t.Width = underlying.Width + t.Align = underlying.Align + t.Orig = underlying.Orig + + if underlying.NotInHeap() { + t.SetNotInHeap(true) + } + if underlying.Broke() { + t.SetBroke(true) + } + + // spec: "The declared type does not inherit any methods bound + // to the existing type, but the method set of an interface + // type [...] remains unchanged." + if t.IsInterface() { + *t.Methods() = *underlying.Methods() + *t.AllMethods() = *underlying.AllMethods() + } + + // Update types waiting on this type. + for _, w := range ft.Copyto { + SetUnderlying(w, t) + } + + // Double-check use of type as embedded type. + if ft.Embedlineno.IsKnown() { + if t.IsPtr() || t.IsUnsafePtr() { + base.ErrorfAt(ft.Embedlineno, "embedded type cannot be a pointer") + } + } +} From f37aa5e4e26a7212b6300e2021b8e6ea7000979b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 1 Dec 2020 01:42:47 -0800 Subject: [PATCH 059/212] [dev.regabi] cmd/compile: add NewNamed The start of abstracting away Type fields. This adds a new constructor for named types, styled after go/types.NewNamed. Along with helper methods for SetNod and Pos, this allows hiding Nod. Change-Id: Ica107034b6346c7b523bf6ae2a34009e350a9aa8 Reviewed-on: https://go-review.googlesource.com/c/go/+/274434 Trust: Matthew Dempsky Reviewed-by: Russ Cox --- src/cmd/compile/fmtmap_test.go | 1 + src/cmd/compile/internal/gc/align.go | 6 +-- src/cmd/compile/internal/gc/export.go | 4 +- src/cmd/compile/internal/gc/iexport.go | 2 +- src/cmd/compile/internal/gc/iimport.go | 2 +- src/cmd/compile/internal/gc/subr.go | 8 ++-- src/cmd/compile/internal/gc/typecheck.go | 14 +------ src/cmd/compile/internal/gc/universe.go | 13 +++--- src/cmd/compile/internal/ir/expr.go | 8 +--- src/cmd/compile/internal/ir/type.go | 29 ++++---------- src/cmd/compile/internal/types/type.go | 51 +++++++++++++++++++++--- 11 files changed, 75 insertions(+), 63 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index 09b06c4d93..ca31705f72 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -130,6 +130,7 @@ var knownFormats = map[string]string{ "cmd/compile/internal/types.EType %d": "", "cmd/compile/internal/types.EType %s": "", "cmd/compile/internal/types.EType %v": "", + "cmd/compile/internal/types.IRNode %v": "", "cmd/internal/obj.ABI %v": "", "error %v": "", "float64 %.2f": "", diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index ffae8dc27b..5171983af0 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -205,7 +205,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { } *path = append(*path, t) - if findTypeLoop(ir.AsNode(t.Nod).Name().Ntype.Type(), path) { + if findTypeLoop(t.Obj().(*ir.Name).Ntype.Type(), path) { return true } *path = (*path)[:len(*path)-1] @@ -314,8 +314,8 @@ func dowidth(t *types.Type) { defercheckwidth() lno := base.Pos - if ir.AsNode(t.Nod) != nil { - base.Pos = ir.AsNode(t.Nod).Pos() + if pos := t.Pos(); pos.IsKnown() { + base.Pos = pos } t.Width = -2 diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 5cd379a7d3..f803a17c60 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -101,9 +101,7 @@ func importsym(ipkg *types.Pkg, s *types.Sym, op ir.Op) ir.Node { func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type { n := importsym(ipkg, s, ir.OTYPE) if n.Op() != ir.OTYPE { - t := types.New(types.TFORW) - t.Sym = s - t.Nod = n + t := types.NewNamed(n) n.SetOp(ir.OTYPE) n.SetPos(pos) diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index d6c50c7285..2dfce26596 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -640,7 +640,7 @@ func (w *exportWriter) doTyp(t *types.Type) { } w.startType(definedType) - w.qualifiedIdent(ir.TypeNode(t)) + w.qualifiedIdent(t.Obj().(*ir.Name)) return } diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 0696d05c11..15f1b646f7 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -316,7 +316,7 @@ func (r *importReader) doDecl(n ir.Node) { // after the underlying type has been assigned. defercheckwidth() underlying := r.typ() - types.SetUnderlying(t, underlying) + t.SetUnderlying(underlying) resumecheckwidth() if underlying.IsInterface() { diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 0163653d3b..04c8c537bd 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -1490,9 +1490,9 @@ func ifaceData(pos src.XPos, n ir.Node, t *types.Type) ir.Node { // typePos returns the position associated with t. // This is where t was declared or where it appeared as a type expression. func typePos(t *types.Type) src.XPos { - n := ir.AsNode(t.Nod) - if n == nil || !n.Pos().IsKnown() { - base.Fatalf("bad type: %v", t) + if pos := t.Pos(); pos.IsKnown() { + return pos } - return n.Pos() + base.Fatalf("bad type: %v", t) + panic("unreachable") } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 6858b51699..dccb5ecdce 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3432,10 +3432,8 @@ func typecheckdeftype(n *ir.Name) { defer tracePrint("typecheckdeftype", n)(nil) } - t := types.New(types.TFORW) - t.Sym = n.Sym() + t := types.NewNamed(n) t.Vargen = n.Vargen - t.Nod = n if n.Pragma()&ir.NotInHeap != 0 { t.SetNotInHeap(true) } @@ -3448,7 +3446,7 @@ func typecheckdeftype(n *ir.Name) { errorsBefore := base.Errors() n.Ntype = typecheckNtype(n.Ntype) if underlying := n.Ntype.Type(); underlying != nil { - types.SetUnderlying(t, underlying) + t.SetUnderlying(underlying) } else { n.SetDiag(true) n.SetType(nil) @@ -3895,14 +3893,6 @@ func deadcodeexpr(n ir.Node) ir.Node { return n } -func toTypeNode(orig ir.Node, t *types.Type) ir.Node { - n := ir.Nod(ir.OTYPE, nil, nil) - n.SetPos(orig.Pos()) - n.SetType(t) - t.Nod = n - return n -} - // getIotaValue returns the current value for "iota", // or -1 if not within a ConstSpec. func getIotaValue() int64 { diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index c3c2c0492a..31b49e05a5 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -337,11 +337,12 @@ func makeErrorInterface() *types.Type { func lexinit1() { // error type - s := ir.BuiltinPkg.Lookup("error") - types.Errortype = makeErrorInterface() - types.Errortype.Sym = s - types.Errortype.Orig = makeErrorInterface() - s.Def = ir.TypeNode(types.Errortype) + n := ir.NewNameAt(src.NoXPos, ir.BuiltinPkg.Lookup("error")) + types.Errortype = types.NewNamed(n) + types.Errortype.SetUnderlying(makeErrorInterface()) + n.SetOp(ir.OTYPE) + n.SetType(types.Errortype) + n.Sym().Def = n dowidth(types.Errortype) // We create separate byte and rune types for better error messages @@ -353,7 +354,7 @@ func lexinit1() { // type aliases, albeit at the cost of having to deal with it everywhere). // byte alias - s = ir.BuiltinPkg.Lookup("byte") + s := ir.BuiltinPkg.Lookup("byte") types.Bytetype = types.New(types.TUINT8) types.Bytetype.Sym = s s.Def = ir.TypeNode(types.Bytetype) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 87593520a1..2a7211cfda 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -545,9 +545,7 @@ func (*ParenExpr) CanBeNtype() {} func (n *ParenExpr) SetOTYPE(t *types.Type) { n.op = OTYPE n.typ = t - if t.Nod == nil { - t.Nod = n - } + t.SetNod(n) } // A ResultExpr represents a direct access to a result slot on the stack frame. @@ -762,9 +760,7 @@ func (n *StarExpr) SetOTYPE(t *types.Type) { n.op = OTYPE n.X = nil n.typ = t - if t.Nod == nil { - t.Nod = n - } + t.SetNod(n) } func (n *StarExpr) DeepCopy(pos src.XPos) Node { diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index af8db15e84..446145b24c 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -5,6 +5,7 @@ package ir import ( + "cmd/compile/internal/base" "cmd/compile/internal/types" "cmd/internal/src" "fmt" @@ -51,12 +52,7 @@ func (n *miniType) setOTYPE(t *types.Type, self Node) { } n.op = OTYPE n.typ = t - - // t.Nod can be non-nil already - // in the case of shared *type.Types, like []byte or interface{}. - if t.Nod == nil { - t.Nod = self - } + t.SetNod(self) } func (n *miniType) Sym() *types.Sym { return nil } // for Format OTYPE @@ -362,20 +358,11 @@ func (n *typeNode) CanBeNtype() {} // TypeNode returns the Node representing the type t. func TypeNode(t *types.Type) Ntype { - return TypeNodeAt(src.NoXPos, t) -} - -// TypeNodeAt returns the Node representing the type t. -// If the node must be created, TypeNodeAt uses the position pos. -// TODO(rsc): Does anyone actually use position on these type nodes? -func TypeNodeAt(pos src.XPos, t *types.Type) Ntype { - // If we copied another type with *t = *u, - // then t.Nod might be out of date, so check t.Nod.Type() too. - n := AsNode(t.Nod) - if n == nil || n.Type() != t { - n := newTypeNode(pos, t) // t.Sym may be nil - t.Nod = n - return n + if n := t.Obj(); n != nil { + if n.Type() != t { + base.Fatalf("type skew: %v has type %v, but expected %v", n, n.Type(), t) + } + return n.(Ntype) } - return n.(Ntype) + return newTypeNode(src.NoXPos, t) } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 2a65b713be..d6d56426a5 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -14,7 +14,11 @@ import ( // IRNode represents an ir.Node, but without needing to import cmd/compile/internal/ir, // which would cause an import cycle. The uses in other packages must type assert // values of type IRNode to ir.Node or a more specific type. -type IRNode interface{ Type() *Type } +type IRNode interface { + Pos() src.XPos + Sym() *Sym + Type() *Type +} //go:generate stringer -type EType -trimprefix T @@ -142,7 +146,7 @@ type Type struct { methods Fields allMethods Fields - Nod IRNode // canonical OTYPE node + nod IRNode // canonical OTYPE node Orig *Type // original type (type literal or predefined type) // Cache of composite types, with this type being the element type. @@ -180,6 +184,24 @@ func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) } func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) } func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) } +// SetNod associates t with syntax node n. +func (t *Type) SetNod(n IRNode) { + // t.nod can be non-nil already + // in the case of shared *Types, like []byte or interface{}. + if t.nod == nil { + t.nod = n + } +} + +// Pos returns a position associated with t, if any. +// This should only be used for diagnostics. +func (t *Type) Pos() src.XPos { + if t.nod != nil { + return t.nod.Pos() + } + return src.NoXPos +} + // Pkg returns the package that t appeared in. // // Pkg is only defined for function, struct, and interface types @@ -1519,7 +1541,24 @@ var ( TypeInt128 = newSSA("int128") ) -func SetUnderlying(t, underlying *Type) { +// NewNamed returns a new named type for the given type name. +func NewNamed(obj IRNode) *Type { + t := New(TFORW) + t.Sym = obj.Sym() + t.nod = obj + return t +} + +// Obj returns the type name for the named type t. +func (t *Type) Obj() IRNode { + if t.Sym != nil { + return t.nod + } + return nil +} + +// SetUnderlying sets the underlying type. +func (t *Type) SetUnderlying(underlying *Type) { if underlying.Etype == TFORW { // This type isn't computed yet; when it is, update n. underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t) @@ -1546,13 +1585,13 @@ func SetUnderlying(t, underlying *Type) { // to the existing type, but the method set of an interface // type [...] remains unchanged." if t.IsInterface() { - *t.Methods() = *underlying.Methods() - *t.AllMethods() = *underlying.AllMethods() + t.methods = underlying.methods + t.allMethods = underlying.allMethods } // Update types waiting on this type. for _, w := range ft.Copyto { - SetUnderlying(w, t) + w.SetUnderlying(t) } // Double-check use of type as embedded type. From a17c5e2fce9340ec19d4019490b38a7645f244df Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 1 Dec 2020 02:58:41 -0800 Subject: [PATCH 060/212] [dev.regabi] cmd/compile: add NewBasic and cleanup universe This CL introduces types.NewBasic, for creating the predeclared universal types, and reorganizes how the universe is initialized so that all predeclared types are uniformly constructed. There are now a bunch of Type fields that are no longer assigned outside of the package, so this CL also introduces some new accessor methods that a subsequent CL will mechanically introduce uses of. Change-Id: Ie7996c3d5f1ca46cd5bfe45ecc91ebfa6a7b6c7d Reviewed-on: https://go-review.googlesource.com/c/go/+/274435 Trust: Matthew Dempsky Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/universe.go | 200 +++++++++--------------- src/cmd/compile/internal/types/type.go | 21 ++- 2 files changed, 93 insertions(+), 128 deletions(-) diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 31b49e05a5..b1492659b4 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -87,31 +87,80 @@ var unsafeFuncs = [...]struct { // initUniverse initializes the universe block. func initUniverse() { - lexinit() - typeinit() - lexinit1() -} - -// lexinit initializes known symbols and the basic types. -func lexinit() { - for _, s := range &basicTypes { - etype := s.etype - if int(etype) >= len(types.Types) { - base.Fatalf("lexinit: %s bad etype", s.name) - } - s2 := ir.BuiltinPkg.Lookup(s.name) - t := types.Types[etype] - if t == nil { - t = types.New(etype) - t.Sym = s2 - if etype != types.TANY && etype != types.TSTRING { - dowidth(t) - } - types.Types[etype] = t - } - s2.Def = ir.TypeNode(t) + if Widthptr == 0 { + base.Fatalf("typeinit before betypeinit") } + slicePtrOffset = 0 + sliceLenOffset = Rnd(slicePtrOffset+int64(Widthptr), int64(Widthptr)) + sliceCapOffset = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) + sizeofSlice = Rnd(sliceCapOffset+int64(Widthptr), int64(Widthptr)) + + // string is same as slice wo the cap + sizeofString = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) + + for et := types.EType(0); et < types.NTYPE; et++ { + simtype[et] = et + } + + types.Types[types.TANY] = types.New(types.TANY) + types.Types[types.TINTER] = types.New(types.TINTER) // empty interface + + defBasic := func(kind types.EType, pkg *types.Pkg, name string) *types.Type { + sym := pkg.Lookup(name) + n := ir.NewNameAt(src.NoXPos, sym) + n.SetOp(ir.OTYPE) + t := types.NewBasic(kind, n) + n.SetType(t) + sym.Def = n + if kind != types.TANY { + dowidth(t) + } + return t + } + + for _, s := range &basicTypes { + types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name) + } + + for _, s := range &typedefs { + sameas := s.sameas32 + if Widthptr == 8 { + sameas = s.sameas64 + } + simtype[s.etype] = sameas + + types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name) + } + + // We create separate byte and rune types for better error messages + // rather than just creating type alias *types.Sym's for the uint8 and + // int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false. + // TODO(gri) Should we get rid of this special case (at the cost + // of less informative error messages involving bytes and runes)? + // (Alternatively, we could introduce an OTALIAS node representing + // type aliases, albeit at the cost of having to deal with it everywhere). + types.Bytetype = defBasic(types.TUINT8, ir.BuiltinPkg, "byte") + types.Runetype = defBasic(types.TINT32, ir.BuiltinPkg, "rune") + + // error type + s := ir.BuiltinPkg.Lookup("error") + n := ir.NewNameAt(src.NoXPos, s) + n.SetOp(ir.OTYPE) + types.Errortype = types.NewNamed(n) + types.Errortype.SetUnderlying(makeErrorInterface()) + n.SetType(types.Errortype) + s.Def = n + dowidth(types.Errortype) + + types.Types[types.TUNSAFEPTR] = defBasic(types.TUNSAFEPTR, unsafepkg, "Pointer") + + // simple aliases + simtype[types.TMAP] = types.TPTR + simtype[types.TCHAN] = types.TPTR + simtype[types.TFUNC] = types.TPTR + simtype[types.TUNSAFEPTR] = types.TPTR + for _, s := range &builtinFuncs { s2 := ir.BuiltinPkg.Lookup(s.name) s2.Def = NewName(s2) @@ -124,19 +173,13 @@ func lexinit() { ir.AsNode(s2.Def).SetSubOp(s.op) } - types.UntypedString = types.New(types.TSTRING) - types.UntypedBool = types.New(types.TBOOL) - types.Types[types.TANY] = types.New(types.TANY) - - s := ir.BuiltinPkg.Lookup("true") + s = ir.BuiltinPkg.Lookup("true") s.Def = nodbool(true) ir.AsNode(s.Def).SetSym(lookup("true")) - ir.AsNode(s.Def).SetType(types.UntypedBool) s = ir.BuiltinPkg.Lookup("false") s.Def = nodbool(false) ir.AsNode(s.Def).SetSym(lookup("false")) - ir.AsNode(s.Def).SetType(types.UntypedBool) s = lookup("_") s.Block = -100 @@ -160,28 +203,6 @@ func lexinit() { s = ir.BuiltinPkg.Lookup("iota") s.Def = ir.Nod(ir.OIOTA, nil, nil) ir.AsNode(s.Def).SetSym(s) -} - -func typeinit() { - if Widthptr == 0 { - base.Fatalf("typeinit before betypeinit") - } - - for et := types.EType(0); et < types.NTYPE; et++ { - simtype[et] = et - } - - types.Types[types.TPTR] = types.New(types.TPTR) - dowidth(types.Types[types.TPTR]) - - t := types.New(types.TUNSAFEPTR) - types.Types[types.TUNSAFEPTR] = t - t.Sym = unsafepkg.Lookup("Pointer") - n := ir.NewNameAt(src.NoXPos, t.Sym) // NewNameAt to get a package for use tracking - n.SetOp(ir.OTYPE) - n.SetType(t) - t.Sym.Def = n - dowidth(types.Types[types.TUNSAFEPTR]) for et := types.TINT8; et <= types.TUINT64; et++ { isInt[et] = true @@ -259,8 +280,7 @@ func typeinit() { okforcmp[types.TSTRING] = true - var i int - for i = 0; i < len(okfor); i++ { + for i := range okfor { okfor[i] = okfornone[:] } @@ -302,25 +322,6 @@ func typeinit() { iscmp[ir.OLE] = true iscmp[ir.OEQ] = true iscmp[ir.ONE] = true - - types.Types[types.TINTER] = types.New(types.TINTER) // empty interface - - // simple aliases - simtype[types.TMAP] = types.TPTR - simtype[types.TCHAN] = types.TPTR - simtype[types.TFUNC] = types.TPTR - simtype[types.TUNSAFEPTR] = types.TPTR - - slicePtrOffset = 0 - sliceLenOffset = Rnd(slicePtrOffset+int64(Widthptr), int64(Widthptr)) - sliceCapOffset = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) - sizeofSlice = Rnd(sliceCapOffset+int64(Widthptr), int64(Widthptr)) - - // string is same as slice wo the cap - sizeofString = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) - - dowidth(types.Types[types.TSTRING]) - dowidth(types.UntypedString) } func makeErrorInterface() *types.Type { @@ -335,59 +336,6 @@ func makeErrorInterface() *types.Type { return t } -func lexinit1() { - // error type - n := ir.NewNameAt(src.NoXPos, ir.BuiltinPkg.Lookup("error")) - types.Errortype = types.NewNamed(n) - types.Errortype.SetUnderlying(makeErrorInterface()) - n.SetOp(ir.OTYPE) - n.SetType(types.Errortype) - n.Sym().Def = n - dowidth(types.Errortype) - - // We create separate byte and rune types for better error messages - // rather than just creating type alias *types.Sym's for the uint8 and - // int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false. - // TODO(gri) Should we get rid of this special case (at the cost - // of less informative error messages involving bytes and runes)? - // (Alternatively, we could introduce an OTALIAS node representing - // type aliases, albeit at the cost of having to deal with it everywhere). - - // byte alias - s := ir.BuiltinPkg.Lookup("byte") - types.Bytetype = types.New(types.TUINT8) - types.Bytetype.Sym = s - s.Def = ir.TypeNode(types.Bytetype) - dowidth(types.Bytetype) - - // rune alias - s = ir.BuiltinPkg.Lookup("rune") - types.Runetype = types.New(types.TINT32) - types.Runetype.Sym = s - s.Def = ir.TypeNode(types.Runetype) - dowidth(types.Runetype) - - // backend-dependent builtin types (e.g. int). - for _, s := range &typedefs { - s1 := ir.BuiltinPkg.Lookup(s.name) - - sameas := s.sameas32 - if Widthptr == 8 { - sameas = s.sameas64 - } - - simtype[s.etype] = sameas - - t := types.New(s.etype) - t.Sym = s1 - types.Types[s.etype] = t - s1.Def = ir.TypeNode(t) - s1.Origpkg = ir.BuiltinPkg - - dowidth(t) - } -} - // finishUniverse makes the universe block visible within the current package. func finishUniverse() { // Operationally, this is similar to a dot import of builtinpkg, except diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index d6d56426a5..f0211a67fb 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -110,8 +110,8 @@ var ( Errortype *Type // Types to represent untyped string and boolean constants. - UntypedString *Type - UntypedBool *Type + UntypedString = New(TSTRING) + UntypedBool = New(TBOOL) // Types to represent untyped numeric constants. UntypedInt = New(TIDEAL) @@ -184,6 +184,15 @@ func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) } func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) } func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) } +// Kind returns the kind of type t. +func (t *Type) Kind() EType { return t.Etype } + +// Sym returns the name of type t. +func (t *Type) GetSym() *Sym { return t.Sym } + +// Underlying returns the underlying type of type t. +func (t *Type) Underlying() *Type { return t.Orig } + // SetNod associates t with syntax node n. func (t *Type) SetNod(n IRNode) { // t.nod can be non-nil already @@ -1601,3 +1610,11 @@ func (t *Type) SetUnderlying(underlying *Type) { } } } + +// NewNamed returns a new basic type of the given kind. +func NewBasic(kind EType, obj IRNode) *Type { + t := New(kind) + t.Sym = obj.Sym() + t.nod = obj + return t +} From 6ca23a45feebc8672a1851dbc65c5b34d481ca30 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 1 Dec 2020 03:52:20 -0800 Subject: [PATCH 061/212] [dev.regabi] cmd/compile: only save ONAMEs on Curfn.Dcl There's not really any use to tracking function-scoped constants and types on Curfn.Dcl, and there's sloppy code that assumes all of the declarations are variables (e.g., cmpstackvarlt). Change-Id: I5d10dc681dac2c161c7b73ba808403052ca0608e Reviewed-on: https://go-review.googlesource.com/c/go/+/274436 Reviewed-by: Russ Cox Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/dcl.go | 2 +- test/live.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 637587392a..3b60496c5c 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -84,7 +84,7 @@ func declare(n *ir.Name, ctxt ir.Class) { base.Pos = n.Pos() base.Fatalf("automatic outside function") } - if Curfn != nil && ctxt != ir.PFUNC { + if Curfn != nil && ctxt != ir.PFUNC && n.Op() == ir.ONAME { Curfn.Dcl = append(Curfn.Dcl, n) } if n.Op() == ir.OTYPE { diff --git a/test/live.go b/test/live.go index 3df7ab01af..d52ce7f007 100644 --- a/test/live.go +++ b/test/live.go @@ -718,5 +718,5 @@ func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f" } ret := T{} ret.s[0] = f() - return ret // ERROR "stack object .autotmp_5 T" + return ret // ERROR "stack object .autotmp_[0-9]+ T" } From dd4a52c2a588c57edc76cb0a414ae6f2e5bf5d52 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 1 Dec 2020 11:10:40 -0500 Subject: [PATCH 062/212] doc/go1.16: add multiple release notes for the go command Added notes for: * go test -c and -i flags used with unknown flags * GO111MODULE=on by default * GOVCS * Dropped requirements on excluded versions Removed TODOs for documentation on the retract directive and 'go install pkg@version'. These pages will be written after the beta. Change-Id: Ic9877a62f908be177a6035a039b72e969e7b7f22 Reviewed-on: https://go-review.googlesource.com/c/go/+/274438 Trust: Jay Conrod Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- doc/go1.16.html | 57 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 71cd7e259e..145f920aab 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -80,17 +80,16 @@ Do not send CLs removing the interior tags from such phrases.

Go command

-

- TODO - - - - - -

-

Modules

+

+ Module-aware mode is enabled by default, regardless of whether a + go.mod file is present in the current working directory or a + parent directory. Specifically, the GO111MODULE environment + variable now defaults to on. To switch to the previous behavior, + set GO111MODULE to auto. +

+

Build commands like go build and go test no longer modify go.mod and go.sum @@ -107,9 +106,7 @@ Do not send CLs removing the interior tags from such phrases. install to build and install packages in module-aware mode, ignoring the go.mod file in the current directory or any parent directory, if there is one. This is useful for installing executables without - affecting the dependencies of the main module.
- TODO: write and link to section in golang.org/ref/mod
- TODO: write and link to blog post + affecting the dependencies of the main module.

@@ -127,8 +124,6 @@ Do not send CLs removing the interior tags from such phrases. to indicate that certain published versions of the module should not be used by other modules. A module author may retract a version after a severe problem is discovered or if the version was published unintentionally.
- TODO: write and link to section in golang.org/ref/mod
- TODO: write and link to tutorial or blog post

@@ -138,6 +133,14 @@ Do not send CLs removing the interior tags from such phrases. resolving missing packages.

+

+ The go command now ignores requirements on module versions + excluded by exclude directives in the main module. Previously, + the go command used the next version higher than an excluded + version, but that version could change over time, resulting in + non-reproducible builds. +

+

go test

@@ -150,6 +153,15 @@ Do not send CLs removing the interior tags from such phrases. that is still considered to be a passing test.

+

+ go test reports an error when the -c + or -i flags are used together with unknown flags. Normally, + unknown flags are passed to tests, but when -c or -i + are used, tests are not run. +

+ +

go get

+

The go get -insecure flag is deprecated and will be removed in a future version. This flag permits @@ -161,8 +173,6 @@ Do not send CLs removing the interior tags from such phrases. See go help environment for details.

-

go get

-

go get example.com/mod@patch now requires that some version of example.com/mod already be @@ -171,6 +181,21 @@ Do not send CLs removing the interior tags from such phrases. to patch even newly-added dependencies.)

+

GOVCS environment variable

+ +

+ GOVCS is a new environment variable that limits which version + control tools the go command may use to download source code. + This mitigates security issues with tools that are typically used in trusted, + authenticated environments. By default, git and hg + may be used to download code from any repository. svn, + bzr, and fossil may only be used to download code + from repositories with module paths or package paths matching patterns in + the GOPRIVATE environment variable. See + go + help vcs for details. +

+

The all pattern

From 5ffa275f3cab631483a1ce76a63fc4ede3d204e8 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 1 Dec 2020 03:25:29 -0800 Subject: [PATCH 063/212] [dev.regabi] cmd/compile: first pass at abstracting Type Passes toolstash/buildall. [git-generate] cd src/cmd/compile/internal/ssa rf ' ex . ../ir ../gc { import "cmd/compile/internal/types" var t *types.Type t.Etype -> t.Kind() t.Sym -> t.GetSym() t.Orig -> t.Underlying() } ' cd ../types rf ' mv EType Kind mv IRNode Object mv Type.Etype Type.kind mv Type.Sym Type.sym mv Type.Orig Type.underlying mv Type.Cache Type.cache mv Type.GetSym Type.Sym mv Bytetype ByteType mv Runetype RuneType mv Errortype ErrorType ' cd ../gc sed -i 's/Bytetype/ByteType/; s/Runetype/RuneType/' mkbuiltin.go git codereview gofmt go install cmd/compile/internal/... go test cmd/compile -u || go test cmd/compile Change-Id: Ibecb2d7100d3318a49238eb4a78d70acb49eedca Reviewed-on: https://go-review.googlesource.com/c/go/+/274437 Run-TryBot: Matthew Dempsky Reviewed-by: Russ Cox Trust: Matthew Dempsky --- src/cmd/compile/fmtmap_test.go | 8 +- src/cmd/compile/internal/gc/alg.go | 12 +- src/cmd/compile/internal/gc/align.go | 12 +- src/cmd/compile/internal/gc/bexport.go | 10 +- src/cmd/compile/internal/gc/builtin.go | 4 +- src/cmd/compile/internal/gc/const.go | 22 +-- src/cmd/compile/internal/gc/dcl.go | 18 +- src/cmd/compile/internal/gc/embed.go | 4 +- src/cmd/compile/internal/gc/escape.go | 2 +- src/cmd/compile/internal/gc/go.go | 2 +- src/cmd/compile/internal/gc/iexport.go | 18 +- src/cmd/compile/internal/gc/inl.go | 4 +- src/cmd/compile/internal/gc/mkbuiltin.go | 4 +- src/cmd/compile/internal/gc/obj.go | 6 +- src/cmd/compile/internal/gc/order.go | 2 +- src/cmd/compile/internal/gc/plive.go | 4 +- src/cmd/compile/internal/gc/range.go | 12 +- src/cmd/compile/internal/gc/reflect.go | 76 ++++---- src/cmd/compile/internal/gc/ssa.go | 56 +++--- src/cmd/compile/internal/gc/subr.go | 72 +++---- src/cmd/compile/internal/gc/swt.go | 4 +- src/cmd/compile/internal/gc/typecheck.go | 80 ++++---- src/cmd/compile/internal/gc/universe.go | 26 +-- src/cmd/compile/internal/gc/walk.go | 48 ++--- src/cmd/compile/internal/ir/fmt.go | 50 ++--- src/cmd/compile/internal/ir/node.go | 2 +- src/cmd/compile/internal/ir/type.go | 2 +- src/cmd/compile/internal/ir/val.go | 2 +- src/cmd/compile/internal/ssa/expand_calls.go | 16 +- src/cmd/compile/internal/ssa/export_test.go | 6 +- src/cmd/compile/internal/ssa/regalloc.go | 4 +- .../compile/internal/types/etype_string.go | 4 +- src/cmd/compile/internal/types/identity.go | 12 +- src/cmd/compile/internal/types/scope.go | 8 +- src/cmd/compile/internal/types/sym.go | 2 +- src/cmd/compile/internal/types/type.go | 182 +++++++++--------- 36 files changed, 398 insertions(+), 398 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index ca31705f72..fde9c51b27 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -127,10 +127,10 @@ var knownFormats = map[string]string{ "cmd/compile/internal/syntax.position %s": "", "cmd/compile/internal/syntax.token %q": "", "cmd/compile/internal/syntax.token %s": "", - "cmd/compile/internal/types.EType %d": "", - "cmd/compile/internal/types.EType %s": "", - "cmd/compile/internal/types.EType %v": "", - "cmd/compile/internal/types.IRNode %v": "", + "cmd/compile/internal/types.Kind %d": "", + "cmd/compile/internal/types.Kind %s": "", + "cmd/compile/internal/types.Kind %v": "", + "cmd/compile/internal/types.Object %v": "", "cmd/internal/obj.ABI %v": "", "error %v": "", "float64 %.2f": "", diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go index 806417d03d..b2716399a5 100644 --- a/src/cmd/compile/internal/gc/alg.go +++ b/src/cmd/compile/internal/gc/alg.go @@ -68,7 +68,7 @@ func IncomparableField(t *types.Type) *types.Field { // EqCanPanic reports whether == on type t could panic (has an interface somewhere). // t must be comparable. func EqCanPanic(t *types.Type) bool { - switch t.Etype { + switch t.Kind() { default: return false case types.TINTER: @@ -120,7 +120,7 @@ func algtype1(t *types.Type) (AlgKind, *types.Type) { return ANOEQ, t } - switch t.Etype { + switch t.Kind() { case types.TANY, types.TFORW: // will be defined later. return ANOEQ, t @@ -274,7 +274,7 @@ func genhash(t *types.Type) *obj.LSym { // (And the closure generated by genhash will also get // dead-code eliminated, as we call the subtype hashers // directly.) - switch t.Etype { + switch t.Kind() { case types.TARRAY: genhash(t.Elem()) case types.TSTRUCT: @@ -303,7 +303,7 @@ func genhash(t *types.Type) *obj.LSym { np := ir.AsNode(tfn.Type().Params().Field(0).Nname) nh := ir.AsNode(tfn.Type().Params().Field(1).Nname) - switch t.Etype { + switch t.Kind() { case types.TARRAY: // An array of pure memory would be handled by the // standard algorithm, so the element type must not be @@ -536,7 +536,7 @@ func geneq(t *types.Type) *obj.LSym { // We reach here only for types that have equality but // cannot be handled by the standard algorithms, // so t must be either an array or a struct. - switch t.Etype { + switch t.Kind() { default: base.Fatalf("geneq %v", t) @@ -613,7 +613,7 @@ func geneq(t *types.Type) *obj.LSym { } } - switch t.Elem().Etype { + switch t.Elem().Kind() { case types.TSTRING: // Do two loops. First, check that all the lengths match (cheap). // Second, check that all the contents match (expensive). diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index 5171983af0..af426f5b24 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -185,7 +185,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { // We implement a simple DFS loop-finding algorithm. This // could be faster, but type cycles are rare. - if t.Sym != nil { + if t.Sym() != nil { // Declared type. Check for loops and otherwise // recurse on the type expression used in the type // declaration. @@ -193,7 +193,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { // Type imported from package, so it can't be part of // a type loop (otherwise that package should have // failed to compile). - if t.Sym.Pkg != ir.LocalPkg { + if t.Sym().Pkg != ir.LocalPkg { return false } @@ -212,7 +212,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { } else { // Anonymous type. Recurse on contained types. - switch t.Etype { + switch t.Kind() { case types.TARRAY: if findTypeLoop(t.Elem(), path) { return true @@ -321,15 +321,15 @@ func dowidth(t *types.Type) { t.Width = -2 t.Align = 0 // 0 means use t.Width, below - et := t.Etype + et := t.Kind() switch et { case types.TFUNC, types.TCHAN, types.TMAP, types.TSTRING: break // simtype == 0 during bootstrap default: - if simtype[t.Etype] != 0 { - et = simtype[t.Etype] + if simtype[t.Kind()] != 0 { + et = simtype[t.Kind()] } } diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index dbbac559ae..43c4ce7150 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -35,7 +35,7 @@ func (p *exporter) markType(t *types.Type) { // 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.Etype != types.TINTER { + 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)) @@ -52,7 +52,7 @@ func (p *exporter) markType(t *types.Type) { // Notably, we don't mark function parameter types, because // the user already needs some way to construct values of // those types. - switch t.Etype { + switch t.Kind() { case types.TPTR, types.TARRAY, types.TSLICE: p.markType(t.Elem()) @@ -153,11 +153,11 @@ func predeclared() []*types.Type { types.Types[types.TSTRING], // basic type aliases - types.Bytetype, - types.Runetype, + types.ByteType, + types.RuneType, // error - types.Errortype, + types.ErrorType, // untyped types types.UntypedBool, diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go index efca44c667..07e864dd2e 100644 --- a/src/cmd/compile/internal/gc/builtin.go +++ b/src/cmd/compile/internal/gc/builtin.go @@ -206,7 +206,7 @@ var runtimeDecls = [...]struct { func runtimeTypes() []*types.Type { var typs [131]*types.Type - typs[0] = types.Bytetype + typs[0] = types.ByteType typs[1] = types.NewPtr(typs[0]) typs[2] = types.Types[types.TANY] typs[3] = types.NewPtr(typs[2]) @@ -252,7 +252,7 @@ func runtimeTypes() []*types.Type { typs[43] = functype(nil, []*ir.Field{anonfield(typs[42]), anonfield(typs[22])}, []*ir.Field{anonfield(typs[28])}) typs[44] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[1]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[28])}) typs[45] = functype(nil, []*ir.Field{anonfield(typs[1]), anonfield(typs[15])}, []*ir.Field{anonfield(typs[28])}) - typs[46] = types.Runetype + typs[46] = types.RuneType typs[47] = types.NewSlice(typs[46]) typs[48] = functype(nil, []*ir.Field{anonfield(typs[33]), anonfield(typs[47])}, []*ir.Field{anonfield(typs[28])}) typs[49] = types.NewSlice(typs[0]) diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 4dee373bfa..4a61c77630 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -127,7 +127,7 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir } // Nil is technically not a constant, so handle it specially. - if n.Type().Etype == types.TNIL { + if n.Type().Kind() == types.TNIL { if n.Op() != ir.ONIL { base.Fatalf("unexpected op: %v (%v)", n, n.Op()) } @@ -147,7 +147,7 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir return n } - if t == nil || !ir.OKForConst[t.Etype] { + if t == nil || !ir.OKForConst[t.Kind()] { t = defaultType(n.Type()) } @@ -245,7 +245,7 @@ func operandType(op ir.Op, t *types.Type) *types.Type { return complexForFloat(t) } default: - if okfor[op][t.Etype] { + if okfor[op][t.Kind()] { return t } } @@ -499,12 +499,12 @@ func evalConst(n ir.Node) ir.Node { } case ir.OCONV, ir.ORUNESTR: - if ir.OKForConst[n.Type().Etype] && nl.Op() == ir.OLITERAL { + if ir.OKForConst[n.Type().Kind()] && nl.Op() == ir.OLITERAL { return origConst(n, convertVal(nl.Val(), n.Type(), true)) } case ir.OCONVNOP: - if ir.OKForConst[n.Type().Etype] && nl.Op() == ir.OLITERAL { + if ir.OKForConst[n.Type().Kind()] && nl.Op() == ir.OLITERAL { // set so n.Orig gets OCONV instead of OCONVNOP n.SetOp(ir.OCONV) return origConst(n, nl.Val()) @@ -555,7 +555,7 @@ func evalConst(n ir.Node) ir.Node { return n case ir.OCAP, ir.OLEN: - switch nl.Type().Etype { + switch nl.Type().Kind() { case types.TSTRING: if ir.IsConst(nl, constant.String) { return origIntConst(n, int64(len(nl.StringVal()))) @@ -729,7 +729,7 @@ func mixUntyped(t1, t2 *types.Type) *types.Type { } func defaultType(t *types.Type) *types.Type { - if !t.IsUntyped() || t.Etype == types.TNIL { + if !t.IsUntyped() || t.Kind() == types.TNIL { return t } @@ -741,7 +741,7 @@ func defaultType(t *types.Type) *types.Type { case types.UntypedInt: return types.Types[types.TINT] case types.UntypedRune: - return types.Runetype + return types.RuneType case types.UntypedFloat: return types.Types[types.TFLOAT64] case types.UntypedComplex: @@ -769,7 +769,7 @@ func indexconst(n ir.Node) int64 { if n.Op() != ir.OLITERAL { return -1 } - if !n.Type().IsInteger() && n.Type().Etype != types.TIDEAL { + if !n.Type().IsInteger() && n.Type().Kind() != types.TIDEAL { return -1 } @@ -885,9 +885,9 @@ func (s *constSet) add(pos src.XPos, n ir.Node, what, where string) { typ := n.Type() switch typ { - case types.Bytetype: + case types.ByteType: typ = types.Types[types.TUINT8] - case types.Runetype: + case types.RuneType: typ = types.Types[types.TINT32] } k := constSetKey{typ, ir.ConstValue(n)} diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 3b60496c5c..3d0bdaec7a 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -445,7 +445,7 @@ func funcarg(n *ir.Field, ctxt ir.Class) { // This happens during import, where the hidden_fndcl rule has // used functype directly to parse the function's type. func funcargs2(t *types.Type) { - if t.Etype != types.TFUNC { + if t.Kind() != types.TFUNC { base.Fatalf("funcargs2 %v", t) } @@ -496,7 +496,7 @@ func checkembeddedtype(t *types.Type) { return } - if t.Sym == nil && t.IsPtr() { + if t.Sym() == nil && t.IsPtr() { t = t.Elem() if t.IsInterface() { base.Errorf("embedded type cannot be a pointer to interface") @@ -505,7 +505,7 @@ func checkembeddedtype(t *types.Type) { if t.IsPtr() || t.IsUnsafePtr() { base.Errorf("embedded type cannot be a pointer") - } else if t.Etype == types.TFORW && !t.ForwardType().Embedlineno.IsKnown() { + } else if t.Kind() == types.TFORW && !t.ForwardType().Embedlineno.IsKnown() { t.ForwardType().Embedlineno = base.Pos } } @@ -719,12 +719,12 @@ func methodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy base.Fatalf("blank method name") } - rsym := recv.Sym + rsym := recv.Sym() if recv.IsPtr() { if rsym != nil { base.Fatalf("declared pointer receiver type: %v", recv) } - rsym = recv.Elem().Sym + rsym = recv.Elem().Sym() } // Find the package the receiver type appeared in. For @@ -777,11 +777,11 @@ func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bo } mt := methtype(rf.Type) - if mt == nil || mt.Sym == nil { + if mt == nil || mt.Sym() == nil { pa := rf.Type t := pa if t != nil && t.IsPtr() { - if t.Sym != nil { + if t.Sym() != nil { base.Errorf("invalid receiver type %v (%v is a pointer type)", pa, t) return nil } @@ -791,7 +791,7 @@ func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bo switch { case t == nil || t.Broke(): // rely on typecheck having complained before - case t.Sym == nil: + case t.Sym() == nil: base.Errorf("invalid receiver type %v (%v is not a defined type)", pa, t) case t.IsPtr(): base.Errorf("invalid receiver type %v (%v is a pointer type)", pa, t) @@ -805,7 +805,7 @@ func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bo return nil } - if local && mt.Sym.Pkg != ir.LocalPkg { + if local && mt.Sym().Pkg != ir.LocalPkg { base.Errorf("cannot define new methods on non-local type %v", mt) return nil } diff --git a/src/cmd/compile/internal/gc/embed.go b/src/cmd/compile/internal/gc/embed.go index d9bfd6f5ed..d6e42e4f03 100644 --- a/src/cmd/compile/internal/gc/embed.go +++ b/src/cmd/compile/internal/gc/embed.go @@ -151,13 +151,13 @@ func embedKindApprox(typ ir.Node) int { // embedKind determines the kind of embedding variable. func embedKind(typ *types.Type) int { - if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) { + if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) { return embedFiles } if typ == types.Types[types.TSTRING] { return embedString } - if typ.Sym == nil && typ.IsSlice() && typ.Elem() == types.Bytetype { + if typ.Sym() == nil && typ.IsSlice() && typ.Elem() == types.ByteType { return embedBytes } return embedUnknown diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index f2fff02959..b29896e5a4 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -659,7 +659,7 @@ func (e *Escape) exprSkipInit(k EscHole, n ir.Node) { // unsafeValue evaluates a uintptr-typed arithmetic expression looking // for conversions from an unsafe.Pointer. func (e *Escape) unsafeValue(k EscHole, n ir.Node) { - if n.Type().Etype != types.TUINTPTR { + if n.Type().Kind() != types.TUINTPTR { base.Fatalf("unexpected type %v for %v", n.Type(), n) } diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index 24393de53d..c493165c76 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -102,7 +102,7 @@ var gopkg *types.Pkg // pseudo-package for method symbols on anonymous receiver var zerosize int64 -var simtype [types.NTYPE]types.EType +var simtype [types.NTYPE]types.Kind var ( isInt [types.NTYPE]bool diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 2dfce26596..8f50868fc7 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -473,15 +473,15 @@ func (p *iexporter) doDecl(n ir.Node) { w.tag('T') w.pos(n.Pos()) - underlying := n.Type().Orig - if underlying == types.Errortype.Orig { + underlying := n.Type().Underlying() + if underlying == types.ErrorType.Underlying() { // For "type T error", use error as the // underlying type instead of error's own // underlying anonymous interface. This // ensures consistency with how importers may // declare error (e.g., go/types uses nil Pkg // for predeclared objects). - underlying = types.Errortype + underlying = types.ErrorType } w.typ(underlying) @@ -634,8 +634,8 @@ func (w *exportWriter) startType(k itag) { } func (w *exportWriter) doTyp(t *types.Type) { - if t.Sym != nil { - if t.Sym.Pkg == ir.BuiltinPkg || t.Sym.Pkg == unsafepkg { + if t.Sym() != nil { + if t.Sym().Pkg == ir.BuiltinPkg || t.Sym().Pkg == unsafepkg { base.Fatalf("builtin type missing from typIndex: %v", t) } @@ -644,7 +644,7 @@ func (w *exportWriter) doTyp(t *types.Type) { return } - switch t.Etype { + switch t.Kind() { case types.TPTR: w.startType(pointerType) w.typ(t.Elem()) @@ -762,7 +762,7 @@ func constTypeOf(typ *types.Type) constant.Kind { return constant.Complex } - switch typ.Etype { + switch typ.Kind() { case types.TBOOL: return constant.Bool case types.TSTRING: @@ -809,7 +809,7 @@ func intSize(typ *types.Type) (signed bool, maxBytes uint) { return true, Mpprec / 8 } - switch typ.Etype { + switch typ.Kind() { case types.TFLOAT32, types.TCOMPLEX64: return true, 3 case types.TFLOAT64, types.TCOMPLEX128: @@ -821,7 +821,7 @@ func intSize(typ *types.Type) (signed bool, maxBytes uint) { // The go/types API doesn't expose sizes to importers, so they // don't know how big these types are. - switch typ.Etype { + switch typ.Kind() { case types.TINT, types.TUINT, types.TUINTPTR: maxBytes = 8 } diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 97ecb9559b..b36a01e389 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -61,10 +61,10 @@ func fnpkg(fn *ir.Name) *types.Pkg { if rcvr.IsPtr() { rcvr = rcvr.Elem() } - if rcvr.Sym == nil { + if rcvr.Sym() == nil { base.Fatalf("receiver with no sym: [%v] %L (%v)", fn.Sym(), fn, rcvr) } - return rcvr.Sym.Pkg + return rcvr.Sym().Pkg } // non-method diff --git a/src/cmd/compile/internal/gc/mkbuiltin.go b/src/cmd/compile/internal/gc/mkbuiltin.go index 5317484de9..38aa601645 100644 --- a/src/cmd/compile/internal/gc/mkbuiltin.go +++ b/src/cmd/compile/internal/gc/mkbuiltin.go @@ -143,9 +143,9 @@ func (i *typeInterner) mktype(t ast.Expr) string { case *ast.Ident: switch t.Name { case "byte": - return "types.Bytetype" + return "types.ByteType" case "rune": - return "types.Runetype" + return "types.RuneType" } return fmt.Sprintf("types.Types[types.T%s]", strings.ToUpper(t.Name)) case *ast.SelectorExpr: diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 7b5e3015c2..f65131417a 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -218,7 +218,7 @@ func addptabs() { if s.Pkg.Name != "main" { continue } - if n.Type().Etype == types.TFUNC && n.Class() == ir.PFUNC { + if n.Type().Kind() == types.TFUNC && n.Class() == ir.PFUNC { // function ptabs = append(ptabs, ptabEntry{s: s, t: ir.AsNode(s.Def).Type()}) } else { @@ -602,7 +602,7 @@ func litsym(n, c ir.Node, wid int) { case constant.Float: f, _ := constant.Float64Val(u) - switch n.Type().Etype { + switch n.Type().Kind() { case types.TFLOAT32: s.WriteFloat32(base.Ctxt, n.Offset(), float32(f)) case types.TFLOAT64: @@ -612,7 +612,7 @@ func litsym(n, c ir.Node, wid int) { case constant.Complex: re, _ := constant.Float64Val(constant.Real(u)) im, _ := constant.Float64Val(constant.Imag(u)) - switch n.Type().Etype { + switch n.Type().Kind() { case types.TCOMPLEX64: s.WriteFloat32(base.Ctxt, n.Offset(), float32(re)) s.WriteFloat32(base.Ctxt, n.Offset()+4, float32(im)) diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 83cfb44474..c2e236537f 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -784,7 +784,7 @@ func (o *Order) stmt(n ir.Node) { n.SetRight(o.expr(n.Right(), nil)) orderBody := true - switch n.Type().Etype { + switch n.Type().Kind() { default: base.Fatalf("order.stmt range %v", n.Type()) diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index 6ad3140081..f2555cc941 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -416,7 +416,7 @@ func onebitwalktype1(t *types.Type, off int64, bv bvec) { return } - switch t.Etype { + switch t.Kind() { case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP: if off&int64(Widthptr-1) != 0 { base.Fatalf("onebitwalktype1: invalid alignment, %v", t) @@ -1300,7 +1300,7 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap { // to fully initialize t. func isfat(t *types.Type) bool { if t != nil { - switch t.Etype { + switch t.Kind() { case types.TSLICE, types.TSTRING, types.TINTER: // maybe remove later return true diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go index 2f2d7051c3..e48642a854 100644 --- a/src/cmd/compile/internal/gc/range.go +++ b/src/cmd/compile/internal/gc/range.go @@ -61,7 +61,7 @@ func typecheckrangeExpr(n ir.Node) { var t1, t2 *types.Type toomany := false - switch t.Etype { + switch t.Kind() { default: base.ErrorfAt(n.Pos(), "cannot range over %L", n.Right()) return @@ -88,7 +88,7 @@ func typecheckrangeExpr(n ir.Node) { case types.TSTRING: t1 = types.Types[types.TINT] - t2 = types.Runetype + t2 = types.RuneType } if n.List().Len() > 2 || toomany { @@ -208,7 +208,7 @@ func walkrange(nrange ir.Node) ir.Node { var body []ir.Node var init []ir.Node - switch t.Etype { + switch t.Kind() { default: base.Fatalf("walkrange") @@ -375,7 +375,7 @@ func walkrange(nrange ir.Node) ir.Node { hv1 := temp(types.Types[types.TINT]) hv1t := temp(types.Types[types.TINT]) - hv2 := temp(types.Runetype) + hv2 := temp(types.RuneType) // hv1 := 0 init = append(init, ir.Nod(ir.OAS, hv1, nil)) @@ -391,7 +391,7 @@ func walkrange(nrange ir.Node) ir.Node { // hv2 := rune(ha[hv1]) nind := ir.Nod(ir.OINDEX, ha, hv1) nind.SetBounded(true) - body = append(body, ir.Nod(ir.OAS, hv2, conv(nind, types.Runetype))) + body = append(body, ir.Nod(ir.OAS, hv2, conv(nind, types.RuneType))) // if hv2 < utf8.RuneSelf nif := ir.Nod(ir.OIF, nil, nil) @@ -467,7 +467,7 @@ func isMapClear(n ir.Node) bool { return false } - if n.Op() != ir.ORANGE || n.Type().Etype != types.TMAP || n.List().Len() != 1 { + if n.Op() != ir.ORANGE || n.Type().Kind() != types.TMAP || n.List().Len() != 1 { return false } diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 73d369f413..4ab3005ce8 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -68,7 +68,7 @@ func imethodSize() int { return 4 + 4 } // Sizeof(runtime.imeth func commonSize() int { return 4*Widthptr + 8 + 8 } // Sizeof(runtime._type{}) func uncommonSize(t *types.Type) int { // Sizeof(runtime.uncommontype{}) - if t.Sym == nil && len(methods(t)) == 0 { + if t.Sym() == nil && len(methods(t)) == 0 { return 0 } return 4 + 2 + 2 + 4 + 4 @@ -448,7 +448,7 @@ func methods(t *types.Type) []*Sig { func imethods(t *types.Type) []*Sig { var methods []*Sig for _, f := range t.Fields().Slice() { - if f.Type.Etype != types.TFUNC || f.Sym == nil { + if f.Type.Kind() != types.TFUNC || f.Sym == nil { continue } if f.Sym.IsBlank() { @@ -640,7 +640,7 @@ func dname(name, tag string, pkg *types.Pkg, exported bool) *obj.LSym { // backing array of the []method field is written (by dextratypeData). func dextratype(lsym *obj.LSym, ot int, t *types.Type, dataAdd int) int { m := methods(t) - if t.Sym == nil && len(m) == 0 { + if t.Sym() == nil && len(m) == 0 { return ot } noff := int(Rnd(int64(ot), int64(Widthptr))) @@ -672,16 +672,16 @@ func dextratype(lsym *obj.LSym, ot int, t *types.Type, dataAdd int) int { } func typePkg(t *types.Type) *types.Pkg { - tsym := t.Sym + tsym := t.Sym() if tsym == nil { - switch t.Etype { + switch t.Kind() { case types.TARRAY, types.TSLICE, types.TPTR, types.TCHAN: if t.Elem() != nil { - tsym = t.Elem().Sym + tsym = t.Elem().Sym() } } } - if tsym != nil && t != types.Types[t.Etype] && t != types.Errortype { + if tsym != nil && t != types.Types[t.Kind()] && t != types.ErrorType { return tsym.Pkg } return nil @@ -753,7 +753,7 @@ func typeptrdata(t *types.Type) int64 { return 0 } - switch t.Etype { + switch t.Kind() { case types.TPTR, types.TUNSAFEPTR, types.TFUNC, @@ -823,7 +823,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { var sptr *obj.LSym if !t.IsPtr() || t.IsPtrElem() { tptr := types.NewPtr(t) - if t.Sym != nil || methods(tptr) != nil { + if t.Sym() != nil || methods(tptr) != nil { sptrWeak = false } sptr = dtypesym(tptr) @@ -855,7 +855,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { if uncommonSize(t) != 0 { tflag |= tflagUncommon } - if t.Sym != nil && t.Sym.Name != "" { + if t.Sym() != nil && t.Sym().Name != "" { tflag |= tflagNamed } if IsRegularMemory(t) { @@ -872,12 +872,12 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { if !strings.HasPrefix(p, "*") { p = "*" + p tflag |= tflagExtraStar - if t.Sym != nil { - exported = types.IsExported(t.Sym.Name) + if t.Sym() != nil { + exported = types.IsExported(t.Sym().Name) } } else { - if t.Elem() != nil && t.Elem().Sym != nil { - exported = types.IsExported(t.Elem().Sym.Name) + if t.Elem() != nil && t.Elem().Sym() != nil { + exported = types.IsExported(t.Elem().Sym().Name) } } @@ -895,7 +895,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { ot = duint8(lsym, ot, t.Align) // align ot = duint8(lsym, ot, t.Align) // fieldAlign - i = kinds[t.Etype] + i = kinds[t.Kind()] if isdirectiface(t) { i |= objabi.KindDirectIface } @@ -1029,7 +1029,7 @@ func itabname(t, itype *types.Type) ir.Node { // isreflexive reports whether t has a reflexive equality operator. // That is, if x==x for all x of type t. func isreflexive(t *types.Type) bool { - switch t.Etype { + switch t.Kind() { case types.TBOOL, types.TINT, types.TUINT, @@ -1075,7 +1075,7 @@ func isreflexive(t *types.Type) bool { // needkeyupdate reports whether map updates with t as a key // need the key to be updated. func needkeyupdate(t *types.Type) bool { - switch t.Etype { + switch t.Kind() { case types.TBOOL, types.TINT, types.TUINT, types.TINT8, types.TUINT8, types.TINT16, types.TUINT16, types.TINT32, types.TUINT32, types.TINT64, types.TUINT64, types.TUINTPTR, types.TPTR, types.TUNSAFEPTR, types.TCHAN: return false @@ -1104,7 +1104,7 @@ func needkeyupdate(t *types.Type) bool { // hashMightPanic reports whether the hash of a map key of type t might panic. func hashMightPanic(t *types.Type) bool { - switch t.Etype { + switch t.Kind() { case types.TINTER: return true @@ -1128,8 +1128,8 @@ func hashMightPanic(t *types.Type) bool { // They've been separate internally to make error messages // better, but we have to merge them in the reflect tables. func formalType(t *types.Type) *types.Type { - if t == types.Bytetype || t == types.Runetype { - return types.Types[t.Etype] + if t == types.ByteType || t == types.RuneType { + return types.Types[t.Kind()] } return t } @@ -1152,19 +1152,19 @@ func dtypesym(t *types.Type) *obj.LSym { // emit the type structures for int, float, etc. tbase := t - if t.IsPtr() && t.Sym == nil && t.Elem().Sym != nil { + if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil { tbase = t.Elem() } dupok := 0 - if tbase.Sym == nil { + if tbase.Sym() == nil { dupok = obj.DUPOK } - if base.Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Etype] && tbase != types.Bytetype && tbase != types.Runetype && tbase != types.Errortype) { // int, float, etc + if base.Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Kind()] && tbase != types.ByteType && tbase != types.RuneType && tbase != types.ErrorType) { // int, float, etc // named types from other files are defined only by those files - if tbase.Sym != nil && tbase.Sym.Pkg != ir.LocalPkg { + if tbase.Sym() != nil && tbase.Sym().Pkg != ir.LocalPkg { if i, ok := typeSymIdx[tbase]; ok { - lsym.Pkg = tbase.Sym.Pkg.Prefix + lsym.Pkg = tbase.Sym().Pkg.Prefix if t != tbase { lsym.SymIdx = int32(i[1]) } else { @@ -1175,13 +1175,13 @@ func dtypesym(t *types.Type) *obj.LSym { return lsym } // TODO(mdempsky): Investigate whether this can happen. - if tbase.Etype == types.TFORW { + if tbase.Kind() == types.TFORW { return lsym } } ot := 0 - switch t.Etype { + switch t.Kind() { default: ot = dcommontype(lsym, t) ot = dextratype(lsym, ot, t, 0) @@ -1262,8 +1262,8 @@ func dtypesym(t *types.Type) *obj.LSym { ot = dcommontype(lsym, t) var tpkg *types.Pkg - if t.Sym != nil && t != types.Types[t.Etype] && t != types.Errortype { - tpkg = t.Sym.Pkg + if t.Sym() != nil && t != types.Types[t.Kind()] && t != types.ErrorType { + tpkg = t.Sym().Pkg } ot = dgopkgpath(lsym, ot, tpkg) @@ -1328,7 +1328,7 @@ func dtypesym(t *types.Type) *obj.LSym { ot = dextratype(lsym, ot, t, 0) case types.TPTR: - if t.Elem().Etype == types.TANY { + if t.Elem().Kind() == types.TANY { // ../../../../runtime/type.go:/UnsafePointerType ot = dcommontype(lsym, t) ot = dextratype(lsym, ot, t, 0) @@ -1397,13 +1397,13 @@ func dtypesym(t *types.Type) *obj.LSym { // When buildmode=shared, all types are in typelinks so the // runtime can deduplicate type pointers. keep := base.Ctxt.Flag_dynlink - if !keep && t.Sym == nil { + if !keep && t.Sym() == nil { // For an unnamed type, we only need the link if the type can // be created at run time by reflect.PtrTo and similar // functions. If the type exists in the program, those // functions must return the existing type structure rather // than creating a new one. - switch t.Etype { + switch t.Kind() { case types.TPTR, types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRUCT: keep = true } @@ -1541,7 +1541,7 @@ func dumpsignats() { for _, ts := range signats { t := ts.t dtypesym(t) - if t.Sym != nil { + if t.Sym() != nil { dtypesym(types.NewPtr(t)) } } @@ -1616,7 +1616,7 @@ func dumpbasictypes() { // another possible choice would be package main, // but using runtime means fewer copies in object files. if base.Ctxt.Pkgpath == "runtime" { - for i := types.EType(1); i <= types.TBOOL; i++ { + for i := types.Kind(1); i <= types.TBOOL; i++ { dtypesym(types.NewPtr(types.Types[i])) } dtypesym(types.NewPtr(types.Types[types.TSTRING])) @@ -1624,9 +1624,9 @@ func dumpbasictypes() { // emit type structs for error and func(error) string. // The latter is the type of an auto-generated wrapper. - dtypesym(types.NewPtr(types.Errortype)) + dtypesym(types.NewPtr(types.ErrorType)) - dtypesym(functype(nil, []*ir.Field{anonfield(types.Errortype)}, []*ir.Field{anonfield(types.Types[types.TSTRING])})) + dtypesym(functype(nil, []*ir.Field{anonfield(types.ErrorType)}, []*ir.Field{anonfield(types.Types[types.TSTRING])})) // add paths for runtime and main, which 6l imports implicitly. dimportpath(Runtimepkg) @@ -1665,7 +1665,7 @@ func (a typesByString) Less(i, j int) bool { // will be equal for the above checks, but different in DWARF output. // Sort by source position to ensure deterministic order. // See issues 27013 and 30202. - if a[i].t.Etype == types.TINTER && a[i].t.Methods().Len() > 0 { + if a[i].t.Kind() == types.TINTER && a[i].t.Methods().Len() > 0 { return a[i].t.Methods().Index(0).Pos.Before(a[j].t.Methods().Index(0).Pos) } return false @@ -1821,7 +1821,7 @@ func (p *GCProg) emit(t *types.Type, offset int64) { p.w.Ptr(offset / int64(Widthptr)) return } - switch t.Etype { + switch t.Kind() { default: base.Fatalf("GCProg.emit: unexpected type %v", t) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 4be6caa0e3..3e020d7b92 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -54,13 +54,13 @@ func initssaconfig() { _ = types.NewPtr(types.Types[types.TINTER]) // *interface{} _ = types.NewPtr(types.NewPtr(types.Types[types.TSTRING])) // **string _ = types.NewPtr(types.NewSlice(types.Types[types.TINTER])) // *[]interface{} - _ = types.NewPtr(types.NewPtr(types.Bytetype)) // **byte - _ = types.NewPtr(types.NewSlice(types.Bytetype)) // *[]byte + _ = types.NewPtr(types.NewPtr(types.ByteType)) // **byte + _ = types.NewPtr(types.NewSlice(types.ByteType)) // *[]byte _ = types.NewPtr(types.NewSlice(types.Types[types.TSTRING])) // *[]string _ = types.NewPtr(types.NewPtr(types.NewPtr(types.Types[types.TUINT8]))) // ***uint8 _ = types.NewPtr(types.Types[types.TINT16]) // *int16 _ = types.NewPtr(types.Types[types.TINT64]) // *int64 - _ = types.NewPtr(types.Errortype) // *error + _ = types.NewPtr(types.ErrorType) // *error types.NewPtrCacheEnabled = false ssaConfig = ssa.NewConfig(thearch.LinkArch.Name, *types_, base.Ctxt, base.Flag.N == 0) ssaConfig.SoftFloat = thearch.SoftFloat @@ -1591,7 +1591,7 @@ func (s *state) exit() *ssa.Block { type opAndType struct { op ir.Op - etype types.EType + etype types.Kind } var opToSSA = map[opAndType]ssa.Op{ @@ -1766,8 +1766,8 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{ir.OLE, types.TFLOAT32}: ssa.OpLeq32F, } -func (s *state) concreteEtype(t *types.Type) types.EType { - e := t.Etype +func (s *state) concreteEtype(t *types.Type) types.Kind { + e := t.Kind() switch e { default: return e @@ -1799,7 +1799,7 @@ func (s *state) ssaOp(op ir.Op, t *types.Type) ssa.Op { } func floatForComplex(t *types.Type) *types.Type { - switch t.Etype { + switch t.Kind() { case types.TCOMPLEX64: return types.Types[types.TFLOAT32] case types.TCOMPLEX128: @@ -1810,7 +1810,7 @@ func floatForComplex(t *types.Type) *types.Type { } func complexForFloat(t *types.Type) *types.Type { - switch t.Etype { + switch t.Kind() { case types.TFLOAT32: return types.Types[types.TCOMPLEX64] case types.TFLOAT64: @@ -1822,19 +1822,19 @@ func complexForFloat(t *types.Type) *types.Type { type opAndTwoTypes struct { op ir.Op - etype1 types.EType - etype2 types.EType + etype1 types.Kind + etype2 types.Kind } type twoTypes struct { - etype1 types.EType - etype2 types.EType + etype1 types.Kind + etype2 types.Kind } type twoOpsAndType struct { op1 ssa.Op op2 ssa.Op - intermediateType types.EType + intermediateType types.Kind } var fpConvOpToSSA = map[twoTypes]twoOpsAndType{ @@ -2115,12 +2115,12 @@ func (s *state) expr(n ir.Node) *ssa.Value { v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type // CONVNOP closure - if to.Etype == types.TFUNC && from.IsPtrShaped() { + if to.Kind() == types.TFUNC && from.IsPtrShaped() { return v } // named <--> unnamed type or typed <--> untyped const - if from.Etype == to.Etype { + if from.Kind() == to.Kind() { return v } @@ -2130,7 +2130,7 @@ func (s *state) expr(n ir.Node) *ssa.Value { } // map <--> *hmap - if to.Etype == types.TMAP && from.IsPtr() && + if to.Kind() == types.TMAP && from.IsPtr() && to.MapType().Hmap == from.Elem() { return v } @@ -2141,8 +2141,8 @@ func (s *state) expr(n ir.Node) *ssa.Value { s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width) return nil } - if etypesign(from.Etype) != etypesign(to.Etype) { - s.Fatalf("CONVNOP sign mismatch %v (%s) -> %v (%s)\n", from, from.Etype, to, to.Etype) + if etypesign(from.Kind()) != etypesign(to.Kind()) { + s.Fatalf("CONVNOP sign mismatch %v (%s) -> %v (%s)\n", from, from.Kind(), to, to.Kind()) return nil } @@ -2153,7 +2153,7 @@ func (s *state) expr(n ir.Node) *ssa.Value { return v } - if etypesign(from.Etype) == 0 { + if etypesign(from.Kind()) == 0 { s.Fatalf("CONVNOP unrecognized non-integer %v -> %v\n", from, to) return nil } @@ -2329,7 +2329,7 @@ func (s *state) expr(n ir.Node) *ssa.Value { s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, x))) } - s.Fatalf("unhandled OCONV %s -> %s", n.Left().Type().Etype, n.Type().Etype) + s.Fatalf("unhandled OCONV %s -> %s", n.Left().Type().Kind(), n.Type().Kind()) return nil case ir.ODOTTYPE: @@ -3172,7 +3172,7 @@ const ( type sfRtCallDef struct { rtfn *obj.LSym - rtype types.EType + rtype types.Kind } var softFloatOps map[ssa.Op]sfRtCallDef @@ -3467,9 +3467,9 @@ func init() { }, sys.AMD64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) - type atomicOpEmitter func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) + type atomicOpEmitter func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.Kind) - makeAtomicGuardedIntrinsicARM64 := func(op0, op1 ssa.Op, typ, rtyp types.EType, emit atomicOpEmitter) intrinsicBuilder { + makeAtomicGuardedIntrinsicARM64 := func(op0, op1 ssa.Op, typ, rtyp types.Kind, emit atomicOpEmitter) intrinsicBuilder { return func(s *state, n ir.Node, args []*ssa.Value) *ssa.Value { // Target Atomic feature is identified by dynamic detection @@ -3505,7 +3505,7 @@ func init() { } } - atomicXchgXaddEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) { + atomicXchgXaddEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.Kind) { v := s.newValue3(op, types.NewTuple(types.Types[typ], types.TypeMem), args[0], args[1], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v) @@ -3561,7 +3561,7 @@ func init() { }, sys.PPC64) - atomicCasEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) { + atomicCasEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.Kind) { v := s.newValue4(op, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v) @@ -3599,7 +3599,7 @@ func init() { }, sys.AMD64, sys.MIPS, sys.PPC64, sys.S390X) - atomicAndOrEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) { + atomicAndOrEmitterARM64 := func(s *state, n ir.Node, args []*ssa.Value, op ssa.Op, typ types.Kind) { s.vars[memVar] = s.newValue3(op, types.TypeMem, args[0], args[1], s.mem()) } @@ -4810,7 +4810,7 @@ func (s *state) getClosureAndRcvr(fn ir.Node) (*ssa.Value, *ssa.Value) { // etypesign returns the signed-ness of e, for integer/pointer etypes. // -1 means signed, +1 means unsigned, 0 means non-integer/non-pointer. -func etypesign(e types.EType) int8 { +func etypesign(e types.Kind) int8 { switch e { case types.TINT8, types.TINT16, types.TINT32, types.TINT64, types.TINT: return -1 @@ -4980,7 +4980,7 @@ func canSSAType(t *types.Type) bool { // Too big and we'll introduce too much register pressure. return false } - switch t.Etype { + switch t.Kind() { case types.TARRAY: // We can't do larger arrays because dynamic indexing is // not supported on SSA variables. diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 04c8c537bd..011a7ac5bc 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -181,7 +181,7 @@ func nodstr(s string) ir.Node { return ir.NewLiteral(constant.MakeString(s)) } -func isptrto(t *types.Type, et types.EType) bool { +func isptrto(t *types.Type, et types.Kind) bool { if t == nil { return false } @@ -192,7 +192,7 @@ func isptrto(t *types.Type, et types.EType) bool { if t == nil { return false } - if t.Etype != et { + if t.Kind() != et { return false } return true @@ -208,7 +208,7 @@ func methtype(t *types.Type) *types.Type { // Strip away pointer if it's there. if t.IsPtr() { - if t.Sym != nil { + if t.Sym() != nil { return nil } t = t.Elem() @@ -218,15 +218,15 @@ func methtype(t *types.Type) *types.Type { } // Must be a named type or anonymous struct. - if t.Sym == nil && !t.IsStruct() { + if t.Sym() == nil && !t.IsStruct() { return nil } // Check types. - if issimple[t.Etype] { + if issimple[t.Kind()] { return t } - switch t.Etype { + switch t.Kind() { case types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRING, types.TSTRUCT: return t } @@ -241,7 +241,7 @@ func assignop(src, dst *types.Type) (ir.Op, string) { if src == dst { return ir.OCONVNOP, "" } - if src == nil || dst == nil || src.Etype == types.TFORW || dst.Etype == types.TFORW || src.Orig == nil || dst.Orig == nil { + if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil { return ir.OXXX, "" } @@ -257,13 +257,13 @@ func assignop(src, dst *types.Type) (ir.Op, string) { // we want to recompute the itab. Recomputing the itab ensures // that itabs are unique (thus an interface with a compile-time // type I has an itab with interface type I). - if types.Identical(src.Orig, dst.Orig) { + if types.Identical(src.Underlying(), dst.Underlying()) { if src.IsEmptyInterface() { // Conversion between two empty interfaces // requires no code. return ir.OCONVNOP, "" } - if (src.Sym == nil || dst.Sym == nil) && !src.IsInterface() { + if (src.Sym() == nil || dst.Sym() == nil) && !src.IsInterface() { // Conversion between two types, at least one unnamed, // needs no conversion. The exception is nonempty interfaces // which need to have their itab updated. @@ -272,7 +272,7 @@ func assignop(src, dst *types.Type) (ir.Op, string) { } // 3. dst is an interface type and src implements dst. - if dst.IsInterface() && src.Etype != types.TNIL { + if dst.IsInterface() && src.Kind() != types.TNIL { var missing, have *types.Field var ptr int if implements(src, dst, &missing, &have, &ptr) { @@ -309,7 +309,7 @@ func assignop(src, dst *types.Type) (ir.Op, string) { return ir.OXXX, why } - if src.IsInterface() && dst.Etype != types.TBLANK { + if src.IsInterface() && dst.Kind() != types.TBLANK { var missing, have *types.Field var ptr int var why string @@ -323,14 +323,14 @@ func assignop(src, dst *types.Type) (ir.Op, string) { // src and dst have identical element types, and // either src or dst is not a named type. if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() { - if types.Identical(src.Elem(), dst.Elem()) && (src.Sym == nil || dst.Sym == nil) { + if types.Identical(src.Elem(), dst.Elem()) && (src.Sym() == nil || dst.Sym() == nil) { return ir.OCONVNOP, "" } } // 5. src is the predeclared identifier nil and dst is a nillable type. - if src.Etype == types.TNIL { - switch dst.Etype { + if src.Kind() == types.TNIL { + switch dst.Kind() { case types.TPTR, types.TFUNC, types.TMAP, @@ -344,7 +344,7 @@ func assignop(src, dst *types.Type) (ir.Op, string) { // 6. rule about untyped constants - already converted by defaultlit. // 7. Any typed value can be assigned to the blank identifier. - if dst.Etype == types.TBLANK { + if dst.Kind() == types.TBLANK { return ir.OCONVNOP, "" } @@ -373,7 +373,7 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) { return ir.OXXX, why } // (b) Disallow string to []T where T is go:notinheap. - if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Etype == types.Bytetype.Etype || dst.Elem().Etype == types.Runetype.Etype) { + if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Kind() == types.ByteType.Kind() || dst.Elem().Kind() == types.RuneType.Kind()) { why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem()) return ir.OXXX, why } @@ -393,21 +393,21 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) { } // 2. Ignoring struct tags, src and dst have identical underlying types. - if types.IdenticalIgnoreTags(src.Orig, dst.Orig) { + if types.IdenticalIgnoreTags(src.Underlying(), dst.Underlying()) { return ir.OCONVNOP, "" } // 3. src and dst are unnamed pointer types and, ignoring struct tags, // their base types have identical underlying types. - if src.IsPtr() && dst.IsPtr() && src.Sym == nil && dst.Sym == nil { - if types.IdenticalIgnoreTags(src.Elem().Orig, dst.Elem().Orig) { + if src.IsPtr() && dst.IsPtr() && src.Sym() == nil && dst.Sym() == nil { + if types.IdenticalIgnoreTags(src.Elem().Underlying(), dst.Elem().Underlying()) { return ir.OCONVNOP, "" } } // 4. src and dst are both integer or floating point types. if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) { - if simtype[src.Etype] == simtype[dst.Etype] { + if simtype[src.Kind()] == simtype[dst.Kind()] { return ir.OCONVNOP, "" } return ir.OCONV, "" @@ -415,7 +415,7 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) { // 5. src and dst are both complex types. if src.IsComplex() && dst.IsComplex() { - if simtype[src.Etype] == simtype[dst.Etype] { + if simtype[src.Kind()] == simtype[dst.Kind()] { return ir.OCONVNOP, "" } return ir.OCONV, "" @@ -435,10 +435,10 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) { } if src.IsSlice() && dst.IsString() { - if src.Elem().Etype == types.Bytetype.Etype { + if src.Elem().Kind() == types.ByteType.Kind() { return ir.OBYTES2STR, "" } - if src.Elem().Etype == types.Runetype.Etype { + if src.Elem().Kind() == types.RuneType.Kind() { return ir.ORUNES2STR, "" } } @@ -446,10 +446,10 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) { // 7. src is a string and dst is []byte or []rune. // String to slice. if src.IsString() && dst.IsSlice() { - if dst.Elem().Etype == types.Bytetype.Etype { + if dst.Elem().Kind() == types.ByteType.Kind() { return ir.OSTR2BYTES, "" } - if dst.Elem().Etype == types.Runetype.Etype { + if dst.Elem().Kind() == types.RuneType.Kind() { return ir.OSTR2RUNES, "" } } @@ -467,7 +467,7 @@ func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) { // src is map and dst is a pointer to corresponding hmap. // This rule is needed for the implementation detail that // go gc maps are implemented as a pointer to a hmap struct. - if src.Etype == types.TMAP && dst.IsPtr() && + if src.Kind() == types.TMAP && dst.IsPtr() && src.MapType().Hmap == dst.Elem() { return ir.OCONVNOP, "" } @@ -485,7 +485,7 @@ func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node { return n } - if t.Etype == types.TBLANK && n.Type().Etype == types.TNIL { + if t.Kind() == types.TBLANK && n.Type().Kind() == types.TNIL { base.Errorf("use of untyped nil") } @@ -493,7 +493,7 @@ func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node { if n.Type() == nil { return n } - if t.Etype == types.TBLANK { + if t.Kind() == types.TBLANK { return n } @@ -600,15 +600,15 @@ func calcHasCall(n ir.Node) bool { // When using soft-float, these ops might be rewritten to function calls // so we ensure they are evaluated first. case ir.OADD, ir.OSUB, ir.ONEG, ir.OMUL: - if thearch.SoftFloat && (isFloat[n.Type().Etype] || isComplex[n.Type().Etype]) { + if thearch.SoftFloat && (isFloat[n.Type().Kind()] || isComplex[n.Type().Kind()]) { return true } case ir.OLT, ir.OEQ, ir.ONE, ir.OLE, ir.OGE, ir.OGT: - if thearch.SoftFloat && (isFloat[n.Left().Type().Etype] || isComplex[n.Left().Type().Etype]) { + if thearch.SoftFloat && (isFloat[n.Left().Type().Kind()] || isComplex[n.Left().Type().Kind()]) { return true } case ir.OCONV: - if thearch.SoftFloat && ((isFloat[n.Type().Etype] || isComplex[n.Type().Etype]) || (isFloat[n.Left().Type().Etype] || isComplex[n.Left().Type().Etype])) { + if thearch.SoftFloat && ((isFloat[n.Type().Kind()] || isComplex[n.Type().Kind()]) || (isFloat[n.Left().Type().Kind()] || isComplex[n.Left().Type().Kind()])) { return true } } @@ -802,7 +802,7 @@ func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) } u = t - if t.Sym != nil && t.IsPtr() && !t.Elem().IsPtr() { + if t.Sym() != nil && t.IsPtr() && !t.Elem().IsPtr() { // If t is a defined pointer type, then x.m is shorthand for (*x).m. u = t.Elem() } @@ -1110,13 +1110,13 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { // Only generate (*T).M wrappers for T.M in T's own package. if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && - rcvr.Elem().Sym != nil && rcvr.Elem().Sym.Pkg != ir.LocalPkg { + rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != ir.LocalPkg { return } // Only generate I.M wrappers for I in I's own package // but keep doing it for error.Error (was issue #29304). - if rcvr.IsInterface() && rcvr.Sym != nil && rcvr.Sym.Pkg != ir.LocalPkg && rcvr != types.Errortype { + if rcvr.IsInterface() && rcvr.Sym() != nil && rcvr.Sym().Pkg != ir.LocalPkg && rcvr != types.ErrorType { return } @@ -1193,7 +1193,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { // Inline calls within (*T).M wrappers. This is safe because we only // generate those wrappers within the same compilation unit as (T).M. // TODO(mdempsky): Investigate why we can't enable this more generally. - if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym != nil { + if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym() != nil { inlcalls(fn) } escapeFuncs([]*ir.Func{fn}, false) @@ -1433,7 +1433,7 @@ func isdirectiface(t *types.Type) bool { return false } - switch t.Etype { + switch t.Kind() { case types.TPTR: // Pointers to notinheap types must be stored indirectly. See issue 42076. return !t.Elem().NotInHeap() diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go index 02d38ac4b1..30179e1dd6 100644 --- a/src/cmd/compile/internal/gc/swt.go +++ b/src/cmd/compile/internal/gc/swt.go @@ -157,7 +157,7 @@ func typecheckExprSwitch(n ir.Node) { switch { case t.IsMap(): nilonly = "map" - case t.Etype == types.TFUNC: + case t.Kind() == types.TFUNC: nilonly = "func" case t.IsSlice(): nilonly = "slice" @@ -332,7 +332,7 @@ type exprClause struct { func (s *exprSwitch) Add(pos src.XPos, expr, jmp ir.Node) { c := exprClause{pos: pos, lo: expr, hi: expr, jmp: jmp} - if okforcmp[s.exprname.Type().Etype] && expr.Op() == ir.OLITERAL { + if okforcmp[s.exprname.Type().Kind()] && expr.Op() == ir.OLITERAL { s.clauses = append(s.clauses, c) return } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index dccb5ecdce..f120b44413 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -156,7 +156,7 @@ func typekind(t *types.Type) string { if t.IsUntyped() { return fmt.Sprintf("%v", t) } - et := t.Etype + et := t.Kind() if int(et) < len(_typekind) { s := _typekind[et] if s != "" { @@ -329,7 +329,7 @@ func typecheck(n ir.Node, top int) (res ir.Node) { // The result of indexlit MUST be assigned back to n, e.g. // n.Left = indexlit(n.Left) func indexlit(n ir.Node) ir.Node { - if n != nil && n.Type() != nil && n.Type().Etype == types.TIDEAL { + if n != nil && n.Type() != nil && n.Type().Kind() == types.TIDEAL { return defaultlit(n, types.Types[types.TINT]) } return n @@ -583,7 +583,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } - if n.Implicit() && !okforarith[l.Type().Etype] { + if n.Implicit() && !okforarith[l.Type().Kind()] { base.Errorf("invalid operation: %v (non-numeric type %v)", n, l.Type()) n.SetType(nil) return n @@ -617,7 +617,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n } t = l.Type() - if t != nil && t.Etype != types.TIDEAL && !t.IsInteger() { + if t != nil && t.Kind() != types.TIDEAL && !t.IsInteger() { base.Errorf("invalid operation: %v (shift of type %v)", n, t) n.SetType(nil) return n @@ -659,15 +659,15 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n } t := l.Type() - if t.Etype == types.TIDEAL { + if t.Kind() == types.TIDEAL { t = r.Type() } - et := t.Etype + et := t.Kind() if et == types.TIDEAL { et = types.TINT } aop := ir.OXXX - if iscmp[n.Op()] && t.Etype != types.TIDEAL && !types.Identical(l.Type(), r.Type()) { + if iscmp[n.Op()] && t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) { // comparison is okay as long as one side is // assignable to the other. convert so they have // the same type. @@ -676,7 +676,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // in that case, check comparability of the concrete type. // The conversion allocates, so only do it if the concrete type is huge. converted := false - if r.Type().Etype != types.TBLANK { + if r.Type().Kind() != types.TBLANK { aop, _ = assignop(l.Type(), r.Type()) if aop != ir.OXXX { if r.Type().IsInterface() && !l.Type().IsInterface() && !IsComparable(l.Type()) { @@ -698,7 +698,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } } - if !converted && l.Type().Etype != types.TBLANK { + if !converted && l.Type().Kind() != types.TBLANK { aop, _ = assignop(r.Type(), l.Type()) if aop != ir.OXXX { if l.Type().IsInterface() && !r.Type().IsInterface() && !IsComparable(r.Type()) { @@ -719,10 +719,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } } - et = t.Etype + et = t.Kind() } - if t.Etype != types.TIDEAL && !types.Identical(l.Type(), r.Type()) { + if t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) { l, r = defaultlit2(l, r, true) if l.Type() == nil || r.Type() == nil { n.SetType(nil) @@ -735,10 +735,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } } - if t.Etype == types.TIDEAL { + if t.Kind() == types.TIDEAL { t = mixUntyped(l.Type(), r.Type()) } - if dt := defaultType(t); !okfor[op][dt.Etype] { + if dt := defaultType(t); !okfor[op][dt.Kind()] { base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(t)) n.SetType(nil) return n @@ -764,7 +764,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n } - if l.Type().Etype == types.TFUNC && !ir.IsNil(l) && !ir.IsNil(r) { + if l.Type().Kind() == types.TFUNC && !ir.IsNil(l) && !ir.IsNil(r) { base.Errorf("invalid operation: %v (func can only be compared to nil)", n) n.SetType(nil) return n @@ -825,7 +825,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } - if !okfor[n.Op()][defaultType(t).Etype] { + if !okfor[n.Op()][defaultType(t).Kind()] { base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, n.Op(), typekind(t)) n.SetType(nil) return n @@ -1023,7 +1023,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } - switch t.Etype { + switch t.Kind() { default: base.Errorf("invalid operation: %v (type %v does not support indexing)", n, t) n.SetType(nil) @@ -1032,7 +1032,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { case types.TSTRING, types.TARRAY, types.TSLICE: n.SetRight(indexlit(n.Right())) if t.IsString() { - n.SetType(types.Bytetype) + n.SetType(types.ByteType) } else { n.SetType(t.Elem()) } @@ -1191,7 +1191,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetLeft(defaultlit(n.Left(), types.Types[types.TINT])) - if !n.Left().Type().IsInteger() && n.Type().Etype != types.TIDEAL { + if !n.Left().Type().IsInteger() && n.Type().Kind() != types.TIDEAL { base.Errorf("non-integer len argument in OMAKESLICECOPY") } @@ -1383,7 +1383,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { default: n.SetOp(ir.OCALLFUNC) - if t.Etype != types.TFUNC { + if t.Kind() != types.TFUNC { name := l.String() if isBuiltinFuncName(name) && l.Name().Defn != nil { // be more specific when the function @@ -1446,9 +1446,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { var ok bool if n.Op() == ir.OLEN { - ok = okforlen[t.Etype] + ok = okforlen[t.Kind()] } else { - ok = okforcap[t.Etype] + ok = okforcap[t.Kind()] } if !ok { base.Errorf("invalid argument %L for %v", l, n.Op()) @@ -1469,7 +1469,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } // Determine result type. - switch t.Etype { + switch t.Kind() { case types.TIDEAL: n.SetType(types.UntypedFloat) case types.TCOMPLEX64: @@ -1505,7 +1505,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } var t *types.Type - switch l.Type().Etype { + switch l.Type().Kind() { default: base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type()) n.SetType(nil) @@ -1624,7 +1624,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { break } - args.SetSecond(assignconv(args.Second(), t.Orig, "append")) + args.SetSecond(assignconv(args.Second(), t.Underlying(), "append")) break } @@ -1651,7 +1651,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // copy([]byte, string) if n.Left().Type().IsSlice() && n.Right().Type().IsString() { - if types.Identical(n.Left().Type().Elem(), types.Bytetype) { + if types.Identical(n.Left().Type().Elem(), types.ByteType) { break } base.Errorf("arguments to copy have different element types: %L and string", n.Left().Type()) @@ -1701,8 +1701,8 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetOp(op) switch n.Op() { case ir.OCONVNOP: - if t.Etype == n.Type().Etype { - switch t.Etype { + if t.Kind() == n.Type().Kind() { + switch t.Kind() { case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128: // Floating point casts imply rounding and // so the conversion must be kept. @@ -1741,7 +1741,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { i := 1 var nn ir.Node - switch t.Etype { + switch t.Kind() { default: base.Errorf("cannot make type %v", t) n.SetType(nil) @@ -2062,7 +2062,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { t := n.Type() if t != nil && !t.IsFuncArgStruct() && n.Op() != ir.OTYPE { - switch t.Etype { + switch t.Kind() { case types.TFUNC, // might have TANY; wait until it's called types.TANY, types.TFORW, types.TIDEAL, types.TNIL, types.TBLANK: break @@ -2352,7 +2352,7 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) { // types declared at package scope. However, we need // to make sure to generate wrappers for anonymous // receiver types too. - if mt.Sym == nil { + if mt.Sym() == nil { addsignat(t) } } @@ -2385,7 +2385,7 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) { me.SetOpt(m) // Issue 25065. Make sure that we emit the symbol for a local method. - if base.Ctxt.Flag_dynlink && !inimport && (t.Sym == nil || t.Sym.Pkg == ir.LocalPkg) { + if base.Ctxt.Flag_dynlink && !inimport && (t.Sym() == nil || t.Sym().Pkg == ir.LocalPkg) { makefuncsym(me.Sym()) } @@ -2417,7 +2417,7 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field { } var f2 *types.Field - if n.Left().Type() == t || n.Left().Type().Sym == nil { + if n.Left().Type() == t || n.Left().Type().Sym() == nil { mt := methtype(t) if mt != nil { f2 = lookdot1(n, s, mt, mt.Methods(), dostrcmp) @@ -2493,7 +2493,7 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field { pll = ll ll = ll.Left() } - if pll.Implicit() && ll.Type().IsPtr() && ll.Type().Sym != nil && ir.AsNode(ll.Type().Sym.Def) != nil && ir.AsNode(ll.Type().Sym.Def).Op() == ir.OTYPE { + if pll.Implicit() && ll.Type().IsPtr() && ll.Type().Sym() != nil && ir.AsNode(ll.Type().Sym().Def) != nil && ir.AsNode(ll.Type().Sym().Def).Op() == ir.OTYPE { // It is invalid to automatically dereference a named pointer type when selecting a method. // Make n.Left == ll to clarify error message. n.SetLeft(ll) @@ -2681,7 +2681,7 @@ func sigrepr(t *types.Type, isddd bool) string { return "bool" } - if t.Etype == types.TIDEAL { + if t.Kind() == types.TIDEAL { // "untyped number" is not commonly used // outside of the compiler, so let's use "number". // TODO(mdempsky): Revisit this. @@ -2724,7 +2724,7 @@ func fielddup(name string, hash map[string]bool) { // iscomptype reports whether type t is a composite literal type. func iscomptype(t *types.Type) bool { - switch t.Etype { + switch t.Kind() { case types.TARRAY, types.TSLICE, types.TSTRUCT, types.TMAP: return true default: @@ -2801,7 +2801,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) { } n.SetType(t) - switch t.Etype { + switch t.Kind() { default: base.Errorf("invalid composite literal type %v", t) n.SetType(nil) @@ -3154,7 +3154,7 @@ func samesafeexpr(l ir.Node, r ir.Node) bool { case ir.OCONV: // Some conversions can't be reused, such as []byte(str). // Allow only numeric-ish types. This is a bit conservative. - return issimple[l.Type().Etype] && samesafeexpr(l.Left(), r.Left()) + return issimple[l.Type().Kind()] && samesafeexpr(l.Left(), r.Left()) case ir.OINDEX, ir.OINDEXMAP, ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD: @@ -3451,7 +3451,7 @@ func typecheckdeftype(n *ir.Name) { n.SetDiag(true) n.SetType(nil) } - if t.Etype == types.TFORW && base.Errors() > errorsBefore { + if t.Kind() == types.TFORW && base.Errors() > errorsBefore { // Something went wrong during type-checking, // but it was reported. Silence future errors. t.SetBroke(true) @@ -3541,7 +3541,7 @@ func typecheckdef(n ir.Node) { t := n.Type() if t != nil { - if !ir.OKForConst[t.Etype] { + if !ir.OKForConst[t.Kind()] { base.ErrorfAt(n.Pos(), "invalid constant type %v", t) goto ret } @@ -3638,7 +3638,7 @@ ret: func checkmake(t *types.Type, arg string, np *ir.Node) bool { n := *np - if !n.Type().IsInteger() && n.Type().Etype != types.TIDEAL { + if !n.Type().IsInteger() && n.Type().Kind() != types.TIDEAL { base.Errorf("non-integer %s argument in make(%v) - %v", arg, t, n.Type()) return false } diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index b1492659b4..49e50734c6 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -15,7 +15,7 @@ import ( var basicTypes = [...]struct { name string - etype types.EType + etype types.Kind }{ {"int8", types.TINT8}, {"int16", types.TINT16}, @@ -35,9 +35,9 @@ var basicTypes = [...]struct { var typedefs = [...]struct { name string - etype types.EType - sameas32 types.EType - sameas64 types.EType + etype types.Kind + sameas32 types.Kind + sameas64 types.Kind }{ {"int", types.TINT, types.TINT32, types.TINT64}, {"uint", types.TUINT, types.TUINT32, types.TUINT64}, @@ -99,14 +99,14 @@ func initUniverse() { // string is same as slice wo the cap sizeofString = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) - for et := types.EType(0); et < types.NTYPE; et++ { + for et := types.Kind(0); et < types.NTYPE; et++ { simtype[et] = et } types.Types[types.TANY] = types.New(types.TANY) types.Types[types.TINTER] = types.New(types.TINTER) // empty interface - defBasic := func(kind types.EType, pkg *types.Pkg, name string) *types.Type { + defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type { sym := pkg.Lookup(name) n := ir.NewNameAt(src.NoXPos, sym) n.SetOp(ir.OTYPE) @@ -140,18 +140,18 @@ func initUniverse() { // of less informative error messages involving bytes and runes)? // (Alternatively, we could introduce an OTALIAS node representing // type aliases, albeit at the cost of having to deal with it everywhere). - types.Bytetype = defBasic(types.TUINT8, ir.BuiltinPkg, "byte") - types.Runetype = defBasic(types.TINT32, ir.BuiltinPkg, "rune") + types.ByteType = defBasic(types.TUINT8, ir.BuiltinPkg, "byte") + types.RuneType = defBasic(types.TINT32, ir.BuiltinPkg, "rune") // error type s := ir.BuiltinPkg.Lookup("error") n := ir.NewNameAt(src.NoXPos, s) n.SetOp(ir.OTYPE) - types.Errortype = types.NewNamed(n) - types.Errortype.SetUnderlying(makeErrorInterface()) - n.SetType(types.Errortype) + types.ErrorType = types.NewNamed(n) + types.ErrorType.SetUnderlying(makeErrorInterface()) + n.SetType(types.ErrorType) s.Def = n - dowidth(types.Errortype) + dowidth(types.ErrorType) types.Types[types.TUNSAFEPTR] = defBasic(types.TUNSAFEPTR, unsafepkg, "Pointer") @@ -218,7 +218,7 @@ func initUniverse() { isComplex[types.TCOMPLEX128] = true // initialize okfor - for et := types.EType(0); et < types.NTYPE; et++ { + for et := types.Kind(0); et < types.NTYPE; et++ { if isInt[et] || et == types.TIDEAL { okforeq[et] = true okforcmp[et] = true diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 511cdd3685..b3af353c3f 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -423,7 +423,7 @@ func walkexpr(n ir.Node, init *ir.Nodes) ir.Node { // Eagerly checkwidth all expressions for the back end. if n.Type() != nil && !n.Type().WidthCalculated() { - switch n.Type().Etype { + switch n.Type().Kind() { case types.TBLANK, types.TNIL, types.TIDEAL: default: checkwidth(n.Type()) @@ -975,7 +975,7 @@ opswitch: n.SetRight(walkexpr(n.Right(), init)) // rewrite complex div into function call. - et := n.Left().Type().Etype + et := n.Left().Type().Kind() if isComplex[et] && n.Op() == ir.ODIV { t := n.Type() @@ -1638,7 +1638,7 @@ func markUsedIfaceMethod(n ir.Node) { // name can be derived from the names of the returned types. // // If no such function is necessary, it returns (Txxx, Txxx). -func rtconvfn(src, dst *types.Type) (param, result types.EType) { +func rtconvfn(src, dst *types.Type) (param, result types.Kind) { if thearch.SoftFloat { return types.Txxx, types.Txxx } @@ -1646,31 +1646,31 @@ func rtconvfn(src, dst *types.Type) (param, result types.EType) { switch thearch.LinkArch.Family { case sys.ARM, sys.MIPS: if src.IsFloat() { - switch dst.Etype { + switch dst.Kind() { case types.TINT64, types.TUINT64: - return types.TFLOAT64, dst.Etype + return types.TFLOAT64, dst.Kind() } } if dst.IsFloat() { - switch src.Etype { + switch src.Kind() { case types.TINT64, types.TUINT64: - return src.Etype, types.TFLOAT64 + return src.Kind(), types.TFLOAT64 } } case sys.I386: if src.IsFloat() { - switch dst.Etype { + switch dst.Kind() { case types.TINT64, types.TUINT64: - return types.TFLOAT64, dst.Etype + return types.TFLOAT64, dst.Kind() case types.TUINT32, types.TUINT, types.TUINTPTR: return types.TFLOAT64, types.TUINT32 } } if dst.IsFloat() { - switch src.Etype { + switch src.Kind() { case types.TINT64, types.TUINT64: - return src.Etype, types.TFLOAT64 + return src.Kind(), types.TFLOAT64 case types.TUINT32, types.TUINT, types.TUINTPTR: return types.TUINT32, types.TFLOAT64 } @@ -1937,7 +1937,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node { for i, n := range nn.List().Slice() { if n.Op() == ir.OLITERAL { if n.Type() == types.UntypedRune { - n = defaultlit(n, types.Runetype) + n = defaultlit(n, types.RuneType) } switch n.Val().Kind() { @@ -1949,17 +1949,17 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node { } } - if n.Op() != ir.OLITERAL && n.Type() != nil && n.Type().Etype == types.TIDEAL { + if n.Op() != ir.OLITERAL && n.Type() != nil && n.Type().Kind() == types.TIDEAL { n = defaultlit(n, types.Types[types.TINT64]) } n = defaultlit(n, nil) nn.List().SetIndex(i, n) - if n.Type() == nil || n.Type().Etype == types.TFORW { + if n.Type() == nil || n.Type().Kind() == types.TFORW { continue } var on ir.Node - switch n.Type().Etype { + switch n.Type().Kind() { case types.TINTER: if n.Type().IsEmptyInterface() { on = syslook("printeface") @@ -1984,7 +1984,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node { on = syslook("printslice") on = substArgTypes(on, n.Type()) // any-1 case types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR: - if isRuntimePkg(n.Type().Sym.Pkg) && n.Type().Sym.Name == "hex" { + if isRuntimePkg(n.Type().Sym().Pkg) && n.Type().Sym().Name == "hex" { on = syslook("printhex") } else { on = syslook("printuint") @@ -2058,9 +2058,9 @@ func isReflectHeaderDataField(l ir.Node) bool { var tsym *types.Sym switch l.Op() { case ir.ODOT: - tsym = l.Left().Type().Sym + tsym = l.Left().Type().Sym() case ir.ODOTPTR: - tsym = l.Left().Type().Elem().Sym + tsym = l.Left().Type().Elem().Sym() default: return false } @@ -2484,7 +2484,7 @@ func heapmoves() { } func vmkcall(fn ir.Node, t *types.Type, init *ir.Nodes, va []ir.Node) ir.Node { - if fn.Type() == nil || fn.Type().Etype != types.TFUNC { + if fn.Type() == nil || fn.Type().Kind() != types.TFUNC { base.Fatalf("mkcall %v %v", fn, fn.Type()) } @@ -3264,7 +3264,7 @@ func walkcompare(n ir.Node, init *ir.Nodes) ir.Node { maxcmpsize = 2 * int64(thearch.LinkArch.RegSize) } - switch t.Etype { + switch t.Kind() { default: if base.Debug.Libfuzzer != 0 && t.IsInteger() { n.SetLeft(cheapexpr(n.Left(), init)) @@ -3315,7 +3315,7 @@ func walkcompare(n ir.Node, init *ir.Nodes) ir.Node { return n case types.TARRAY: // We can compare several elements at once with 2/4/8 byte integer compares - inline = t.NumElem() <= 1 || (issimple[t.Elem().Etype] && (t.NumElem() <= 4 || t.Elem().Width*t.NumElem() <= maxcmpsize)) + inline = t.NumElem() <= 1 || (issimple[t.Elem().Kind()] && (t.NumElem() <= 4 || t.Elem().Width*t.NumElem() <= maxcmpsize)) case types.TSTRUCT: inline = t.NumComponents(types.IgnoreBlankFields) <= 4 } @@ -3697,7 +3697,7 @@ func usemethod(n ir.Node) { } if res1 == nil { - if p0.Type.Etype != types.TINT { + if p0.Type.Kind() != types.TINT { return } } else { @@ -3712,7 +3712,7 @@ func usemethod(n ir.Node) { // Note: Don't rely on res0.Type.String() since its formatting depends on multiple factors // (including global variables such as numImports - was issue #19028). // Also need to check for reflect package itself (see Issue #38515). - if s := res0.Type.Sym; s != nil && s.Name == "Method" && isReflectPkg(s.Pkg) { + if s := res0.Type.Sym(); s != nil && s.Name == "Method" && isReflectPkg(s.Pkg) { Curfn.SetReflectMethod(true) // The LSym is initialized at this point. We need to set the attribute on the LSym. Curfn.LSym.Set(obj.AttrReflectMethod, true) @@ -3756,7 +3756,7 @@ func usefield(n ir.Node) { if outer.IsPtr() { outer = outer.Elem() } - if outer.Sym == nil { + if outer.Sym() == nil { base.Errorf("tracked field must be in named struct type") } if !types.IsExported(field.Sym.Name) { diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index a111471222..5bb1ed857c 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -317,7 +317,7 @@ func (m FmtMode) prepareArgs(args []interface{}) { args[i] = &fmtSym{arg, m} case Nodes: args[i] = &fmtNodes{arg, m} - case int32, int64, string, types.EType, constant.Value: + case int32, int64, string, types.Kind, constant.Value: // OK: printing these types doesn't depend on mode default: base.Fatalf("mode.prepareArgs type %T", arg) @@ -590,18 +590,18 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited b.WriteString("") return } - if t.Etype == types.TSSA { + if t.Kind() == types.TSSA { b.WriteString(t.Extra.(string)) return } - if t.Etype == types.TTUPLE { + if t.Kind() == types.TTUPLE { b.WriteString(t.FieldType(0).String()) b.WriteByte(',') b.WriteString(t.FieldType(1).String()) return } - if t.Etype == types.TRESULTS { + if t.Kind() == types.TRESULTS { tys := t.Extra.(*types.Results).Types for i, et := range tys { if i > 0 { @@ -616,51 +616,51 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited if mode == FTypeIdName { flag |= FmtUnsigned } - if t == types.Bytetype || t == types.Runetype { + if t == types.ByteType || t == types.RuneType { // in %-T mode collapse rune and byte with their originals. switch mode { case FTypeIdName, FTypeId: - t = types.Types[t.Etype] + t = types.Types[t.Kind()] default: - sconv2(b, t.Sym, FmtShort, mode) + sconv2(b, t.Sym(), FmtShort, mode) return } } - if t == types.Errortype { + if t == types.ErrorType { b.WriteString("error") return } // Unless the 'L' flag was specified, if the type has a name, just print that name. - if flag&FmtLong == 0 && t.Sym != nil && t != types.Types[t.Etype] { + if flag&FmtLong == 0 && t.Sym() != nil && t != types.Types[t.Kind()] { switch mode { case FTypeId, FTypeIdName: if flag&FmtShort != 0 { if t.Vargen != 0 { - sconv2(b, t.Sym, FmtShort, mode) + sconv2(b, t.Sym(), FmtShort, mode) fmt.Fprintf(b, "·%d", t.Vargen) return } - sconv2(b, t.Sym, FmtShort, mode) + sconv2(b, t.Sym(), FmtShort, mode) return } if mode == FTypeIdName { - sconv2(b, t.Sym, FmtUnsigned, mode) + sconv2(b, t.Sym(), FmtUnsigned, mode) return } - if t.Sym.Pkg == LocalPkg && t.Vargen != 0 { - b.WriteString(mode.Sprintf("%v·%d", t.Sym, t.Vargen)) + if t.Sym().Pkg == LocalPkg && t.Vargen != 0 { + b.WriteString(mode.Sprintf("%v·%d", t.Sym(), t.Vargen)) return } } - sconv2(b, t.Sym, 0, mode) + sconv2(b, t.Sym(), 0, mode) return } - if int(t.Etype) < len(BasicTypeNames) && BasicTypeNames[t.Etype] != "" { + if int(t.Kind()) < len(BasicTypeNames) && BasicTypeNames[t.Kind()] != "" { var name string switch t { case types.UntypedBool: @@ -676,14 +676,14 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited case types.UntypedComplex: name = "untyped complex" default: - name = BasicTypeNames[t.Etype] + name = BasicTypeNames[t.Kind()] } b.WriteString(name) return } if mode == FDbg { - b.WriteString(t.Etype.String()) + b.WriteString(t.Kind().String()) b.WriteByte('-') tconv2(b, t, flag, FErr, visited) return @@ -702,7 +702,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited visited[t] = b.Len() defer delete(visited, t) - switch t.Etype { + switch t.Kind() { case types.TPTR: b.WriteByte('*') switch mode { @@ -734,7 +734,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited tconv2(b, t.Elem(), 0, mode, visited) default: b.WriteString("chan ") - if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == types.Crecv { + if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym() == nil && t.Elem().ChanDir() == types.Crecv { b.WriteByte('(') tconv2(b, t.Elem(), 0, mode, visited) b.WriteByte(')') @@ -860,9 +860,9 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited case types.TFORW: b.WriteString("undefined") - if t.Sym != nil { + if t.Sym() != nil { b.WriteByte(' ') - sconv2(b, t.Sym, 0, mode) + sconv2(b, t.Sym(), 0, mode) } case types.TUNSAFEPTR: @@ -872,7 +872,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited b.WriteString("Txxx") default: // Don't know how to handle - fall back to detailed prints. - b.WriteString(mode.Sprintf("%v <%v>", t.Etype, t.Sym)) + b.WriteString(mode.Sprintf("%v <%v>", t.Kind(), t.Sym())) } } @@ -1446,7 +1446,7 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { OSTR2BYTES, OSTR2RUNES, ORUNESTR: - if n.Type() == nil || n.Type().Sym == nil { + if n.Type() == nil || n.Type().Sym() == nil { mode.Fprintf(s, "(%v)", n.Type()) } else { mode.Fprintf(s, "%v", n.Type()) @@ -1564,7 +1564,7 @@ func nodeFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { } if flag&FmtLong != 0 && t != nil { - if t.Etype == types.TNIL { + if t.Kind() == types.TNIL { fmt.Fprint(s, "nil") } else if n.Op() == ONAME && n.Name().AutoTemp() { mode.Fprintf(s, "%v value", t) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index a7144eee44..fc4c593929 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -647,7 +647,7 @@ const ( GoBuildPragma ) -func AsNode(n types.IRNode) Node { +func AsNode(n types.Object) Node { if n == nil { return nil } diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index 446145b24c..d2f5bb9239 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -353,7 +353,7 @@ func (n *typeNode) String() string { return fmt.Sprint(n) } func (n *typeNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *typeNode) rawCopy() Node { c := *n; return &c } func (n *typeNode) Type() *types.Type { return n.typ } -func (n *typeNode) Sym() *types.Sym { return n.typ.Sym } +func (n *typeNode) Sym() *types.Sym { return n.typ.Sym() } func (n *typeNode) CanBeNtype() {} // TypeNode returns the Node representing the type t. diff --git a/src/cmd/compile/internal/ir/val.go b/src/cmd/compile/internal/ir/val.go index 9035e90084..aae965bb4c 100644 --- a/src/cmd/compile/internal/ir/val.go +++ b/src/cmd/compile/internal/ir/val.go @@ -73,7 +73,7 @@ func AssertValidTypeForConst(t *types.Type, v constant.Value) { func ValidTypeForConst(t *types.Type, v constant.Value) bool { switch v.Kind() { case constant.Unknown: - return OKForConst[t.Etype] + return OKForConst[t.Kind()] case constant.Bool: return t.IsBoolean() case constant.String: diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index f266e49327..0eba238d81 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -69,7 +69,7 @@ func expandCalls(f *Func) { // intPairTypes returns the pair of 32-bit int types needed to encode a 64-bit integer type on a target // that has no 64-bit integer registers. - intPairTypes := func(et types.EType) (tHi, tLo *types.Type) { + intPairTypes := func(et types.Kind) (tHi, tLo *types.Type) { tHi = typ.UInt32 if et == types.TINT64 { tHi = typ.Int32 @@ -294,7 +294,7 @@ func expandCalls(f *Func) { case OpStructSelect: w := selector.Args[0] var ls []LocalSlot - if w.Type.Etype != types.TSTRUCT { // IData artifact + if w.Type.Kind() != types.TSTRUCT { // IData artifact ls = rewriteSelect(leaf, w, offset) } else { ls = rewriteSelect(leaf, w, offset+w.Type.FieldOff(int(selector.AuxInt))) @@ -383,7 +383,7 @@ func expandCalls(f *Func) { decomposeOne func(pos src.XPos, b *Block, base, source, mem *Value, t1 *types.Type, offArg, offStore int64) *Value, decomposeTwo func(pos src.XPos, b *Block, base, source, mem *Value, t1, t2 *types.Type, offArg, offStore int64) *Value) *Value { u := source.Type - switch u.Etype { + switch u.Kind() { case types.TARRAY: elem := u.Elem() for i := int64(0); i < u.NumElem(); i++ { @@ -403,7 +403,7 @@ func expandCalls(f *Func) { if t.Width == regSize { break } - tHi, tLo := intPairTypes(t.Etype) + tHi, tLo := intPairTypes(t.Kind()) mem = decomposeOne(pos, b, base, source, mem, tHi, source.AuxInt+hiOffset, offset+hiOffset) pos = pos.WithNotStmt() return decomposeOne(pos, b, base, source, mem, tLo, source.AuxInt+lowOffset, offset+lowOffset) @@ -491,7 +491,7 @@ func expandCalls(f *Func) { return storeArgOrLoad(pos, b, base, source.Args[0], mem, t.Elem(), offset) case OpInt64Make: - tHi, tLo := intPairTypes(t.Etype) + tHi, tLo := intPairTypes(t.Kind()) mem = storeArgOrLoad(pos, b, base, source.Args[0], mem, tHi, offset+hiOffset) pos = pos.WithNotStmt() return storeArgOrLoad(pos, b, base, source.Args[1], mem, tLo, offset+lowOffset) @@ -524,7 +524,7 @@ func expandCalls(f *Func) { } // For nodes that cannot be taken apart -- OpSelectN, other structure selectors. - switch t.Etype { + switch t.Kind() { case types.TARRAY: elt := t.Elem() if source.Type != t && t.NumElem() == 1 && elt.Width == t.Width && t.Width == regSize { @@ -576,7 +576,7 @@ func expandCalls(f *Func) { if t.Width == regSize { break } - tHi, tLo := intPairTypes(t.Etype) + tHi, tLo := intPairTypes(t.Kind()) sel := source.Block.NewValue1(pos, OpInt64Hi, tHi, source) mem = storeArgOrLoad(pos, b, base, sel, mem, tHi, offset+hiOffset) pos = pos.WithNotStmt() @@ -873,7 +873,7 @@ func expandCalls(f *Func) { offset := int64(0) switch v.Op { case OpStructSelect: - if w.Type.Etype == types.TSTRUCT { + if w.Type.Kind() == types.TSTRUCT { offset = w.Type.FieldOff(int(v.AuxInt)) } else { // Immediate interface data artifact, offset is zero. f.Fatalf("Expand calls interface data problem, func %s, v=%s, w=%s\n", f.Name, v.LongString(), w.LongString()) diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index df83383308..5a81f76ceb 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -140,7 +140,7 @@ func init() { // so this test setup can share it. types.Tconv = func(t *types.Type, flag, mode int) string { - return t.Etype.String() + return t.Kind().String() } types.Sconv = func(s *types.Sym, flag, mode int) string { return "sym" @@ -149,13 +149,13 @@ func init() { fmt.Fprintf(s, "sym") } types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) { - fmt.Fprintf(s, "%v", t.Etype) + fmt.Fprintf(s, "%v", t.Kind()) } types.Dowidth = func(t *types.Type) {} for _, typ := range [...]struct { width int64 - et types.EType + et types.Kind }{ {1, types.TINT8}, {1, types.TUINT8}, diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 459a9923f7..376ca97512 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -783,9 +783,9 @@ func (s *regAllocState) compatRegs(t *types.Type) regMask { return 0 } if t.IsFloat() || t == types.TypeInt128 { - if t.Etype == types.TFLOAT32 && s.f.Config.fp32RegMask != 0 { + if t.Kind() == types.TFLOAT32 && s.f.Config.fp32RegMask != 0 { m = s.f.Config.fp32RegMask - } else if t.Etype == types.TFLOAT64 && s.f.Config.fp64RegMask != 0 { + } else if t.Kind() == types.TFLOAT64 && s.f.Config.fp64RegMask != 0 { m = s.f.Config.fp64RegMask } else { m = s.f.Config.fpRegMask diff --git a/src/cmd/compile/internal/types/etype_string.go b/src/cmd/compile/internal/types/etype_string.go index 14fd5b71df..e7698296ab 100644 --- a/src/cmd/compile/internal/types/etype_string.go +++ b/src/cmd/compile/internal/types/etype_string.go @@ -52,8 +52,8 @@ const _EType_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTR var _EType_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 158, 161, 166, 174, 182, 185, 190, 197, 202} -func (i EType) String() string { - if i >= EType(len(_EType_index)-1) { +func (i Kind) String() string { + if i >= Kind(len(_EType_index)-1) { return "EType(" + strconv.FormatInt(int64(i), 10) + ")" } return _EType_name[_EType_index[i]:_EType_index[i+1]] diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go index a77f514df9..9bc636d7ff 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -25,17 +25,17 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b if t1 == t2 { return true } - if t1 == nil || t2 == nil || t1.Etype != t2.Etype || t1.Broke() || t2.Broke() { + if t1 == nil || t2 == nil || t1.kind != t2.kind || t1.Broke() || t2.Broke() { return false } - if t1.Sym != nil || t2.Sym != nil { + if t1.sym != nil || t2.sym != nil { // Special case: we keep byte/uint8 and rune/int32 // separate for error messages. Treat them as equal. - switch t1.Etype { + switch t1.kind { case TUINT8: - return (t1 == Types[TUINT8] || t1 == Bytetype) && (t2 == Types[TUINT8] || t2 == Bytetype) + return (t1 == Types[TUINT8] || t1 == ByteType) && (t2 == Types[TUINT8] || t2 == ByteType) case TINT32: - return (t1 == Types[TINT32] || t1 == Runetype) && (t2 == Types[TINT32] || t2 == Runetype) + return (t1 == Types[TINT32] || t1 == RuneType) && (t2 == Types[TINT32] || t2 == RuneType) default: return false } @@ -52,7 +52,7 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b } assumedEqual[typePair{t1, t2}] = struct{}{} - switch t1.Etype { + switch t1.kind { case TIDEAL: // Historically, cmd/compile used a single "untyped // number" type, so all untyped number types were diff --git a/src/cmd/compile/internal/types/scope.go b/src/cmd/compile/internal/types/scope.go index 33a02c543d..37ac90a025 100644 --- a/src/cmd/compile/internal/types/scope.go +++ b/src/cmd/compile/internal/types/scope.go @@ -15,7 +15,7 @@ var Block int32 // current block number // restored once the block scope ends. type dsym struct { sym *Sym // sym == nil indicates stack mark - def IRNode + def Object block int32 lastlineno src.XPos // last declaration for diagnostic } @@ -79,16 +79,16 @@ func IsDclstackValid() bool { } // PkgDef returns the definition associated with s at package scope. -func (s *Sym) PkgDef() IRNode { +func (s *Sym) PkgDef() Object { return *s.pkgDefPtr() } // SetPkgDef sets the definition associated with s at package scope. -func (s *Sym) SetPkgDef(n IRNode) { +func (s *Sym) SetPkgDef(n Object) { *s.pkgDefPtr() = n } -func (s *Sym) pkgDefPtr() *IRNode { +func (s *Sym) pkgDefPtr() *Object { // Look for outermost saved declaration, which must be the // package scope definition, if present. for _, d := range dclstack { diff --git a/src/cmd/compile/internal/types/sym.go b/src/cmd/compile/internal/types/sym.go index 7272f1f786..490222d843 100644 --- a/src/cmd/compile/internal/types/sym.go +++ b/src/cmd/compile/internal/types/sym.go @@ -33,7 +33,7 @@ type Sym struct { Name string // object name // saved and restored by dcopy - Def IRNode // definition: ONAME OTYPE OPACK or OLITERAL + Def Object // definition: ONAME OTYPE OPACK or OLITERAL Block int32 // blocknumber to catch redeclaration Lastlineno src.XPos // last declaration for diagnostic diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index f0211a67fb..36aac53124 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -14,7 +14,7 @@ import ( // IRNode represents an ir.Node, but without needing to import cmd/compile/internal/ir, // which would cause an import cycle. The uses in other packages must type assert // values of type IRNode to ir.Node or a more specific type. -type IRNode interface { +type Object interface { Pos() src.XPos Sym() *Sym Type() *Type @@ -23,10 +23,10 @@ type IRNode interface { //go:generate stringer -type EType -trimprefix T // EType describes a kind of type. -type EType uint8 +type Kind uint8 const ( - Txxx EType = iota + Txxx Kind = iota TINT8 TUINT8 @@ -103,11 +103,11 @@ var Types [NTYPE]*Type var ( // Predeclared alias types. Kept separate for better error messages. - Bytetype *Type - Runetype *Type + ByteType *Type + RuneType *Type // Predeclared error interface type. - Errortype *Type + ErrorType *Type // Types to represent untyped string and boolean constants. UntypedString = New(TSTRING) @@ -146,19 +146,19 @@ type Type struct { methods Fields allMethods Fields - nod IRNode // canonical OTYPE node - Orig *Type // original type (type literal or predefined type) + nod Object // canonical OTYPE node + underlying *Type // original type (type literal or predefined type) // Cache of composite types, with this type being the element type. - Cache struct { + cache struct { ptr *Type // *T, or nil slice *Type // []T, or nil } - Sym *Sym // symbol containing name, for named types + sym *Sym // symbol containing name, for named types Vargen int32 // unique name for OTYPE/ONAME - Etype EType // kind of type + kind Kind // kind of type Align uint8 // the required alignment of this type, in bytes (0 means Width and Align have not yet been computed) flags bitset8 @@ -185,16 +185,16 @@ func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) } func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) } // Kind returns the kind of type t. -func (t *Type) Kind() EType { return t.Etype } +func (t *Type) Kind() Kind { return t.kind } // Sym returns the name of type t. -func (t *Type) GetSym() *Sym { return t.Sym } +func (t *Type) Sym() *Sym { return t.sym } // Underlying returns the underlying type of type t. -func (t *Type) Underlying() *Type { return t.Orig } +func (t *Type) Underlying() *Type { return t.underlying } // SetNod associates t with syntax node n. -func (t *Type) SetNod(n IRNode) { +func (t *Type) SetNod(n Object) { // t.nod can be non-nil already // in the case of shared *Types, like []byte or interface{}. if t.nod == nil { @@ -218,7 +218,7 @@ func (t *Type) Pos() src.XPos { // cmd/compile itself, but we need to track it because it's exposed by // the go/types API. func (t *Type) Pkg() *Pkg { - switch t.Etype { + switch t.kind { case TFUNC: return t.Extra.(*Func).pkg case TSTRUCT: @@ -233,7 +233,7 @@ func (t *Type) Pkg() *Pkg { // SetPkg sets the package that t appeared in. func (t *Type) SetPkg(pkg *Pkg) { - switch t.Etype { + switch t.kind { case TFUNC: t.Extra.(*Func).pkg = pkg case TSTRUCT: @@ -392,7 +392,7 @@ type Field struct { // For fields that represent function parameters, Nname points // to the associated ONAME Node. - Nname IRNode + Nname Object // Offset in bytes of this field or method within its enclosing struct // or interface Type. @@ -420,7 +420,7 @@ func (f *Field) End() int64 { // IsMethod reports whether f represents a method rather than a struct field. func (f *Field) IsMethod() bool { - return f.Type.Etype == TFUNC && f.Type.Recv() != nil + return f.Type.kind == TFUNC && f.Type.Recv() != nil } // Fields is a pointer to a slice of *Field. @@ -475,14 +475,14 @@ func (f *Fields) Append(s ...*Field) { } // New returns a new Type of the specified kind. -func New(et EType) *Type { +func New(et Kind) *Type { t := &Type{ - Etype: et, + kind: et, Width: BADWIDTH, } - t.Orig = t + t.underlying = t // TODO(josharian): lazily initialize some of these? - switch t.Etype { + switch t.kind { case TMAP: t.Extra = new(Map) case TFORW: @@ -522,7 +522,7 @@ func NewArray(elem *Type, bound int64) *Type { // NewSlice returns the slice Type with element type elem. func NewSlice(elem *Type) *Type { - if t := elem.Cache.slice; t != nil { + if t := elem.cache.slice; t != nil { if t.Elem() != elem { Fatalf("elem mismatch") } @@ -531,7 +531,7 @@ func NewSlice(elem *Type) *Type { t := New(TSLICE) t.Extra = Slice{Elem: elem} - elem.Cache.slice = t + elem.cache.slice = t return t } @@ -583,7 +583,7 @@ func NewPtr(elem *Type) *Type { Fatalf("NewPtr: pointer to elem Type is nil") } - if t := elem.Cache.ptr; t != nil { + if t := elem.cache.ptr; t != nil { if t.Elem() != elem { Fatalf("NewPtr: elem mismatch") } @@ -595,7 +595,7 @@ func NewPtr(elem *Type) *Type { t.Width = int64(Widthptr) t.Align = uint8(Widthptr) if NewPtrCacheEnabled { - elem.Cache.ptr = t + elem.cache.ptr = t } return t } @@ -634,7 +634,7 @@ func SubstAny(t *Type, types *[]*Type) *Type { return nil } - switch t.Etype { + switch t.kind { default: // Leave the type unchanged. @@ -718,7 +718,7 @@ func (t *Type) copy() *Type { } nt := *t // copy any *T Extra fields, to avoid aliasing - switch t.Etype { + switch t.kind { case TMAP: x := *t.Extra.(*Map) nt.Extra = &x @@ -744,8 +744,8 @@ func (t *Type) copy() *Type { Fatalf("ssa types cannot be copied") } // TODO(mdempsky): Find out why this is necessary and explain. - if t.Orig == t { - nt.Orig = &nt + if t.underlying == t { + nt.underlying = &nt } return &nt } @@ -755,8 +755,8 @@ func (f *Field) Copy() *Field { return &nf } -func (t *Type) wantEtype(et EType) { - if t.Etype != et { +func (t *Type) wantEtype(et Kind) { + if t.kind != et { Fatalf("want %v, but have %v", et, t) } } @@ -810,7 +810,7 @@ func (t *Type) Key() *Type { // Elem returns the type of elements of t. // Usable with pointers, channels, arrays, slices, and maps. func (t *Type) Elem() *Type { - switch t.Etype { + switch t.kind { case TPTR: return t.Extra.(Ptr).Elem case TARRAY: @@ -822,7 +822,7 @@ func (t *Type) Elem() *Type { case TMAP: return t.Extra.(*Map).Elem } - Fatalf("Type.Elem %s", t.Etype) + Fatalf("Type.Elem %s", t.kind) return nil } @@ -840,7 +840,7 @@ func (t *Type) FuncArgs() *Type { // IsFuncArgStruct reports whether t is a struct representing function parameters. func (t *Type) IsFuncArgStruct() bool { - return t.Etype == TSTRUCT && t.Extra.(*Struct).Funarg != FunargNone + return t.kind == TSTRUCT && t.Extra.(*Struct).Funarg != FunargNone } func (t *Type) Methods() *Fields { @@ -854,7 +854,7 @@ func (t *Type) AllMethods() *Fields { } func (t *Type) Fields() *Fields { - switch t.Etype { + switch t.kind { case TSTRUCT: return &t.Extra.(*Struct).fields case TINTER: @@ -919,7 +919,7 @@ func (t *Type) ArgWidth() int64 { } func (t *Type) Size() int64 { - if t.Etype == TSSA { + if t.kind == TSSA { if t == TypeInt128 { return 16 } @@ -935,7 +935,7 @@ func (t *Type) Alignment() int64 { } func (t *Type) SimpleString() string { - return t.Etype.String() + return t.kind.String() } // Cmp is a comparison between values a and b. @@ -1019,31 +1019,31 @@ func (t *Type) cmp(x *Type) Cmp { return CMPgt } - if t.Etype != x.Etype { - return cmpForNe(t.Etype < x.Etype) + if t.kind != x.kind { + return cmpForNe(t.kind < x.kind) } - if t.Sym != nil || x.Sym != nil { + if t.sym != nil || x.sym != nil { // Special case: we keep byte and uint8 separate // for error messages. Treat them as equal. - switch t.Etype { + switch t.kind { case TUINT8: - if (t == Types[TUINT8] || t == Bytetype) && (x == Types[TUINT8] || x == Bytetype) { + if (t == Types[TUINT8] || t == ByteType) && (x == Types[TUINT8] || x == ByteType) { return CMPeq } case TINT32: - if (t == Types[Runetype.Etype] || t == Runetype) && (x == Types[Runetype.Etype] || x == Runetype) { + if (t == Types[RuneType.kind] || t == RuneType) && (x == Types[RuneType.kind] || x == RuneType) { return CMPeq } } } - if c := t.Sym.cmpsym(x.Sym); c != CMPeq { + if c := t.sym.cmpsym(x.sym); c != CMPeq { return c } - if x.Sym != nil { + if x.sym != nil { // Syms non-nil, if vargens match then equal. if t.Vargen != x.Vargen { return cmpForNe(t.Vargen < x.Vargen) @@ -1052,7 +1052,7 @@ func (t *Type) cmp(x *Type) Cmp { } // both syms nil, look at structure below. - switch t.Etype { + switch t.kind { case TBOOL, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TUNSAFEPTR, TUINTPTR, TINT8, TINT16, TINT32, TINT64, TINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINT: return CMPeq @@ -1209,15 +1209,15 @@ func (t *Type) cmp(x *Type) Cmp { } // IsKind reports whether t is a Type of the specified kind. -func (t *Type) IsKind(et EType) bool { - return t != nil && t.Etype == et +func (t *Type) IsKind(et Kind) bool { + return t != nil && t.kind == et } func (t *Type) IsBoolean() bool { - return t.Etype == TBOOL + return t.kind == TBOOL } -var unsignedEType = [...]EType{ +var unsignedEType = [...]Kind{ TINT8: TUINT8, TUINT8: TUINT8, TINT16: TUINT16, @@ -1236,11 +1236,11 @@ func (t *Type) ToUnsigned() *Type { if !t.IsInteger() { Fatalf("unsignedType(%v)", t) } - return Types[unsignedEType[t.Etype]] + return Types[unsignedEType[t.kind]] } func (t *Type) IsInteger() bool { - switch t.Etype { + switch t.kind { case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR: return true } @@ -1248,7 +1248,7 @@ func (t *Type) IsInteger() bool { } func (t *Type) IsSigned() bool { - switch t.Etype { + switch t.kind { case TINT8, TINT16, TINT32, TINT64, TINT: return true } @@ -1256,7 +1256,7 @@ func (t *Type) IsSigned() bool { } func (t *Type) IsUnsigned() bool { - switch t.Etype { + switch t.kind { case TUINT8, TUINT16, TUINT32, TUINT64, TUINT, TUINTPTR: return true } @@ -1264,32 +1264,32 @@ func (t *Type) IsUnsigned() bool { } func (t *Type) IsFloat() bool { - return t.Etype == TFLOAT32 || t.Etype == TFLOAT64 || t == UntypedFloat + return t.kind == TFLOAT32 || t.kind == TFLOAT64 || t == UntypedFloat } func (t *Type) IsComplex() bool { - return t.Etype == TCOMPLEX64 || t.Etype == TCOMPLEX128 || t == UntypedComplex + return t.kind == TCOMPLEX64 || t.kind == TCOMPLEX128 || t == UntypedComplex } // IsPtr reports whether t is a regular Go pointer type. // This does not include unsafe.Pointer. func (t *Type) IsPtr() bool { - return t.Etype == TPTR + return t.kind == TPTR } // IsPtrElem reports whether t is the element of a pointer (to t). func (t *Type) IsPtrElem() bool { - return t.Cache.ptr != nil + return t.cache.ptr != nil } // IsUnsafePtr reports whether t is an unsafe pointer. func (t *Type) IsUnsafePtr() bool { - return t.Etype == TUNSAFEPTR + return t.kind == TUNSAFEPTR } // IsUintptr reports whether t is an uintptr. func (t *Type) IsUintptr() bool { - return t.Etype == TUINTPTR + return t.kind == TUINTPTR } // IsPtrShaped reports whether t is represented by a single machine pointer. @@ -1298,13 +1298,13 @@ func (t *Type) IsUintptr() bool { // that consist of a single pointer shaped type. // TODO(mdempsky): Should it? See golang.org/issue/15028. func (t *Type) IsPtrShaped() bool { - return t.Etype == TPTR || t.Etype == TUNSAFEPTR || - t.Etype == TMAP || t.Etype == TCHAN || t.Etype == TFUNC + return t.kind == TPTR || t.kind == TUNSAFEPTR || + t.kind == TMAP || t.kind == TCHAN || t.kind == TFUNC } // HasNil reports whether the set of values determined by t includes nil. func (t *Type) HasNil() bool { - switch t.Etype { + switch t.kind { case TCHAN, TFUNC, TINTER, TMAP, TNIL, TPTR, TSLICE, TUNSAFEPTR: return true } @@ -1312,31 +1312,31 @@ func (t *Type) HasNil() bool { } func (t *Type) IsString() bool { - return t.Etype == TSTRING + return t.kind == TSTRING } func (t *Type) IsMap() bool { - return t.Etype == TMAP + return t.kind == TMAP } func (t *Type) IsChan() bool { - return t.Etype == TCHAN + return t.kind == TCHAN } func (t *Type) IsSlice() bool { - return t.Etype == TSLICE + return t.kind == TSLICE } func (t *Type) IsArray() bool { - return t.Etype == TARRAY + return t.kind == TARRAY } func (t *Type) IsStruct() bool { - return t.Etype == TSTRUCT + return t.kind == TSTRUCT } func (t *Type) IsInterface() bool { - return t.Etype == TINTER + return t.kind == TINTER } // IsEmptyInterface reports whether t is an empty interface type. @@ -1352,7 +1352,7 @@ func (t *Type) NumFields() int { return t.Fields().Len() } func (t *Type) FieldType(i int) *Type { - if t.Etype == TTUPLE { + if t.kind == TTUPLE { switch i { case 0: return t.Extra.(*Tuple).first @@ -1362,7 +1362,7 @@ func (t *Type) FieldType(i int) *Type { panic("bad tuple index") } } - if t.Etype == TRESULTS { + if t.kind == TRESULTS { return t.Extra.(*Results).Types[i] } return t.Field(i).Type @@ -1393,7 +1393,7 @@ const ( // (and their comprised elements) are excluded from the count. // struct { x, y [3]int } has six components; [10]struct{ x, y string } has twenty. func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 { - switch t.Etype { + switch t.kind { case TSTRUCT: if t.IsFuncArgStruct() { Fatalf("NumComponents func arg struct") @@ -1416,7 +1416,7 @@ func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 { // if there is exactly one. Otherwise, it returns nil. // Components are counted as in NumComponents, including blank fields. func (t *Type) SoleComponent() *Type { - switch t.Etype { + switch t.kind { case TSTRUCT: if t.IsFuncArgStruct() { Fatalf("SoleComponent func arg struct") @@ -1442,10 +1442,10 @@ func (t *Type) ChanDir() ChanDir { } func (t *Type) IsMemory() bool { - if t == TypeMem || t.Etype == TTUPLE && t.Extra.(*Tuple).second == TypeMem { + if t == TypeMem || t.kind == TTUPLE && t.Extra.(*Tuple).second == TypeMem { return true } - if t.Etype == TRESULTS { + if t.kind == TRESULTS { if types := t.Extra.(*Results).Types; len(types) > 0 && types[len(types)-1] == TypeMem { return true } @@ -1454,8 +1454,8 @@ func (t *Type) IsMemory() bool { } func (t *Type) IsFlags() bool { return t == TypeFlags } func (t *Type) IsVoid() bool { return t == TypeVoid } -func (t *Type) IsTuple() bool { return t.Etype == TTUPLE } -func (t *Type) IsResults() bool { return t.Etype == TRESULTS } +func (t *Type) IsTuple() bool { return t.kind == TTUPLE } +func (t *Type) IsResults() bool { return t.kind == TRESULTS } // IsUntyped reports whether t is an untyped type. func (t *Type) IsUntyped() bool { @@ -1465,7 +1465,7 @@ func (t *Type) IsUntyped() bool { if t == UntypedString || t == UntypedBool { return true } - switch t.Etype { + switch t.kind { case TNIL, TIDEAL: return true } @@ -1475,7 +1475,7 @@ func (t *Type) IsUntyped() bool { // HasPointers reports whether t contains a heap pointer. // Note that this function ignores pointers to go:notinheap types. func (t *Type) HasPointers() bool { - switch t.Etype { + switch t.kind { case TINT, TUINT, TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TUINTPTR, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TBOOL, TSSA: return false @@ -1551,16 +1551,16 @@ var ( ) // NewNamed returns a new named type for the given type name. -func NewNamed(obj IRNode) *Type { +func NewNamed(obj Object) *Type { t := New(TFORW) - t.Sym = obj.Sym() + t.sym = obj.Sym() t.nod = obj return t } // Obj returns the type name for the named type t. -func (t *Type) Obj() IRNode { - if t.Sym != nil { +func (t *Type) Obj() Object { + if t.sym != nil { return t.nod } return nil @@ -1568,7 +1568,7 @@ func (t *Type) Obj() IRNode { // SetUnderlying sets the underlying type. func (t *Type) SetUnderlying(underlying *Type) { - if underlying.Etype == TFORW { + if underlying.kind == TFORW { // This type isn't computed yet; when it is, update n. underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t) return @@ -1577,11 +1577,11 @@ func (t *Type) SetUnderlying(underlying *Type) { ft := t.ForwardType() // TODO(mdempsky): Fix Type rekinding. - t.Etype = underlying.Etype + t.kind = underlying.kind t.Extra = underlying.Extra t.Width = underlying.Width t.Align = underlying.Align - t.Orig = underlying.Orig + t.underlying = underlying.underlying if underlying.NotInHeap() { t.SetNotInHeap(true) @@ -1612,9 +1612,9 @@ func (t *Type) SetUnderlying(underlying *Type) { } // NewNamed returns a new basic type of the given kind. -func NewBasic(kind EType, obj IRNode) *Type { +func NewBasic(kind Kind, obj Object) *Type { t := New(kind) - t.Sym = obj.Sym() + t.sym = obj.Sym() t.nod = obj return t } From ae3bfba6269fcc75aced2418b870ba2706b0d35f Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Tue, 1 Dec 2020 13:54:53 +0100 Subject: [PATCH 064/212] doc/go1.16: add text/template changes to release notes For #40700 Fixes #42914 Change-Id: I673d86a946c362e28bfbf35fab2c60ebfbd8bda2 Reviewed-on: https://go-review.googlesource.com/c/go/+/274472 Trust: Alberto Donizetti Reviewed-by: Dmitri Shuralyov --- doc/go1.16.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 145f920aab..3545632ea4 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -699,8 +699,9 @@ Do not send CLs removing the interior tags from such phrases.

text/template
-

- TODO: https://golang.org/cl/254257: allow newlines inside action delimiters +

+ Newlines characters are now allowed inside action delimiters, + permitting actions to span multiple lines.

From 4ef78b09c9ea54019e13fd19b2368960b155399f Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Tue, 1 Dec 2020 14:03:54 +0100 Subject: [PATCH 065/212] doc/go1.16: add runtime/debug changes to release notes For #40700 Fixes #42912 Change-Id: Ifd36950136db1fc93a8de76a2717a473210418b1 Reviewed-on: https://go-review.googlesource.com/c/go/+/274473 Trust: Alberto Donizetti Reviewed-by: Keith Randall Reviewed-by: Dmitri Shuralyov --- doc/go1.16.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 3545632ea4..0c1fe5b381 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -663,7 +663,10 @@ Do not send CLs removing the interior tags from such phrases.
runtime/debug

- TODO: https://golang.org/cl/249677: provide Addr method for errors from SetPanicOnFault + The runtime.Error values + used when SetPanicOnFault is enabled may now have an + Addr method. If that method exists, it returns the memory + address that triggered the fault.

From 212d385a2f723a8dd5e7d2e83efb478ddd139349 Mon Sep 17 00:00:00 2001 From: Michael Fraenkel Date: Sat, 26 Sep 2020 09:20:16 -0600 Subject: [PATCH 066/212] net/http: ignore connection closes once done with the connection Once the connection is put back into the idle pool, the request should not take any action if the connection is closed. Fixes #41600 Change-Id: I5e4ddcdc03cd44f5197ecfbe324638604961de84 Reviewed-on: https://go-review.googlesource.com/c/go/+/257818 Reviewed-by: Brad Fitzpatrick Trust: Damien Neil --- src/net/http/transport.go | 13 ++++++--- src/net/http/transport_test.go | 51 ++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 79b1fc7681..8de0f3a6a0 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -2599,6 +2599,7 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err var respHeaderTimer <-chan time.Time cancelChan := req.Request.Cancel ctxDoneChan := req.Context().Done() + pcClosed := pc.closech for { testHookWaitResLoop() select { @@ -2618,11 +2619,15 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err defer timer.Stop() // prevent leaks respHeaderTimer = timer.C } - case <-pc.closech: - if debugRoundTrip { - req.logf("closech recv: %T %#v", pc.closed, pc.closed) + case <-pcClosed: + pcClosed = nil + // check if we are still using the connection + if pc.t.replaceReqCanceler(req.cancelKey, nil) { + if debugRoundTrip { + req.logf("closech recv: %T %#v", pc.closed, pc.closed) + } + return nil, pc.mapRoundTripError(req, startBytesWritten, pc.closed) } - return nil, pc.mapRoundTripError(req, startBytesWritten, pc.closed) case <-respHeaderTimer: if debugRoundTrip { req.logf("timeout waiting for response headers.") diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index 9086507d57..f22b798035 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -6433,3 +6433,54 @@ func TestErrorWriteLoopRace(t *testing.T) { testTransportRace(req) } } + +// Issue 41600 +// Test that a new request which uses the connection of an active request +// cannot cause it to be canceled as well. +func TestCancelRequestWhenSharingConnection(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, req *Request) { + w.Header().Add("Content-Length", "0") + })) + defer ts.Close() + + client := ts.Client() + transport := client.Transport.(*Transport) + transport.MaxIdleConns = 1 + transport.MaxConnsPerHost = 1 + + var wg sync.WaitGroup + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + + for i := 0; i < 10; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for ctx.Err() == nil { + reqctx, reqcancel := context.WithCancel(ctx) + go reqcancel() + req, _ := NewRequestWithContext(reqctx, "GET", ts.URL, nil) + res, err := client.Do(req) + if err == nil { + res.Body.Close() + } + } + }() + } + + for ctx.Err() == nil { + req, _ := NewRequest("GET", ts.URL, nil) + if res, err := client.Do(req); err != nil { + t.Errorf("unexpected: %p %v", req, err) + break + } else { + res.Body.Close() + } + } + + cancel() + wg.Wait() +} From 50b16f9de590822a04ec8d6cbac476366c1bde32 Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sat, 24 Oct 2020 00:40:41 +0000 Subject: [PATCH 067/212] net/http: allow upgrading non keepalive connections If one was using http.Transport with DisableKeepAlives and trying to upgrade a connection against net/http's Server, the Server would not allow a "Connection: Upgrade" header to be written and instead override it to "Connection: Close" which would break the handshake. This change ensures net/http's Server does not override the connection header for successful protocol switch responses. Fixes #36381. Change-Id: I882aad8539e6c87ff5f37c20e20b3a7fa1a30357 GitHub-Last-Rev: dc0de83201dc26236527b68bd49dffc53dd0389b GitHub-Pull-Request: golang/go#36382 Reviewed-on: https://go-review.googlesource.com/c/go/+/213277 Trust: Emmanuel Odeke Trust: Brad Fitzpatrick Reviewed-by: Brad Fitzpatrick --- src/net/http/response.go | 16 ++++++++---- src/net/http/serve_test.go | 53 ++++++++++++++++++++++++++++++++++++++ src/net/http/server.go | 8 +++++- 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/net/http/response.go b/src/net/http/response.go index 72812f0642..b95abae646 100644 --- a/src/net/http/response.go +++ b/src/net/http/response.go @@ -352,10 +352,16 @@ func (r *Response) bodyIsWritable() bool { return ok } -// isProtocolSwitch reports whether r is a response to a successful -// protocol upgrade. +// isProtocolSwitch reports whether the response code and header +// indicate a successful protocol upgrade response. func (r *Response) isProtocolSwitch() bool { - return r.StatusCode == StatusSwitchingProtocols && - r.Header.Get("Upgrade") != "" && - httpguts.HeaderValuesContainsToken(r.Header["Connection"], "Upgrade") + return isProtocolSwitchResponse(r.StatusCode, r.Header) +} + +// isProtocolSwitchResponse reports whether the response code and +// response header indicate a successful protocol upgrade response. +func isProtocolSwitchResponse(code int, h Header) bool { + return code == StatusSwitchingProtocols && + h.Get("Upgrade") != "" && + httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") } diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index ba54b31a29..b1bf8e6c5e 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -6448,3 +6448,56 @@ func BenchmarkResponseStatusLine(b *testing.B) { } }) } +func TestDisableKeepAliveUpgrade(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + + setParallel(t) + defer afterTest(t) + + s := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) { + w.Header().Set("Connection", "Upgrade") + w.Header().Set("Upgrade", "someProto") + w.WriteHeader(StatusSwitchingProtocols) + c, _, err := w.(Hijacker).Hijack() + if err != nil { + return + } + defer c.Close() + + io.Copy(c, c) + })) + s.Config.SetKeepAlivesEnabled(false) + s.Start() + defer s.Close() + + cl := s.Client() + cl.Transport.(*Transport).DisableKeepAlives = true + + resp, err := cl.Get(s.URL) + if err != nil { + t.Fatalf("failed to perform request: %v", err) + } + defer resp.Body.Close() + + rwc, ok := resp.Body.(io.ReadWriteCloser) + if !ok { + t.Fatalf("Response.Body is not a io.ReadWriteCloser: %T", resp.Body) + } + + _, err = rwc.Write([]byte("hello")) + if err != nil { + t.Fatalf("failed to write to body: %v", err) + } + + b := make([]byte, 5) + _, err = io.ReadFull(rwc, b) + if err != nil { + t.Fatalf("failed to read from body: %v", err) + } + + if string(b) != "hello" { + t.Fatalf("unexpected value read from body:\ngot: %q\nwant: %q", b, "hello") + } +} diff --git a/src/net/http/server.go b/src/net/http/server.go index 6c7d281705..102e893d5f 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -1468,7 +1468,13 @@ func (cw *chunkWriter) writeHeader(p []byte) { return } - if w.closeAfterReply && (!keepAlivesEnabled || !hasToken(cw.header.get("Connection"), "close")) { + // Only override the Connection header if it is not a successful + // protocol switch response and if KeepAlives are not enabled. + // See https://golang.org/issue/36381. + delConnectionHeader := w.closeAfterReply && + (!keepAlivesEnabled || !hasToken(cw.header.get("Connection"), "close")) && + !isProtocolSwitchResponse(w.status, header) + if delConnectionHeader { delHeader("Connection") if w.req.ProtoAtLeast(1, 1) { setHeader.connection = "close" From 933ce97bbae311b299d342c38df81165334cea37 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 1 Dec 2020 13:51:17 -0500 Subject: [PATCH 068/212] cmd/go: don't print deprecation notice for 'go get exe' It's difficult for module authors to provide installation instructions that work in both Go 1.15 and 1.16. We'll wait until 1.17 to print a deprecation warning for installing executables with 'go get'. Fixes #42885 Change-Id: I835b447e83e760f48fd664e8a117749e0cb59f83 Reviewed-on: https://go-review.googlesource.com/c/go/+/274552 Trust: Jay Conrod Run-TryBot: Bryan C. Mills Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/modget/get.go | 29 ++----------------- .../script/mod_get_deprecate_install.txt | 22 -------------- 2 files changed, 3 insertions(+), 48 deletions(-) delete mode 100644 src/cmd/go/testdata/script/mod_get_deprecate_install.txt diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index ecb0142524..e5f55879ee 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -436,32 +436,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { work.BuildInit() pkgs := load.PackagesForBuild(ctx, pkgPatterns) work.InstallPackages(ctx, pkgPatterns, pkgs) - - haveExe := false - for _, pkg := range pkgs { - if pkg.Name == "main" { - haveExe = true - break - } - } - if haveExe { - fmt.Fprint(os.Stderr, "go get: installing executables with 'go get' in module mode is deprecated.") - var altMsg string - if modload.HasModRoot() { - altMsg = ` - To adjust dependencies of the current module, use 'go get -d'. - To install using requirements of the current module, use 'go install'. - To install ignoring the current module, use 'go install' with a version, - like 'go install example.com/cmd@latest'. -` - } else { - altMsg = "\n\tUse 'go install pkg@version' instead.\n" - } - fmt.Fprint(os.Stderr, altMsg) - fmt.Fprint(os.Stderr, "\tSee 'go help get' and 'go help install' for more information.\n") - } - // TODO(golang.org/issue/40276): link to HTML documentation explaining - // what's changing and gives more examples. + // TODO(#40276): After Go 1.16, print a deprecation notice when building + // and installing main packages. 'go install pkg' or + // 'go install pkg@version' should be used instead. } if !modload.HasModRoot() { diff --git a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt deleted file mode 100644 index 7f5bcad410..0000000000 --- a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt +++ /dev/null @@ -1,22 +0,0 @@ -[short] skip - -env GO111MODULE=on - -# 'go get' outside a module with an executable prints a deprecation message. -go get example.com/cmd/a -stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$' -stderr 'Use ''go install pkg@version'' instead.' - - -go mod init m - -# 'go get' inside a module with a non-main package does not print a message. -# This will stop building in the future, but it's the command we want to use. -go get rsc.io/quote -! stderr deprecated - -# 'go get' inside a module with an executable prints a different -# deprecation message. -go get example.com/cmd/a -stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$' -stderr 'To adjust dependencies of the current module, use ''go get -d''' From 20e251864b7caa1b863814fdf6c26280e1b669b3 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 1 Dec 2020 15:10:03 -0500 Subject: [PATCH 069/212] cmd: update golang.org/x/mod to v0.4.0 CL 269357 is the only difference between the pseudo-version we were using and v0.4.0. Change-Id: If15326bda51e04b47130429b818bfe2facaee03d Reviewed-on: https://go-review.googlesource.com/c/go/+/274593 Trust: Jay Conrod Run-TryBot: Jay Conrod Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 ++-- src/cmd/vendor/golang.org/x/mod/semver/semver.go | 3 +++ src/cmd/vendor/modules.txt | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 6f55b2d1c8..bfee2c7f06 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -7,7 +7,7 @@ require ( github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 // indirect golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 + golang.org/x/mod v0.4.0 golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 // indirect golang.org/x/tools v0.0.0-20201110201400-7099162a900a ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 8775b754d8..7a743d9f73 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -15,8 +15,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 h1:xUIPaMhvROX9dhPvRCenIJtU78+lbEenGbgqB5hfHCQ= -golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= diff --git a/src/cmd/vendor/golang.org/x/mod/semver/semver.go b/src/cmd/vendor/golang.org/x/mod/semver/semver.go index 2988e3cf9c..4338f35177 100644 --- a/src/cmd/vendor/golang.org/x/mod/semver/semver.go +++ b/src/cmd/vendor/golang.org/x/mod/semver/semver.go @@ -138,6 +138,9 @@ func Compare(v, w string) int { // Max canonicalizes its arguments and then returns the version string // that compares greater. +// +// Deprecated: use Compare instead. In most cases, returning a canonicalized +// version is not expected or desired. func Max(v, w string) string { v = Canonical(v) w = Canonical(w) diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index f20b6b2be1..21bd6bfe48 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -29,7 +29,7 @@ golang.org/x/arch/x86/x86asm golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 golang.org/x/crypto/ssh/terminal -# golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 +# golang.org/x/mod v0.4.0 ## explicit golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile From 7430266af4f951df3c113f2c817bc600650e2295 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Sat, 21 Nov 2020 21:33:18 -0500 Subject: [PATCH 070/212] cmd/internal/codesign: new package On macOS/ARM64, the kernel requires that binaries must have a valid code signature to run. The C toolchain code-signs the binary at link time. We do the same. It is more subtle for Go because we stamp the buildid after linking. As the signature contains hashes of the entire file (except the signature itself), we must (re)generate the signature after stamping the buildid. This CL adds a new codesign package, which provides functionality to generate the code signature. It is a separate internal package so it can be used both in the linker and by the go command. The next CLs will add code-signing to the linker and the go command. Updates #38485, #42684. Change-Id: Id46801a6665beebaab0eb413ff2e64c5b9467059 Reviewed-on: https://go-review.googlesource.com/c/go/+/272254 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Austin Clements Reviewed-by: Than McIntosh --- src/cmd/dist/buildtool.go | 1 + src/cmd/internal/codesign/codesign.go | 268 ++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 src/cmd/internal/codesign/codesign.go diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 37b3d45977..e7bedfb84e 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -53,6 +53,7 @@ var bootstrapDirs = []string{ "cmd/compile/internal/x86", "cmd/compile/internal/wasm", "cmd/internal/bio", + "cmd/internal/codesign", "cmd/internal/gcprog", "cmd/internal/dwarf", "cmd/internal/edit", diff --git a/src/cmd/internal/codesign/codesign.go b/src/cmd/internal/codesign/codesign.go new file mode 100644 index 0000000000..0517a10640 --- /dev/null +++ b/src/cmd/internal/codesign/codesign.go @@ -0,0 +1,268 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package codesign provides basic functionalities for +// ad-hoc code signing of Mach-O files. +// +// This is not a general tool for code-signing. It is made +// specifically for the Go toolchain. It uses the same +// ad-hoc signing algorithm as the Darwin linker. +package codesign + +import ( + "crypto/sha256" + "debug/macho" + "encoding/binary" + "io" +) + +// Code signature layout. +// +// The code signature is a block of bytes that contains +// a SuperBlob, which contains one or more Blobs. For ad-hoc +// signing, a single CodeDirectory Blob suffices. +// +// A SuperBlob starts with its header (the binary representation +// of the SuperBlob struct), followed by a list of (in our case, +// one) Blobs (offset and size). A CodeDirectory Blob starts +// with its head (the binary representation of CodeDirectory struct), +// followed by the identifier (as a C string) and the hashes, at +// the corresponding offsets. +// +// The signature data must be included in the __LINKEDIT segment. +// In the Mach-O file header, an LC_CODE_SIGNATURE load command +// points to the data. + +const ( + pageSizeBits = 12 + pageSize = 1 << pageSizeBits +) + +const LC_CODE_SIGNATURE = 0x1d + +// Constants and struct layouts are from +// https://opensource.apple.com/source/xnu/xnu-4903.270.47/osfmk/kern/cs_blobs.h + +const ( + CSMAGIC_REQUIREMENT = 0xfade0c00 // single Requirement blob + CSMAGIC_REQUIREMENTS = 0xfade0c01 // Requirements vector (internal requirements) + CSMAGIC_CODEDIRECTORY = 0xfade0c02 // CodeDirectory blob + CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 // embedded form of signature data + CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1 // multi-arch collection of embedded signatures + + CSSLOT_CODEDIRECTORY = 0 // slot index for CodeDirectory +) + +const ( + CS_HASHTYPE_SHA1 = 1 + CS_HASHTYPE_SHA256 = 2 + CS_HASHTYPE_SHA256_TRUNCATED = 3 + CS_HASHTYPE_SHA384 = 4 +) + +const ( + CS_EXECSEG_MAIN_BINARY = 0x1 // executable segment denotes main binary + CS_EXECSEG_ALLOW_UNSIGNED = 0x10 // allow unsigned pages (for debugging) + CS_EXECSEG_DEBUGGER = 0x20 // main binary is debugger + CS_EXECSEG_JIT = 0x40 // JIT enabled + CS_EXECSEG_SKIP_LV = 0x80 // skip library validation + CS_EXECSEG_CAN_LOAD_CDHASH = 0x100 // can bless cdhash for execution + CS_EXECSEG_CAN_EXEC_CDHASH = 0x200 // can execute blessed cdhash +) + +type Blob struct { + typ uint32 // type of entry + offset uint32 // offset of entry + // data follows +} + +func (b *Blob) put(out []byte) []byte { + out = put32be(out, b.typ) + out = put32be(out, b.offset) + return out +} + +const blobSize = 2 * 4 + +type SuperBlob struct { + magic uint32 // magic number + length uint32 // total length of SuperBlob + count uint32 // number of index entries following + // blobs []Blob +} + +func (s *SuperBlob) put(out []byte) []byte { + out = put32be(out, s.magic) + out = put32be(out, s.length) + out = put32be(out, s.count) + return out +} + +const superBlobSize = 3 * 4 + +type CodeDirectory struct { + magic uint32 // magic number (CSMAGIC_CODEDIRECTORY) + length uint32 // total length of CodeDirectory blob + version uint32 // compatibility version + flags uint32 // setup and mode flags + hashOffset uint32 // offset of hash slot element at index zero + identOffset uint32 // offset of identifier string + nSpecialSlots uint32 // number of special hash slots + nCodeSlots uint32 // number of ordinary (code) hash slots + codeLimit uint32 // limit to main image signature range + hashSize uint8 // size of each hash in bytes + hashType uint8 // type of hash (cdHashType* constants) + _pad1 uint8 // unused (must be zero) + pageSize uint8 // log2(page size in bytes); 0 => infinite + _pad2 uint32 // unused (must be zero) + scatterOffset uint32 + teamOffset uint32 + _pad3 uint32 + codeLimit64 uint64 + execSegBase uint64 + execSegLimit uint64 + execSegFlags uint64 + // data follows +} + +func (c *CodeDirectory) put(out []byte) []byte { + out = put32be(out, c.magic) + out = put32be(out, c.length) + out = put32be(out, c.version) + out = put32be(out, c.flags) + out = put32be(out, c.hashOffset) + out = put32be(out, c.identOffset) + out = put32be(out, c.nSpecialSlots) + out = put32be(out, c.nCodeSlots) + out = put32be(out, c.codeLimit) + out = put8(out, c.hashSize) + out = put8(out, c.hashType) + out = put8(out, c._pad1) + out = put8(out, c.pageSize) + out = put32be(out, c._pad2) + out = put32be(out, c.scatterOffset) + out = put32be(out, c.teamOffset) + out = put32be(out, c._pad3) + out = put64be(out, c.codeLimit64) + out = put64be(out, c.execSegBase) + out = put64be(out, c.execSegLimit) + out = put64be(out, c.execSegFlags) + return out +} + +const codeDirectorySize = 13*4 + 4 + 4*8 + +// CodeSigCmd is Mach-O LC_CODE_SIGNATURE load command. +type CodeSigCmd struct { + Cmd uint32 // LC_CODE_SIGNATURE + Cmdsize uint32 // sizeof this command (16) + Dataoff uint32 // file offset of data in __LINKEDIT segment + Datasize uint32 // file size of data in __LINKEDIT segment +} + +func FindCodeSigCmd(f *macho.File) (CodeSigCmd, bool) { + get32 := f.ByteOrder.Uint32 + for _, l := range f.Loads { + data := l.Raw() + cmd := get32(data) + if cmd == LC_CODE_SIGNATURE { + return CodeSigCmd{ + cmd, + get32(data[4:]), + get32(data[8:]), + get32(data[12:]), + }, true + } + } + return CodeSigCmd{}, false +} + +func put32be(b []byte, x uint32) []byte { binary.BigEndian.PutUint32(b, x); return b[4:] } +func put64be(b []byte, x uint64) []byte { binary.BigEndian.PutUint64(b, x); return b[8:] } +func put8(b []byte, x uint8) []byte { b[0] = x; return b[1:] } +func puts(b, s []byte) []byte { n := copy(b, s); return b[n:] } + +// Size computes the size of the code signature. +// id is the identifier used for signing (a field in CodeDirectory blob, which +// has no significance in ad-hoc signing). +func Size(codeSize int64, id string) int64 { + nhashes := (codeSize + pageSize - 1) / pageSize + idOff := int64(codeDirectorySize) + hashOff := idOff + int64(len(id)+1) + cdirSz := hashOff + nhashes*sha256.Size + return int64(superBlobSize+blobSize) + cdirSz +} + +// Sign generates an ad-hoc code signature and writes it to out. +// out must have length at least Size(codeSize, id). +// data is the file content without the signature, of size codeSize. +// textOff and textSize is the file offset and size of the text segment. +// isMain is true if this is a main executable. +// id is the identifier used for signing (a field in CodeDirectory blob, which +// has no significance in ad-hoc signing). +func Sign(out []byte, data io.Reader, id string, codeSize, textOff, textSize int64, isMain bool) { + nhashes := (codeSize + pageSize - 1) / pageSize + idOff := int64(codeDirectorySize) + hashOff := idOff + int64(len(id)+1) + sz := Size(codeSize, id) + + // emit blob headers + sb := SuperBlob{ + magic: CSMAGIC_EMBEDDED_SIGNATURE, + length: uint32(sz), + count: 1, + } + blob := Blob{ + typ: CSSLOT_CODEDIRECTORY, + offset: superBlobSize + blobSize, + } + cdir := CodeDirectory{ + magic: CSMAGIC_CODEDIRECTORY, + length: uint32(sz) - (superBlobSize + blobSize), + version: 0x20400, + flags: 0x20002, // adhoc | linkerSigned + hashOffset: uint32(hashOff), + identOffset: uint32(idOff), + nCodeSlots: uint32(nhashes), + codeLimit: uint32(codeSize), + hashSize: sha256.Size, + hashType: CS_HASHTYPE_SHA256, + pageSize: uint8(pageSizeBits), + execSegBase: uint64(textOff), + execSegLimit: uint64(textSize), + } + if isMain { + cdir.execSegFlags = CS_EXECSEG_MAIN_BINARY + } + + outp := out + outp = sb.put(outp) + outp = blob.put(outp) + outp = cdir.put(outp) + + // emit the identifier + outp = puts(outp, []byte(id+"\000")) + + // emit hashes + var buf [pageSize]byte + h := sha256.New() + p := 0 + for p < int(codeSize) { + n, err := io.ReadFull(data, buf[:]) + if err == io.EOF { + break + } + if err != nil && err != io.ErrUnexpectedEOF { + panic(err) + } + if p+n > int(codeSize) { + n = int(codeSize) - p + } + p += n + h.Reset() + h.Write(buf[:n]) + b := h.Sum(nil) + outp = puts(outp, b[:]) + } +} From 7fca39aa05ad3c60abac1ae51ae9847dfbe017d6 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Sat, 21 Nov 2020 17:43:16 -0500 Subject: [PATCH 071/212] cmd/internal/buildid: exclude Mach-O code signature in hash calculation The code signature contains hashes of the entire file (except the signature itself), including the buildid. Therefore, the buildid cannot depend on the signature. Otherwise updating buildid will invalidate the signature, and vice versa. As we cannot change the code-signing algorithm, we can only change buildid calculation. This CL changes the buildid calculation to exclude the Mach-O code signature. So updating code signature after stamping the buildid will not invalidate the buildid. Updates #38485, #42684. Change-Id: I8a9e2e25ca9dc00d9556d13b81652f43bbf6a084 Reviewed-on: https://go-review.googlesource.com/c/go/+/272255 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Austin Clements Reviewed-by: Than McIntosh --- src/cmd/internal/buildid/buildid_test.go | 31 +++++++++++++++ src/cmd/internal/buildid/rewrite.go | 50 ++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/cmd/internal/buildid/buildid_test.go b/src/cmd/internal/buildid/buildid_test.go index 904c2c6f37..e832f9987e 100644 --- a/src/cmd/internal/buildid/buildid_test.go +++ b/src/cmd/internal/buildid/buildid_test.go @@ -11,6 +11,7 @@ import ( "io/ioutil" "os" "reflect" + "strings" "testing" ) @@ -146,3 +147,33 @@ func TestFindAndHash(t *testing.T) { } } } + +func TestExcludedReader(t *testing.T) { + const s = "0123456789abcdefghijklmn" + tests := []struct { + start, end int64 // excluded range + results []string // expected results of reads + }{ + {12, 15, []string{"0123456789", "ab\x00\x00\x00fghij", "klmn"}}, // within one read + {8, 21, []string{"01234567\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00lmn"}}, // across multiple reads + {10, 20, []string{"0123456789", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "klmn"}}, // a whole read + {0, 5, []string{"\x00\x00\x00\x00\x0056789", "abcdefghij", "klmn"}}, // start + {12, 24, []string{"0123456789", "ab\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00"}}, // end + } + p := make([]byte, 10) + for _, test := range tests { + r := &excludedReader{strings.NewReader(s), 0, test.start, test.end} + for _, res := range test.results { + n, err := r.Read(p) + if err != nil { + t.Errorf("read failed: %v", err) + } + if n != len(res) { + t.Errorf("unexpected number of bytes read: want %d, got %d", len(res), n) + } + if string(p[:n]) != res { + t.Errorf("unexpected bytes: want %q, got %q", res, p[:n]) + } + } + } +} diff --git a/src/cmd/internal/buildid/rewrite.go b/src/cmd/internal/buildid/rewrite.go index 5be54552a6..d3d2009d1c 100644 --- a/src/cmd/internal/buildid/rewrite.go +++ b/src/cmd/internal/buildid/rewrite.go @@ -6,7 +6,9 @@ package buildid import ( "bytes" + "cmd/internal/codesign" "crypto/sha256" + "debug/macho" "fmt" "io" ) @@ -26,6 +28,11 @@ func FindAndHash(r io.Reader, id string, bufSize int) (matches []int64, hash [32 zeros := make([]byte, len(id)) idBytes := []byte(id) + // For Mach-O files, we want to exclude the code signature. + // The code signature contains hashes of the whole file (except the signature + // itself), including the buildid. So the buildid cannot contain the signature. + r = excludeMachoCodeSignature(r) + // The strategy is to read the file through buf, looking for id, // but we need to worry about what happens if id is broken up // and returned in parts by two different reads. @@ -89,3 +96,46 @@ func Rewrite(w io.WriterAt, pos []int64, id string) error { } return nil } + +func excludeMachoCodeSignature(r io.Reader) io.Reader { + ra, ok := r.(io.ReaderAt) + if !ok { + return r + } + f, err := macho.NewFile(ra) + if err != nil { + return r + } + cmd, ok := codesign.FindCodeSigCmd(f) + if !ok { + return r + } + return &excludedReader{r, 0, int64(cmd.Dataoff), int64(cmd.Dataoff + cmd.Datasize)} +} + +// excludedReader wraps an io.Reader. Reading from it returns the bytes from +// the underlying reader, except that when the byte offset is within the +// range between start and end, it returns zero bytes. +type excludedReader struct { + r io.Reader + off int64 // current offset + start, end int64 // the range to be excluded (read as zero) +} + +func (r *excludedReader) Read(p []byte) (int, error) { + n, err := r.r.Read(p) + if n > 0 && r.off+int64(n) > r.start && r.off < r.end { + cstart := r.start - r.off + if cstart < 0 { + cstart = 0 + } + cend := r.end - r.off + if cend > int64(n) { + cend = int64(n) + } + zeros := make([]byte, cend-cstart) + copy(p[cstart:cend], zeros) + } + r.off += int64(n) + return n, err +} From 1408d26ccca5f770e29785ddd442523416de2dd6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 1 Dec 2020 11:37:30 -0800 Subject: [PATCH 072/212] [dev.regabi] cmd/compile: cleanup some leftover cruft Just clearing away some scaffolding artifacts from previous refactorings. [git-generate] cd src/cmd/compile/internal/gc rf ' ex { import "cmd/compile/internal/ir" import "cmd/compile/internal/types" var n *ir.Name; n.Name() -> n var f *ir.Func; f.Func() -> f var o types.Object ir.AsNode(o).Sym() -> o.Sym() ir.AsNode(o).Type() -> o.Type() ir.AsNode(o).(*ir.Name) -> o.(*ir.Name) ir.AsNode(o).(*ir.Func) -> o.(*ir.Func) var x ir.Node ir.AsNode(o) != x -> o != x } ' Change-Id: I946ec344bd7ee274900a392da53b95308ceaade4 Reviewed-on: https://go-review.googlesource.com/c/go/+/274592 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/closure.go | 2 +- src/cmd/compile/internal/gc/dcl.go | 10 +++++----- src/cmd/compile/internal/gc/escape.go | 10 +++++----- src/cmd/compile/internal/gc/iexport.go | 4 ++-- src/cmd/compile/internal/gc/init.go | 2 +- src/cmd/compile/internal/gc/main.go | 2 +- src/cmd/compile/internal/gc/noder.go | 2 +- src/cmd/compile/internal/gc/obj.go | 4 ++-- src/cmd/compile/internal/gc/pgen.go | 16 ++++++++-------- src/cmd/compile/internal/gc/reflect.go | 4 ++-- src/cmd/compile/internal/gc/ssa.go | 4 ++-- src/cmd/compile/internal/gc/typecheck.go | 6 +++--- src/cmd/compile/internal/gc/universe.go | 2 +- src/cmd/compile/internal/gc/walk.go | 10 +++++----- 14 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 0ba2858b8b..e33a561bd4 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -437,7 +437,7 @@ func makepartialcall(dot ir.Node, t0 *types.Type, meth *types.Sym) *ir.Func { sym := methodSymSuffix(rcvrtype, meth, "-fm") if sym.Uniq() { - return ir.AsNode(sym.Def).(*ir.Func) + return sym.Def.(*ir.Func) } sym.SetUniq(true) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 3d0bdaec7a..dd59d829fe 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -95,7 +95,7 @@ func declare(n *ir.Name, ctxt ir.Class) { gen = vargen } types.Pushdcl(s) - n.Name().Curfn = Curfn + n.Curfn = Curfn } if ctxt == ir.PAUTO { @@ -113,7 +113,7 @@ func declare(n *ir.Name, ctxt ir.Class) { s.Block = types.Block s.Lastlineno = base.Pos s.Def = n - n.Name().Vargen = int32(gen) + n.Vargen = int32(gen) n.SetClass(ctxt) if ctxt == ir.PFUNC { n.Sym().SetFunc(true) @@ -335,7 +335,7 @@ func colasdefn(left []ir.Node, defn ir.Node) { nnew++ n := NewName(n.Sym()) declare(n, dclcontext) - n.Name().Defn = defn + n.Defn = defn defn.PtrInit().Append(ir.Nod(ir.ODCL, n, nil)) left[i] = n } @@ -438,7 +438,7 @@ func funcarg(n *ir.Field, ctxt ir.Class) { declare(name, ctxt) vargen++ - n.Decl.Name().Vargen = int32(vargen) + n.Decl.Vargen = int32(vargen) } // Same as funcargs, except run over an already constructed TFUNC. @@ -837,7 +837,7 @@ func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bo } f := types.NewField(base.Pos, msym, t) - f.Nname = n.Func().Nname + f.Nname = n.Nname f.SetNointerface(nointerface) mt.Methods().Append(f) diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index b29896e5a4..c139771730 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -1802,8 +1802,8 @@ func addrescapes(n ir.Node) { } // If a closure reference escapes, mark the outer variable as escaping. - if n.Name().IsClosureVar() { - addrescapes(n.Name().Defn) + if n.IsClosureVar() { + addrescapes(n.Defn) break } @@ -1824,7 +1824,7 @@ func addrescapes(n ir.Node) { // then we're analyzing the inner closure but we need to move x to the // heap in f, not in the inner closure. Flip over to f before calling moveToHeap. oldfn := Curfn - Curfn = n.Name().Curfn + Curfn = n.Curfn ln := base.Pos base.Pos = Curfn.Pos() moveToHeap(n) @@ -1893,7 +1893,7 @@ func moveToHeap(n *ir.Name) { // See issue 16095. heapaddr.SetIsOutputParamHeapAddr(true) } - n.Name().Stackcopy = stackcopy + n.Stackcopy = stackcopy // Substitute the stackcopy into the function variable list so that // liveness and other analyses use the underlying stack slot @@ -1920,7 +1920,7 @@ func moveToHeap(n *ir.Name) { // Modify n in place so that uses of n now mean indirection of the heapaddr. n.SetClass(ir.PAUTOHEAP) n.SetOffset(0) - n.Name().Heapaddr = heapaddr + n.Heapaddr = heapaddr n.SetEsc(EscHeap) if base.Flag.LowerM != 0 { base.WarnfAt(n.Pos(), "moved to heap: %v", n) diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 8f50868fc7..2231f493dd 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -395,7 +395,7 @@ func (p *iexporter) stringOff(s string) uint64 { // pushDecl adds n to the declaration work queue, if not already present. func (p *iexporter) pushDecl(n ir.Node) { - if n.Sym() == nil || ir.AsNode(n.Sym().Def) != n && n.Op() != ir.OTYPE { + if n.Sym() == nil || n.Sym().Def != n && n.Op() != ir.OTYPE { base.Fatalf("weird Sym: %v, %v", n, n.Sym()) } @@ -988,7 +988,7 @@ func (w *exportWriter) funcExt(n *ir.Name) { func (w *exportWriter) methExt(m *types.Field) { w.bool(m.Nointerface()) - w.funcExt(ir.AsNode(m.Nname).(*ir.Name)) + w.funcExt(m.Nname.(*ir.Name)) } func (w *exportWriter) linkname(s *types.Sym) { diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go index b5fd2e7c75..e67a032c5d 100644 --- a/src/cmd/compile/internal/gc/init.go +++ b/src/cmd/compile/internal/gc/init.go @@ -60,7 +60,7 @@ func fninit(n []ir.Node) { initializers := lookup("init") fn := dclfunc(initializers, ir.NewFuncType(base.Pos, nil, nil, nil)) for _, dcl := range initTodo.Dcl { - dcl.Name().Curfn = fn + dcl.Curfn = fn } fn.Dcl = append(fn.Dcl, initTodo.Dcl...) initTodo.Dcl = nil diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 718239484b..96031fe511 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -984,7 +984,7 @@ func clearImports() { } func IsAlias(sym *types.Sym) bool { - return sym.Def != nil && ir.AsNode(sym.Def).Sym() != sym + return sym.Def != nil && sym.Def.Sym() != sym } // recordFlags records the specified command-line flags to be placed diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 1340068c72..de7dcda15e 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -1071,7 +1071,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node { if ln.Class() != ir.PPARAMOUT { break } - if ir.AsNode(ln.Sym().Def) != ln { + if ln.Sym().Def != ln { base.Errorf("%s is shadowed during return", ln.Sym().Name) } } diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index f65131417a..21a50257b8 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -220,10 +220,10 @@ func addptabs() { } if n.Type().Kind() == types.TFUNC && n.Class() == ir.PFUNC { // function - ptabs = append(ptabs, ptabEntry{s: s, t: ir.AsNode(s.Def).Type()}) + ptabs = append(ptabs, ptabEntry{s: s, t: s.Def.Type()}) } else { // variable - ptabs = append(ptabs, ptabEntry{s: s, t: types.NewPtr(ir.AsNode(s.Def).Type())}) + ptabs = append(ptabs, ptabEntry{s: s, t: types.NewPtr(s.Def.Type())}) } } } diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index ea294ed66d..1da0929290 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -77,8 +77,8 @@ func cmpstackvarlt(a, b *ir.Name) bool { return a.Offset() < b.Offset() } - if a.Name().Used() != b.Name().Used() { - return a.Name().Used() + if a.Used() != b.Used() { + return a.Used() } ap := a.Type().HasPointers() @@ -87,8 +87,8 @@ func cmpstackvarlt(a, b *ir.Name) bool { return ap } - ap = a.Name().Needzero() - bp = b.Name().Needzero() + ap = a.Needzero() + bp = b.Needzero() if ap != bp { return ap } @@ -115,7 +115,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { // Mark the PAUTO's unused. for _, ln := range fn.Dcl { if ln.Class() == ir.PAUTO { - ln.Name().SetUsed(false) + ln.SetUsed(false) } } @@ -158,7 +158,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { if n.Op() != ir.ONAME || n.Class() != ir.PAUTO { continue } - if !n.Name().Used() { + if !n.Used() { fn.Dcl = fn.Dcl[:i] break } @@ -260,7 +260,7 @@ func compile(fn *ir.Func) { for _, n := range fn.Dcl { switch n.Class() { case ir.PPARAM, ir.PPARAMOUT, ir.PAUTO: - if livenessShouldTrack(n) && n.Name().Addrtaken() { + if livenessShouldTrack(n) && n.Addrtaken() { dtypesym(n.Type()) // Also make sure we allocate a linker symbol // for the stack object data, for the same reason. @@ -447,7 +447,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S } switch n.Class() { case ir.PAUTO: - if !n.Name().Used() { + if !n.Used() { // Text == nil -> generating abstract function if fnsym.Func().Text != nil { base.Fatalf("debuginfo unused node (AllocFrame should truncate fn.Func.Dcl)") diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 4ab3005ce8..06b91ddae6 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -1001,7 +1001,7 @@ func typename(t *types.Type) ir.Node { } n := ir.Nod(ir.OADDR, ir.AsNode(s.Def), nil) - n.SetType(types.NewPtr(ir.AsNode(s.Def).Type())) + n.SetType(types.NewPtr(s.Def.Type())) n.SetTypecheck(1) return n } @@ -1021,7 +1021,7 @@ func itabname(t, itype *types.Type) ir.Node { } n := ir.Nod(ir.OADDR, ir.AsNode(s.Def), nil) - n.SetType(types.NewPtr(ir.AsNode(s.Def).Type())) + n.SetType(types.NewPtr(s.Def.Type())) n.SetTypecheck(1) return n } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 3e020d7b92..60e65e4b11 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -6196,7 +6196,7 @@ func (s byXoffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func emitStackObjects(e *ssafn, pp *Progs) { var vars []ir.Node for _, n := range e.curfn.Dcl { - if livenessShouldTrack(n) && n.Name().Addrtaken() { + if livenessShouldTrack(n) && n.Addrtaken() { vars = append(vars, n) } } @@ -6583,7 +6583,7 @@ func defframe(s *SSAGenState, e *ssafn) { // Iterate through declarations. They are sorted in decreasing Xoffset order. for _, n := range e.curfn.Dcl { - if !n.Name().Needzero() { + if !n.Needzero() { continue } if n.Class() != ir.PAUTO { diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index f120b44413..20ef3fc70a 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2493,7 +2493,7 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field { pll = ll ll = ll.Left() } - if pll.Implicit() && ll.Type().IsPtr() && ll.Type().Sym() != nil && ir.AsNode(ll.Type().Sym().Def) != nil && ir.AsNode(ll.Type().Sym().Def).Op() == ir.OTYPE { + if pll.Implicit() && ll.Type().IsPtr() && ll.Type().Sym() != nil && ll.Type().Sym().Def != nil && ir.AsNode(ll.Type().Sym().Def).Op() == ir.OTYPE { // It is invalid to automatically dereference a named pointer type when selecting a method. // Make n.Left == ll to clarify error message. n.SetLeft(ll) @@ -3369,7 +3369,7 @@ func typecheckfunc(n *ir.Func) { for _, ln := range n.Dcl { if ln.Op() == ir.ONAME && (ln.Class() == ir.PPARAM || ln.Class() == ir.PPARAMOUT) { - ln.Name().Decldepth = 1 + ln.Decldepth = 1 } } @@ -3923,7 +3923,7 @@ func curpkg() *types.Pkg { // referenced by expression n, which must be a method selector, // method expression, or method value. func methodExprName(n ir.Node) *ir.Name { - name, _ := ir.AsNode(methodExprFunc(n).Nname).(*ir.Name) + name, _ := methodExprFunc(n).Nname.(*ir.Name) return name } diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 49e50734c6..b554674fbc 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -358,5 +358,5 @@ func finishUniverse() { nodfp = NewName(lookup(".fp")) nodfp.SetType(types.Types[types.TINT32]) nodfp.SetClass(ir.PPARAM) - nodfp.Name().SetUsed(true) + nodfp.SetUsed(true) } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index b3af353c3f..be6f1539b9 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -43,16 +43,16 @@ func walk(fn *ir.Func) { // Propagate the used flag for typeswitch variables up to the NONAME in its definition. for _, ln := range fn.Dcl { - if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) && ln.Name().Defn != nil && ln.Name().Defn.Op() == ir.OTYPESW && ln.Name().Used() { - ln.Name().Defn.Left().Name().SetUsed(true) + if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) && ln.Defn != nil && ln.Defn.Op() == ir.OTYPESW && ln.Used() { + ln.Defn.Left().Name().SetUsed(true) } } for _, ln := range fn.Dcl { - if ln.Op() != ir.ONAME || (ln.Class() != ir.PAUTO && ln.Class() != ir.PAUTOHEAP) || ln.Sym().Name[0] == '&' || ln.Name().Used() { + if ln.Op() != ir.ONAME || (ln.Class() != ir.PAUTO && ln.Class() != ir.PAUTOHEAP) || ln.Sym().Name[0] == '&' || ln.Used() { continue } - if defn := ln.Name().Defn; defn != nil && defn.Op() == ir.OTYPESW { + if defn := ln.Defn; defn != nil && defn.Op() == ir.OTYPESW { if defn.Left().Name().Used() { continue } @@ -91,7 +91,7 @@ func paramoutheap(fn *ir.Func) bool { for _, ln := range fn.Dcl { switch ln.Class() { case ir.PPARAMOUT: - if isParamStackCopy(ln) || ln.Name().Addrtaken() { + if isParamStackCopy(ln) || ln.Addrtaken() { return true } From 283d65413db75edbc4691c4fecf23228509436f0 Mon Sep 17 00:00:00 2001 From: Kevin Burke Date: Fri, 27 Nov 2020 13:55:27 -0800 Subject: [PATCH 073/212] encoding/json: revert "add "json: " prefix to SyntaxError messages" This reverts commit 6af088bfc66c13143c9ef46b4cf0805df77a8fbe. Reason for revert: Broke many tests inside Google which implies many tests were broken outside of Google as well. The tests may be brittle but still would require work to change and it's not clear it's worth the benefit. Updates #36221 Fixes #42675 Change-Id: Id3a14eb37e7119f5abe50e80dfbf120fdc44db72 Reviewed-on: https://go-review.googlesource.com/c/go/+/273747 Run-TryBot: Joe Tsai TryBot-Result: Go Bot Reviewed-by: Russ Cox Reviewed-by: Joe Tsai Trust: Joe Tsai --- doc/go1.16.html | 6 ------ src/cmd/go/testdata/script/mod_proxy_invalid.txt | 4 ++-- src/cmd/go/testdata/script/mod_query_empty.txt | 2 +- src/encoding/json/scanner.go | 2 +- src/html/template/escape_test.go | 2 +- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 0c1fe5b381..ffdbc97c62 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -454,12 +454,6 @@ Do not send CLs removing the interior tags from such phrases.
encoding/json
-

- The error message for - SyntaxError - now begins with "json: ", matching the other errors in the package. -

-

TODO: https://golang.org/cl/234818: allow semicolon in field key / struct tag

diff --git a/src/cmd/go/testdata/script/mod_proxy_invalid.txt b/src/cmd/go/testdata/script/mod_proxy_invalid.txt index b9418b4df1..6427cc1527 100644 --- a/src/cmd/go/testdata/script/mod_proxy_invalid.txt +++ b/src/cmd/go/testdata/script/mod_proxy_invalid.txt @@ -2,7 +2,7 @@ env GO111MODULE=on env GOPROXY=$GOPROXY/invalid ! go list -m rsc.io/quote@latest -stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": json: invalid character ''i'' looking for beginning of value$' +stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' ! go list -m rsc.io/quote@1.5.2 -stderr '^go list -m: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": json: invalid character ''i'' looking for beginning of value$' +stderr '^go list -m: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' diff --git a/src/cmd/go/testdata/script/mod_query_empty.txt b/src/cmd/go/testdata/script/mod_query_empty.txt index 1f13d7ad69..f8b6e3e97e 100644 --- a/src/cmd/go/testdata/script/mod_query_empty.txt +++ b/src/cmd/go/testdata/script/mod_query_empty.txt @@ -40,7 +40,7 @@ env GOPROXY=file:///$WORK/gatekeeper chmod 0000 $WORK/gatekeeper/example.com/join/subpkg/@latest cp go.mod.orig go.mod ! go get -d example.com/join/subpkg -stderr 'go get: module example.com/join/subpkg: (invalid response from proxy ".+": json: invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' +stderr 'go get: module example.com/join/subpkg: (invalid response from proxy ".+": invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' -- go.mod.orig -- module example.com/othermodule diff --git a/src/encoding/json/scanner.go b/src/encoding/json/scanner.go index c3f5f6372d..9dc1903e2d 100644 --- a/src/encoding/json/scanner.go +++ b/src/encoding/json/scanner.go @@ -47,7 +47,7 @@ type SyntaxError struct { Offset int64 // error occurred after reading Offset bytes } -func (e *SyntaxError) Error() string { return "json: " + e.msg } +func (e *SyntaxError) Error() string { return e.msg } // A scanner is a JSON scanning state machine. // Callers call scan.reset and then pass bytes in one at a time diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go index b6031ea60a..fbc84a7592 100644 --- a/src/html/template/escape_test.go +++ b/src/html/template/escape_test.go @@ -243,7 +243,7 @@ func TestEscape(t *testing.T) { { "badMarshaler", `
From 78e442ea79294480c28e44b21702c6452e704110 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Tue, 1 Dec 2020 14:59:23 -0800 Subject: [PATCH 097/212] doc/go1.16: add encoding/json note for tag change For #40700 Fixes #42898 Change-Id: I652657ff8d6cce20bf868f0b1101d723d3f704d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/274614 Trust: Joe Tsai Reviewed-by: Dmitri Shuralyov --- doc/go1.16.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 2132cbc9c1..086557ca48 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -456,7 +456,11 @@ Do not send CLs removing the interior tags from such phrases.
encoding/json

- TODO: https://golang.org/cl/234818: allow semicolon in field key / struct tag + The json struct field tags understood by + Marshal, + Unmarshal, + and related functionality now permit semicolon characters within + a JSON object name for a Go struct field.

From da54dfb6a1f3bef827b9ec3780c98fde77a97d11 Mon Sep 17 00:00:00 2001 From: KimMachineGun Date: Sun, 29 Nov 2020 08:18:12 +0000 Subject: [PATCH 098/212] doc/go1.16: document new behavior of asn1.Unmarshal on invalid argument For #41509 Change-Id: Ie761c428710d15848cb80ffd2d85de747113f2d4 GitHub-Last-Rev: 05541624593d945d82b6f4cfae1461654eabea7b GitHub-Pull-Request: golang/go#42315 Reviewed-on: https://go-review.googlesource.com/c/go/+/267057 Trust: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor --- doc/go1.16.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/go1.16.html b/doc/go1.16.html index 086557ca48..f8b2c3f371 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -453,6 +453,18 @@ Do not send CLs removing the interior tags from such phrases. +
encoding/asn1
+
+

+ Unmarshal and + UnmarshalWithParams + now return an error instead of panic when the argument is not + a pointer or is nil. This change matches the behavior of other + encoding packages such as encoding/json. +

+
+
+
encoding/json

From 5a3b6796cdb1833929805262b6f843c0e82fa7e1 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 1 Dec 2020 20:51:18 -0800 Subject: [PATCH 099/212] [dev.regabi] cmd/compile: remove extra typ field in Name struct Noticed the typ field was duplicated, since it is also in miniExpr inside Name. Also clarified the comments for Func, now that it is actually the ODCLFUNC node. Change-Id: Ia483a0ad34bb409cd92c43d4ae0a6852f9e4f644 Reviewed-on: https://go-review.googlesource.com/c/go/+/274619 Run-TryBot: Dan Scales TryBot-Result: Go Bot Trust: Dan Scales Reviewed-by: Russ Cox --- src/cmd/compile/internal/ir/func.go | 15 ++++++++------- src/cmd/compile/internal/ir/name.go | 1 - src/cmd/compile/internal/ir/sizeof_test.go | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 3fc8597ef0..98830fb502 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -17,13 +17,14 @@ import ( // // There are multiple nodes that represent a Func in the IR. // -// The ONAME node (Func.Name) is used for plain references to it. -// The ODCLFUNC node (Func.Decl) is used for its declaration code. -// The OCLOSURE node (Func.Closure) is used for a reference to a +// The ONAME node (Func.Nname) is used for plain references to it. +// The ODCLFUNC node (the Func itself) is used for its declaration code. +// The OCLOSURE node (Func.OClosure) is used for a reference to a // function literal. // -// A Func for an imported function will have only an ONAME node. -// A declared function or method has an ONAME and an ODCLFUNC. +// An imported function will have an ONAME node which points to a Func +// with an empty body. +// A declared function or method has an ODCLFUNC (the Func itself) and an ONAME. // A function literal is represented directly by an OCLOSURE, but it also // has an ODCLFUNC (and a matching ONAME) representing the compiled // underlying form of the closure, which accesses the captured variables @@ -44,8 +45,8 @@ import ( // the method name is stored in Sym instead of Right. // Each OCALLPART ends up being implemented as a new // function, a bit like a closure, with its own ODCLFUNC. -// The OCALLPART has uses n.Func to record the linkage to -// the generated ODCLFUNC (as n.Func.Decl), but there is no +// The OCALLPART uses n.Func to record the linkage to +// the generated ODCLFUNC, but there is no // pointer from the Func back to the OCALLPART. type Func struct { miniNode diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 3c62800ad3..1d886bb9a1 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -21,7 +21,6 @@ type Name struct { flags bitset16 pragma PragmaFlag // int16 sym *types.Sym - typ *types.Type fn *Func offset int64 val constant.Value diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go index 4a133cb999..181f1462fe 100644 --- a/src/cmd/compile/internal/ir/sizeof_test.go +++ b/src/cmd/compile/internal/ir/sizeof_test.go @@ -21,7 +21,7 @@ func TestSizeof(t *testing.T) { _64bit uintptr // size on 64bit platforms }{ {Func{}, 168, 288}, - {Name{}, 128, 224}, + {Name{}, 124, 216}, } for _, tt := range tests { From 00e572779077737d409ed57194510ec42c520b34 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 2 Dec 2020 14:40:48 +0700 Subject: [PATCH 100/212] [dev.regabi] cmd/compile: remove okAs The check for blank in okAs is redundant with what its callers already done, so just inline the conversion in callers side instead. Passes toolstash-check. Change-Id: I606105e2d2cf8e80214722a13c3101c464d20d82 Reviewed-on: https://go-review.googlesource.com/c/go/+/274793 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/order.go | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 352e9c473b..7816e684dc 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -936,7 +936,7 @@ func (o *Order) stmt(n ir.Node) { } tmp := o.newTemp(types.Types[types.TBOOL], false) - as := okas(ok, tmp) + as := ir.Nod(ir.OAS, ok, conv(tmp, ok.Type())) as = typecheck(as, ctxStmt) n2.PtrInit().Append(as) ok = tmp @@ -1382,15 +1382,6 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { return n } -// okas creates and returns an assignment of val to ok, -// including an explicit conversion if necessary. -func okas(ok, val ir.Node) ir.Node { - if !ir.IsBlank(ok) { - val = conv(val, ok.Type()) - } - return ir.Nod(ir.OAS, ok, val) -} - // as2 orders OAS2XXXX nodes. It creates temporaries to ensure left-to-right assignment. // The caller should order the right-hand side of the assignment before calling order.as2. // It rewrites, @@ -1442,7 +1433,7 @@ func (o *Order) okAs2(n ir.Node) { n.List().SetFirst(tmp1) } if tmp2 != nil { - r := okas(n.List().Second(), tmp2) + r := ir.Nod(ir.OAS, n.List().Second(), conv(tmp2, n.List().Second().Type())) r = typecheck(r, ctxStmt) o.mapAssign(r) n.List().SetSecond(tmp2) From d0c0dc682c1fb15241d84df11715e706a5bc0da7 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 3 Dec 2020 11:07:27 +0100 Subject: [PATCH 101/212] doc/go1.16: document os package changes For #39444 For #40700 Fixes #42908 Change-Id: Idae35adecd79e9d7d207f9d78cb009a980e5c8a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/274477 Trust: Tobias Klauser Reviewed-by: Russ Cox --- doc/go1.16.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index f8b2c3f371..6618240ed1 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -618,7 +618,10 @@ Do not send CLs removing the interior tags from such phrases.

os

- TODO: https://golang.org/cl/242998: export errFinished as ErrProcessDone + Process.Signal now + returns ErrProcessDone + instead of the unexported errFinished when the process has + already finished.

From 07cba70d5794747044ce5f2f3b34de139193e2a5 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Mon, 16 Nov 2020 21:28:26 -0500 Subject: [PATCH 102/212] cmd/compile, runtime: use __msan_memmove for moving data, split msanread to fields Currently, for data moving, we generate an msanread of the source, followed by an msanwrite of the destination. msanread checks the source is initialized. This has a problem: if the source is an aggregate type containing alignment paddings, the padding bytes may not be thought as initialized by MSAN. If we copy the aggregate type by value, if it counts as a read, MSAN reports using uninitialized data. This CL changes it to use __msan_memmove for data copying, which tells MSAN to propagate initialized-ness but not check for it. Caveat: technically __msan_memmove is not a public API of MSAN, although the C compiler does generate direct calls to it. Also, when instrumenting a load of a struct, split the instrumentation to fields, instead of generating an msanread for the whole struct. This skips padding bytes, which may not be considered initialized in MSAN. Fixes #42820. Change-Id: Id861c8bbfd94cfcccefcc58eaf9e4eb43b4d85c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/270859 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Austin Clements --- misc/cgo/testsanitizers/msan_test.go | 1 + misc/cgo/testsanitizers/testdata/msan7.go | 38 +++++++++ src/cmd/compile/internal/gc/builtin.go | 42 +++++----- .../compile/internal/gc/builtin/runtime.go | 1 + src/cmd/compile/internal/gc/go.go | 1 + src/cmd/compile/internal/gc/ssa.go | 83 ++++++++++++++++--- src/runtime/msan.go | 6 +- src/runtime/msan_amd64.s | 9 ++ src/runtime/msan_arm64.s | 10 +++ 9 files changed, 158 insertions(+), 33 deletions(-) create mode 100644 misc/cgo/testsanitizers/testdata/msan7.go diff --git a/misc/cgo/testsanitizers/msan_test.go b/misc/cgo/testsanitizers/msan_test.go index 88b90d3d70..5e2f9759ba 100644 --- a/misc/cgo/testsanitizers/msan_test.go +++ b/misc/cgo/testsanitizers/msan_test.go @@ -28,6 +28,7 @@ func TestMSAN(t *testing.T) { {src: "msan4.go"}, {src: "msan5.go"}, {src: "msan6.go"}, + {src: "msan7.go"}, {src: "msan_fail.go", wantErr: true}, } for _, tc := range cases { diff --git a/misc/cgo/testsanitizers/testdata/msan7.go b/misc/cgo/testsanitizers/testdata/msan7.go new file mode 100644 index 0000000000..2f29fd21b2 --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/msan7.go @@ -0,0 +1,38 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +// Test passing C struct to exported Go function. + +/* +#include +#include + +// T is a C struct with alignment padding after b. +// The padding bytes are not considered initialized by MSAN. +// It is big enough to be passed on stack in C ABI (and least +// on AMD64). +typedef struct { char b; uintptr_t x, y; } T; + +extern void F(T); + +// Use weak as a hack to permit defining a function even though we use export. +void CF(int x) __attribute__ ((weak)); +void CF(int x) { + T *t = malloc(sizeof(T)); + t->b = (char)x; + t->x = x; + t->y = x; + F(*t); +} +*/ +import "C" + +//export F +func F(t C.T) { println(t.b, t.x, t.y) } + +func main() { + C.CF(C.int(0)) +} diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go index fd95b657b2..e04f23e229 100644 --- a/src/cmd/compile/internal/gc/builtin.go +++ b/src/cmd/compile/internal/gc/builtin.go @@ -184,16 +184,17 @@ var runtimeDecls = [...]struct { {"racewriterange", funcTag, 121}, {"msanread", funcTag, 121}, {"msanwrite", funcTag, 121}, - {"checkptrAlignment", funcTag, 122}, - {"checkptrArithmetic", funcTag, 124}, - {"libfuzzerTraceCmp1", funcTag, 126}, - {"libfuzzerTraceCmp2", funcTag, 128}, - {"libfuzzerTraceCmp4", funcTag, 129}, - {"libfuzzerTraceCmp8", funcTag, 130}, - {"libfuzzerTraceConstCmp1", funcTag, 126}, - {"libfuzzerTraceConstCmp2", funcTag, 128}, - {"libfuzzerTraceConstCmp4", funcTag, 129}, - {"libfuzzerTraceConstCmp8", funcTag, 130}, + {"msanmove", funcTag, 122}, + {"checkptrAlignment", funcTag, 123}, + {"checkptrArithmetic", funcTag, 125}, + {"libfuzzerTraceCmp1", funcTag, 127}, + {"libfuzzerTraceCmp2", funcTag, 129}, + {"libfuzzerTraceCmp4", funcTag, 130}, + {"libfuzzerTraceCmp8", funcTag, 131}, + {"libfuzzerTraceConstCmp1", funcTag, 127}, + {"libfuzzerTraceConstCmp2", funcTag, 129}, + {"libfuzzerTraceConstCmp4", funcTag, 130}, + {"libfuzzerTraceConstCmp8", funcTag, 131}, {"x86HasPOPCNT", varTag, 6}, {"x86HasSSE41", varTag, 6}, {"x86HasFMA", varTag, 6}, @@ -202,7 +203,7 @@ var runtimeDecls = [...]struct { } func runtimeTypes() []*types.Type { - var typs [131]*types.Type + var typs [132]*types.Type typs[0] = types.Bytetype typs[1] = types.NewPtr(typs[0]) typs[2] = types.Types[TANY] @@ -325,14 +326,15 @@ func runtimeTypes() []*types.Type { typs[119] = functype(nil, []*Node{anonfield(typs[65])}, []*Node{anonfield(typs[20])}) typs[120] = functype(nil, []*Node{anonfield(typs[26]), anonfield(typs[26])}, []*Node{anonfield(typs[26])}) typs[121] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[5])}, nil) - typs[122] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil) - typs[123] = types.NewSlice(typs[7]) - typs[124] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[123])}, nil) - typs[125] = types.Types[TUINT8] - typs[126] = functype(nil, []*Node{anonfield(typs[125]), anonfield(typs[125])}, nil) - typs[127] = types.Types[TUINT16] - typs[128] = functype(nil, []*Node{anonfield(typs[127]), anonfield(typs[127])}, nil) - typs[129] = functype(nil, []*Node{anonfield(typs[65]), anonfield(typs[65])}, nil) - typs[130] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, nil) + typs[122] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[5]), anonfield(typs[5])}, nil) + typs[123] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil) + typs[124] = types.NewSlice(typs[7]) + typs[125] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[124])}, nil) + typs[126] = types.Types[TUINT8] + typs[127] = functype(nil, []*Node{anonfield(typs[126]), anonfield(typs[126])}, nil) + typs[128] = types.Types[TUINT16] + typs[129] = functype(nil, []*Node{anonfield(typs[128]), anonfield(typs[128])}, nil) + typs[130] = functype(nil, []*Node{anonfield(typs[65]), anonfield(typs[65])}, nil) + typs[131] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, nil) return typs[:] } diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go index aac2de38c6..acb69c7b28 100644 --- a/src/cmd/compile/internal/gc/builtin/runtime.go +++ b/src/cmd/compile/internal/gc/builtin/runtime.go @@ -237,6 +237,7 @@ func racewriterange(addr, size uintptr) // memory sanitizer func msanread(addr, size uintptr) func msanwrite(addr, size uintptr) +func msanmove(dst, src, size uintptr) func checkptrAlignment(unsafe.Pointer, *byte, uintptr) func checkptrArithmetic(unsafe.Pointer, []unsafe.Pointer) diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index da6b6d6e72..274930bd15 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -309,6 +309,7 @@ var ( growslice, msanread, msanwrite, + msanmove, newobject, newproc, panicdivide, diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 0b38e70cd2..65b9291b76 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -79,6 +79,7 @@ func initssaconfig() { growslice = sysfunc("growslice") msanread = sysfunc("msanread") msanwrite = sysfunc("msanwrite") + msanmove = sysfunc("msanmove") newobject = sysfunc("newobject") newproc = sysfunc("newproc") panicdivide = sysfunc("panicdivide") @@ -966,7 +967,45 @@ func (s *state) newValueOrSfCall2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Valu return s.newValue2(op, t, arg0, arg1) } -func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) { +type instrumentKind uint8 + +const ( + instrumentRead = iota + instrumentWrite + instrumentMove +) + +func (s *state) instrument(t *types.Type, addr *ssa.Value, kind instrumentKind) { + s.instrument2(t, addr, nil, kind) +} + +// instrumentFields instruments a read/write operation on addr. +// If it is instrumenting for MSAN and t is a struct type, it instruments +// operation for each field, instead of for the whole struct. +func (s *state) instrumentFields(t *types.Type, addr *ssa.Value, kind instrumentKind) { + if !flag_msan || !t.IsStruct() { + s.instrument(t, addr, kind) + return + } + for _, f := range t.Fields().Slice() { + if f.Sym.IsBlank() { + continue + } + offptr := s.newValue1I(ssa.OpOffPtr, types.NewPtr(f.Type), f.Offset, addr) + s.instrumentFields(f.Type, offptr, kind) + } +} + +func (s *state) instrumentMove(t *types.Type, dst, src *ssa.Value) { + if flag_msan { + s.instrument2(t, dst, src, instrumentMove) + } else { + s.instrument(t, src, instrumentRead) + s.instrument(t, dst, instrumentWrite) + } +} + +func (s *state) instrument2(t *types.Type, addr, addr2 *ssa.Value, kind instrumentKind) { if !s.curfn.Func.InstrumentBody() { return } @@ -983,33 +1022,54 @@ func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) { var fn *obj.LSym needWidth := false + if addr2 != nil && kind != instrumentMove { + panic("instrument2: non-nil addr2 for non-move instrumentation") + } + if flag_msan { - fn = msanread - if wr { + switch kind { + case instrumentRead: + fn = msanread + case instrumentWrite: fn = msanwrite + case instrumentMove: + fn = msanmove + default: + panic("unreachable") } needWidth = true } else if flag_race && t.NumComponents(types.CountBlankFields) > 1 { // for composite objects we have to write every address // because a write might happen to any subobject. // composites with only one element don't have subobjects, though. - fn = racereadrange - if wr { + switch kind { + case instrumentRead: + fn = racereadrange + case instrumentWrite: fn = racewriterange + default: + panic("unreachable") } needWidth = true } else if flag_race { // for non-composite objects we can write just the start // address, as any write must write the first byte. - fn = raceread - if wr { + switch kind { + case instrumentRead: + fn = raceread + case instrumentWrite: fn = racewrite + default: + panic("unreachable") } } else { panic("unreachable") } args := []*ssa.Value{addr} + if addr2 != nil { + args = append(args, addr2) + } if needWidth { args = append(args, s.constInt(types.Types[TUINTPTR], w)) } @@ -1017,7 +1077,7 @@ func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) { } func (s *state) load(t *types.Type, src *ssa.Value) *ssa.Value { - s.instrument(t, src, false) + s.instrumentFields(t, src, instrumentRead) return s.rawLoad(t, src) } @@ -1030,15 +1090,14 @@ func (s *state) store(t *types.Type, dst, val *ssa.Value) { } func (s *state) zero(t *types.Type, dst *ssa.Value) { - s.instrument(t, dst, true) + s.instrument(t, dst, instrumentWrite) store := s.newValue2I(ssa.OpZero, types.TypeMem, t.Size(), dst, s.mem()) store.Aux = t s.vars[&memVar] = store } func (s *state) move(t *types.Type, dst, src *ssa.Value) { - s.instrument(t, src, false) - s.instrument(t, dst, true) + s.instrumentMove(t, dst, src) store := s.newValue3I(ssa.OpMove, types.TypeMem, t.Size(), dst, src, s.mem()) store.Aux = t s.vars[&memVar] = store @@ -5248,7 +5307,7 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args . // do *left = right for type t. func (s *state) storeType(t *types.Type, left, right *ssa.Value, skip skipMask, leftIsStmt bool) { - s.instrument(t, left, true) + s.instrument(t, left, instrumentWrite) if skip == 0 && (!t.HasPointers() || ssa.IsStackAddr(left)) { // Known to not have write barrier. Store the whole type. diff --git a/src/runtime/msan.go b/src/runtime/msan.go index c0f3957e28..6a5960b0a8 100644 --- a/src/runtime/msan.go +++ b/src/runtime/msan.go @@ -50,8 +50,12 @@ func msanmalloc(addr unsafe.Pointer, sz uintptr) //go:noescape func msanfree(addr unsafe.Pointer, sz uintptr) -// These are called from msan_amd64.s +//go:noescape +func msanmove(dst, src unsafe.Pointer, sz uintptr) + +// These are called from msan_GOARCH.s //go:cgo_import_static __msan_read_go //go:cgo_import_static __msan_write_go //go:cgo_import_static __msan_malloc_go //go:cgo_import_static __msan_free_go +//go:cgo_import_static __msan_memmove diff --git a/src/runtime/msan_amd64.s b/src/runtime/msan_amd64.s index cbe739df53..669e9ca73f 100644 --- a/src/runtime/msan_amd64.s +++ b/src/runtime/msan_amd64.s @@ -58,6 +58,15 @@ TEXT runtime·msanfree(SB), NOSPLIT, $0-16 MOVQ $__msan_free_go(SB), AX JMP msancall<>(SB) +// func runtime·msanmove(dst, src unsafe.Pointer, sz uintptr) +TEXT runtime·msanmove(SB), NOSPLIT, $0-24 + MOVQ dst+0(FP), RARG0 + MOVQ src+8(FP), RARG1 + MOVQ size+16(FP), RARG2 + // void __msan_memmove(void *dst, void *src, uintptr_t sz); + MOVQ $__msan_memmove(SB), AX + JMP msancall<>(SB) + // Switches SP to g0 stack and calls (AX). Arguments already set. TEXT msancall<>(SB), NOSPLIT, $0-0 get_tls(R12) diff --git a/src/runtime/msan_arm64.s b/src/runtime/msan_arm64.s index 5e29f1aefb..f19906cfc8 100644 --- a/src/runtime/msan_arm64.s +++ b/src/runtime/msan_arm64.s @@ -9,6 +9,7 @@ #define RARG0 R0 #define RARG1 R1 +#define RARG2 R2 #define FARG R3 // func runtime·domsanread(addr unsafe.Pointer, sz uintptr) @@ -45,6 +46,15 @@ TEXT runtime·msanfree(SB), NOSPLIT, $0-16 MOVD $__msan_free_go(SB), FARG JMP msancall<>(SB) +// func runtime·msanmove(dst, src unsafe.Pointer, sz uintptr) +TEXT runtime·msanmove(SB), NOSPLIT, $0-24 + MOVD dst+0(FP), RARG0 + MOVD src+8(FP), RARG1 + MOVD size+16(FP), RARG2 + // void __msan_memmove(void *dst, void *src, uintptr_t sz); + MOVD $__msan_memmove(SB), FARG + JMP msancall<>(SB) + // Switches SP to g0 stack and calls (FARG). Arguments already set. TEXT msancall<>(SB), NOSPLIT, $0-0 MOVD RSP, R19 // callee-saved From 5246fa5e75b129a7dbd9722aa4de0cbaf7ceae43 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 09:45:07 -0500 Subject: [PATCH 103/212] mime/multipart: handle ReadForm(math.MaxInt64) better Returning an error about integer overflow is needlessly pedantic. The meaning of ReadForm(MaxInt64) is easily understood (accept a lot of data) and can be implemented. Fixes #40430. Change-Id: I8a522033dd9a2f9ad31dd2ad82cf08d553736ab9 Reviewed-on: https://go-review.googlesource.com/c/go/+/275112 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/mime/multipart/formdata.go | 8 ++++++-- src/mime/multipart/formdata_test.go | 14 +++++--------- src/net/http/request_test.go | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go index 4eb3101294..9c42ea8c02 100644 --- a/src/mime/multipart/formdata.go +++ b/src/mime/multipart/formdata.go @@ -7,9 +7,9 @@ package multipart import ( "bytes" "errors" - "fmt" "io" "io/ioutil" + "math" "net/textproto" "os" ) @@ -43,7 +43,11 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) { // Reserve an additional 10 MB for non-file parts. maxValueBytes := maxMemory + int64(10<<20) if maxValueBytes <= 0 { - return nil, fmt.Errorf("multipart: integer overflow from maxMemory(%d) + 10MiB for non-file parts", maxMemory) + if maxMemory < 0 { + maxValueBytes = 0 + } else { + maxValueBytes = math.MaxInt64 + } } for { p, err := r.NextPart() diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go index 7112e0d372..e3a3a3eae8 100644 --- a/src/mime/multipart/formdata_test.go +++ b/src/mime/multipart/formdata_test.go @@ -53,20 +53,16 @@ func TestReadFormWithNamelessFile(t *testing.T) { } } -// Issue 40430: Ensure that we report integer overflows in additions of maxMemory, -// instead of silently and subtly failing without indication. +// Issue 40430: Handle ReadForm(math.MaxInt64) func TestReadFormMaxMemoryOverflow(t *testing.T) { b := strings.NewReader(strings.ReplaceAll(messageWithTextContentType, "\n", "\r\n")) r := NewReader(b, boundary) f, err := r.ReadForm(math.MaxInt64) - if err == nil { - t.Fatal("Unexpected a non-nil error") + if err != nil { + t.Fatalf("ReadForm(MaxInt64): %v", err) } - if f != nil { - t.Fatalf("Unexpected returned a non-nil form: %v\n", f) - } - if g, w := err.Error(), "integer overflow from maxMemory"; !strings.Contains(g, w) { - t.Errorf(`Error mismatch\n%q\ndid not contain\n%q`, g, w) + if f == nil { + t.Fatal("ReadForm(MaxInt64): missing form") } } diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go index 19526b9ad7..689498e19d 100644 --- a/src/net/http/request_test.go +++ b/src/net/http/request_test.go @@ -285,7 +285,7 @@ func TestMaxInt64ForMultipartFormMaxMemoryOverflow(t *testing.T) { t.Fatal(err) } res.Body.Close() - if g, w := res.StatusCode, StatusBadRequest; g != w { + if g, w := res.StatusCode, StatusOK; g != w { t.Fatalf("Status code mismatch: got %d, want %d", g, w) } } From c519b156fcc5e53a2a91690303cc7502261dc57b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 10:03:22 -0500 Subject: [PATCH 104/212] doc/go1.16: more release notes Fixes #42899 (flag). Fixes #42900 (io). Fixes #42901 (log). Fixes #42902 (log/syslog). Fixes #42903 (mime/multipart). Fixes #42904 (net). Fixes #42905 (net/http). Fixes #42906 (net/http/httputil). Fixes #42907 (net/smtp). Fixes #42909 (os/signal). Fixes #42913 (syscall). Change-Id: Id09f038751d61fe0f1ff57b525e49473dd75c95f Reviewed-on: https://go-review.googlesource.com/c/go/+/275113 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov --- doc/go1.16.html | 56 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 6618240ed1..1862808486 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -494,7 +494,10 @@ Do not send CLs removing the interior tags from such phrases.
flag

- TODO: https://golang.org/cl/240014: add Func + The new Func function + allows registering a flag implemented by calling a function, + as a lighter-weight alternative to implementing the + Value interface.

@@ -502,7 +505,8 @@ Do not send CLs removing the interior tags from such phrases.
io

- TODO: https://golang.org/cl/261577: add a new ReadSeekCloser interface + The package now defines a + ReadSeekCloser interface.

@@ -510,7 +514,8 @@ Do not send CLs removing the interior tags from such phrases.
log

- TODO: https://golang.org/cl/264460: expose std via new Default function + The new Default function + provides access to the default Logger.

@@ -518,7 +523,11 @@ Do not send CLs removing the interior tags from such phrases.
log/syslog

- TODO: https://golang.org/cl/264297: set local to true if network is any of "unix", or "unixgram" + The Writer + now uses the local message format + (omitting the host name and using a shorter time stamp) + when logging to custom Unix domain sockets, + matching the format already used for the default log socket.

@@ -526,7 +535,10 @@ Do not send CLs removing the interior tags from such phrases.
mime/multipart

- TODO: https://golang.org/cl/247477: return overflow errors in Reader.ReadForm + The Reader's + ReadForm + method no longer rejects form data + when passed the maximum int64 value as a limit.

@@ -550,7 +562,10 @@ Do not send CLs removing the interior tags from such phrases.

- TODO: https://golang.org/cl/238629: prefer /etc/hosts over DNS when no /etc/nsswitch.conf is present + On Linux, host name lookups no longer use DNS before checking + /etc/hosts when /etc/nsswitch.conf + is missing; this is common on musl-based systems and makes + Go programs match the behavior of C programs on those systems.

@@ -590,11 +605,16 @@ Do not send CLs removing the interior tags from such phrases.

- TODO: https://golang.org/cl/250039: set Content-Length:0 for empty PATCH requests as with POST, PATCH + The Client now sends + an explicit Content-Length: 0 + header in PATCH requests with empty bodies, + matching the existing behavior of POST and PUT.

- TODO: https://golang.org/cl/249440: match http scheme when selecting http_proxy + The ProxyFromEnvironment function + no longer returns the setting of the HTTP_PROXY environment + variable for https:// URLs when HTTPS_PROXY is unset.

@@ -602,7 +622,9 @@ Do not send CLs removing the interior tags from such phrases.
net/http/httputil

- TODO: https://golang.org/cl/260637: flush ReverseProxy immediately if Content-Length is -1 + The ReverseProxy + now flushes buffered data more aggressively when proxying + streamed responses with unknown body lengths.

@@ -610,7 +632,10 @@ Do not send CLs removing the interior tags from such phrases.
net/smtp

- TODO: https://golang.org/cl/247257: adds support for the SMTPUTF8 extension + The Client's + Mail + method now sends the SMTPUTF8 directive to + servers that support it, signaling that addresses are encoded in UTF-8.

@@ -629,7 +654,10 @@ Do not send CLs removing the interior tags from such phrases.
os/signal

- TODO: https://golang.org/cl/219640: add NotifyContext to cancel context using system signals + The new + NotifyContext + function allows creating contexts that are canceled upon arrival of + specific signals.

@@ -709,7 +737,11 @@ Do not send CLs removing the interior tags from such phrases.

- TODO: https://golang.org/cl/210639: support POSIX semantics for Linux syscalls + On Linux, + Setgid, + Setuid, + and related calls are now implemented. + Previously, they returned an syscall.EOPNOTSUPP error.

From 932733d4212a7aa651f5060dff489f0819d928bb Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 10:31:42 -0500 Subject: [PATCH 105/212] doc/go1.16: document embed, io/fs, runtime/metrics Fixes #42915. Change-Id: Ia6e205aaac3cbf4ba7340deafad444ac3e573559 Reviewed-on: https://go-review.googlesource.com/c/go/+/275114 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Ian Lance Taylor --- doc/go1.16.html | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 1862808486..88feab30c5 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -85,7 +85,7 @@ Do not send CLs removing the interior tags from such phrases.

Module-aware mode is enabled by default, regardless of whether a go.mod file is present in the current working directory or a - parent directory. Specifically, the GO111MODULE environment + parent directory. More precisely, the GO111MODULE environment variable now defaults to on. To switch to the previous behavior, set GO111MODULE to auto.

@@ -141,6 +141,17 @@ Do not send CLs removing the interior tags from such phrases. non-reproducible builds.

+

Embedding Files

+ +

+ The go command now supports including + static files and file trees as part of the final executable, + using the new //go:embed directive. + See the documentation for the new + embed + package for details. +

+

go test

@@ -260,7 +271,15 @@ Do not send CLs removing the interior tags from such phrases.

Runtime

- TODO + The new runtime/metrics package + introduces a stable interface for reading + implementation-defined metrics from the Go runtime. + It supersedes existing functions like + runtime.ReadMemStats + and + debug.GCStats + and is significantly more general and efficient. + See the package documentation for more details.

@@ -313,9 +332,54 @@ Do not send CLs removing the interior tags from such phrases.

Core library

+

Embedded Files

+

- TODO: mention significant additions like new packages (io/fs), - new proposal-scoped features (//go:embed), and so on + The new embed package + provides access to files embedded in the program during compilation + using the new //go:embed directive. +

+ +

File Systems

+ +

+ The new io/fs package + defines an abstraction for read-only trees of files, + the fs.FS interface, + and the standard library packages have + been adapted to make use of the interface as appropriate. +

+ +

+ On the producer side of the interface, + the new embed.FS type + implements fs.FS, as does + zip.Reader. + The new os.Dir function + provides an implementation of fs.FS backed by a tree + of operating system files. +

+ +

+ On the consumer side, + the new http.FS + function converts an fs.FS to an + http.Handler. + Also, the html/template + and text/template + packages’ ParseFS + functions and methods read templates from an fs.FS. +

+ +

+ For testing code that implements fs.FS, + the new testing/fstest + package provides a TestFS + function that checks for and reports common mistakes. + It also provides a simple in-memory file system implementation, + MapFS, + which can be useful for testing code that accepts fs.FS + implementations.

From 59b8916d482bdca933885881dff54365432ec9f5 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 1 Dec 2020 12:02:16 -0500 Subject: [PATCH 106/212] [dev.regabi] cmd/compile: handle OCONVNOP better in ssa This CL improves handling of OCONVNOP nodes during ssa generation, so it is not toolstash safe. An OCONVNOP wrapper is necessary for the "for" condition of certain compiled range loops, and the boolean evaluator was not looking through them properly, generating unnecessary temporaries. That change saved 8k of the (13 MB) go binary. The other changes just streamline the handling of OCONVNOP to be more like what OSTMTEXPR will be like. They have no effect on output size but do tweak the ssa graph a little, which causes different register decisions and therefore different output. Change-Id: I9e1dcd413b60944e21554c3e3f2bdc9adcee7634 Reviewed-on: https://go-review.googlesource.com/c/go/+/274598 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 10 ++++++++++ src/cmd/compile/internal/gc/walk.go | 3 +++ 2 files changed, 13 insertions(+) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 7c74054b60..d53bd1aa4f 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -2103,6 +2103,9 @@ func (s *state) expr(n ir.Node) *ssa.Value { // Assume everything will work out, so set up our return value. // Anything interesting that happens from here is a fatal. x := s.expr(n.Left()) + if to == from { + return x + } // Special case for not confusing GC and liveness. // We don't want pointers accidentally classified @@ -2966,6 +2969,10 @@ func (s *state) condBranch(cond ir.Node, yes, no *ssa.Block, likely int8) { s.stmtList(cond.Init()) s.condBranch(cond.Left(), no, yes, -likely) return + case ir.OCONVNOP: + s.stmtList(cond.Init()) + s.condBranch(cond.Left(), yes, no, likely) + return } c := s.expr(cond) b := s.endBlock() @@ -4903,6 +4910,9 @@ func (s *state) addr(n ir.Node) *ssa.Value { return s.newValue1I(ssa.OpOffPtr, t, n.Offset(), s.entryNewValue0(ssa.OpGetClosurePtr, s.f.Config.Types.BytePtr)) case ir.OCONVNOP: + if n.Type() == n.Left().Type() { + return s.addr(n.Left()) + } addr := s.addr(n.Left()) return s.newValue1(ssa.OpCopy, t, addr) // ensure that addr has the right type case ir.OCALLFUNC, ir.OCALLINTER, ir.OCALLMETH: diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index f439237936..c0f447f1a2 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -966,6 +966,9 @@ opswitch: case ir.OCONV, ir.OCONVNOP: n.SetLeft(walkexpr(n.Left(), init)) + if n.Op() == ir.OCONVNOP && n.Type() == n.Left().Type() { + return n.Left() + } if n.Op() == ir.OCONVNOP && checkPtr(Curfn, 1) { if n.Type().IsPtr() && n.Left().Type().IsUnsafePtr() { // unsafe.Pointer to *T n = walkCheckPtrAlignment(n, init, nil) From 58768ae15b3f892b9b1902220ba3564375e5c6de Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 2 Dec 2020 18:13:14 -0800 Subject: [PATCH 107/212] test: match gccgo error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit assign.go:59:28: error: ‘x’ repeated on left side of := assign.go:65:20: error: ‘a’ repeated on left side of := method2.go:36:11: error: reference to method ‘val’ in type that is pointer to interface, not interface method2.go:37:11: error: reference to method ‘val’ in type that is pointer to interface, not interface Change-Id: I8f385c75a82fae4eacf4618df8f9f65932826494 Reviewed-on: https://go-review.googlesource.com/c/go/+/274447 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- test/assign.go | 4 ++-- test/method2.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/assign.go b/test/assign.go index 6611f8ce3e..62fd3b5be3 100644 --- a/test/assign.go +++ b/test/assign.go @@ -56,13 +56,13 @@ func main() { { var x = 1 { - x, x := 2, 3 // ERROR "x repeated on left side of :=" + x, x := 2, 3 // ERROR ".*x.* repeated on left side of :=" _ = x } _ = x } { - a, a := 1, 2 // ERROR "a repeated on left side of :=" + a, a := 1, 2 // ERROR ".*a.* repeated on left side of :=" _ = a } } diff --git a/test/method2.go b/test/method2.go index 7feb675055..ac1d771c05 100644 --- a/test/method2.go +++ b/test/method2.go @@ -33,8 +33,8 @@ var _ = (*Val).val // ERROR "method" var v Val var pv = &v -var _ = pv.val() // ERROR "undefined" -var _ = pv.val // ERROR "undefined" +var _ = pv.val() // ERROR "undefined|pointer to interface" +var _ = pv.val // ERROR "undefined|pointer to interface" func (t *T) g() int { return t.a } From dda2991c2ea0c5914714469c4defc2562a907230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Thu, 3 Dec 2020 16:41:57 +0100 Subject: [PATCH 108/212] internal/cpu: disable FMA when OSXSAVE is not enabled on x86 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All instructions in the FMA extension on x86 are VEX prefixed. VEX prefixed instructions generally require OSXSAVE to be enabled. The execution of FMA instructions emitted by the Go compiler on amd64 will generate an invalid opcode exception if OSXSAVE is not enabled. Fixes #41022 Change-Id: I49881630e7195c804110a2bd81b5bec8cac31ba8 Reviewed-on: https://go-review.googlesource.com/c/go/+/274479 Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/internal/cpu/cpu_x86.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go index fb414adaf8..ba6bf69034 100644 --- a/src/internal/cpu/cpu_x86.go +++ b/src/internal/cpu/cpu_x86.go @@ -75,13 +75,22 @@ func doinit() { X86.HasSSE3 = isSet(ecx1, cpuid_SSE3) X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ) X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3) - X86.HasFMA = isSet(ecx1, cpuid_FMA) X86.HasSSE41 = isSet(ecx1, cpuid_SSE41) X86.HasSSE42 = isSet(ecx1, cpuid_SSE42) X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT) X86.HasAES = isSet(ecx1, cpuid_AES) + + // OSXSAVE can be false when using older Operating Systems + // or when explicitly disabled on newer Operating Systems by + // e.g. setting the xsavedisable boot option on Windows 10. X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE) + // The FMA instruction set extension only has VEX prefixed instructions. + // VEX prefixed instructions require OSXSAVE to be enabled. + // See Intel 64 and IA-32 Architecture Software Developer’s Manual Volume 2 + // Section 2.4 "AVX and SSE Instruction Exception Specification" + X86.HasFMA = isSet(ecx1, cpuid_FMA) && X86.HasOSXSAVE + osSupportsAVX := false // For XGETBV, OSXSAVE bit is required and sufficient. if X86.HasOSXSAVE { From 7e81135be7b264517cf2ae17dec0fdbafc4c6841 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 2 Dec 2020 17:03:18 -0500 Subject: [PATCH 109/212] [dev.regabi] cmd/compile: rename addinit(n, init) to initExpr(init, n) Recreated manually to push below some CLs it depended on. Change-Id: I1b3316fcdce39cbb33e5cbb471f5cd1cd2efc1f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/274599 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/inl.go | 4 ++-- src/cmd/compile/internal/gc/order.go | 2 +- src/cmd/compile/internal/gc/subr.go | 6 +++--- src/cmd/compile/internal/gc/typecheck.go | 4 ++-- src/cmd/compile/internal/gc/walk.go | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index fd8e9cfd46..42125f38f3 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -537,7 +537,7 @@ func inlconv2stmt(inlcall ir.Node) ir.Node { // n.Left = inlconv2expr(n.Left) func inlconv2expr(n ir.Node) ir.Node { r := n.Rlist().First() - return addinit(r, append(n.Init().Slice(), n.Body().Slice()...)) + return initExpr(append(n.Init().Slice(), n.Body().Slice()...), r) } // Turn the rlist (with the return values) of the OINLCALL in @@ -551,7 +551,7 @@ func inlconv2list(n ir.Node) []ir.Node { } s := n.Rlist().Slice() - s[0] = addinit(s[0], append(n.Init().Slice(), n.Body().Slice()...)) + s[0] = initExpr(append(n.Init().Slice(), n.Body().Slice()...), s[0]) return s } diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 7816e684dc..e4175bbf36 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -433,7 +433,7 @@ func (o *Order) exprInPlace(n ir.Node) ir.Node { var order Order order.free = o.free n = order.expr(n, nil) - n = addinit(n, order.out) + n = initExpr(order.out, n) // insert new temporaries from order // at head of outer list. diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 011a7ac5bc..970f78b355 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -1355,9 +1355,9 @@ func ngotype(n ir.Node) *types.Sym { return nil } -// The result of addinit MUST be assigned back to n, e.g. -// n.Left = addinit(n.Left, init) -func addinit(n ir.Node, init []ir.Node) ir.Node { +// The result of initExpr MUST be assigned back to n, e.g. +// n.Left = initExpr(init, n.Left) +func initExpr(init []ir.Node, n ir.Node) ir.Node { if len(init) == 0 { return n } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 5a073ac324..55443ba596 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1314,7 +1314,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } old := n n = ir.NodAt(n.Pos(), l.SubOp(), arg, nil) - n = addinit(n, old.Init().Slice()) // typecheckargs can add to old.Init + n = initExpr(old.Init().Slice(), n) // typecheckargs can add to old.Init case ir.OCOMPLEX, ir.OCOPY: typecheckargs(n) @@ -1325,7 +1325,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } old := n n = ir.NodAt(n.Pos(), l.SubOp(), arg1, arg2) - n = addinit(n, old.Init().Slice()) // typecheckargs can add to old.Init + n = initExpr(old.Init().Slice(), n) // typecheckargs can add to old.Init } n = typecheck1(n, top) return n diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index c0f447f1a2..e72015c05e 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -180,7 +180,7 @@ func walkstmt(n ir.Node) ir.Node { n = mkcall1(chanfn("chanrecv1", 2, n.Left().Type()), nil, &init, n.Left(), nodnil()) n = walkexpr(n, &init) - n = addinit(n, init.Slice()) + n = initExpr(init.Slice(), n) case ir.OBREAK, ir.OCONTINUE, @@ -268,7 +268,7 @@ func walkstmt(n ir.Node) ir.Node { init := n.Left().Init() n.Left().PtrInit().Set(nil) n.SetLeft(walkexpr(n.Left(), &init)) - n.SetLeft(addinit(n.Left(), init.Slice())) + n.SetLeft(initExpr(init.Slice(), n.Left())) } n.SetRight(walkstmt(n.Right())) @@ -557,7 +557,7 @@ opswitch: var ll ir.Nodes n.SetRight(walkexpr(n.Right(), &ll)) - n.SetRight(addinit(n.Right(), ll.Slice())) + n.SetRight(initExpr(ll.Slice(), n.Right())) case ir.OPRINT, ir.OPRINTN: n = walkprint(n, init) From beb5e0540406e2281a7502a2009db752668219da Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 2 Dec 2020 23:55:42 -0800 Subject: [PATCH 110/212] [dev.regabi] cmd/compile: refactoring prep for ConstExpr The next CL adds ConstExpr, which is a more memory efficient representation for constant expressions than Name. However, currently a bunch of Val helper methods are defined on Name. This CL changes them into standalone functions that work with any Node.Val implementation. There's also an existing standalone function named Int64Val, which takes a Type argument to specify what type of integer is expected. So to avoid collisions, this CL renames it to IntVal. Passes buildall w/ toolstash -cmp. [git-generate] cd src/cmd/compile/internal/ir rf 'mv Int64Val IntVal' sed -i -E -e 's/\(n \*Name\) (CanInt64|((I|Ui)nt64|Bool|String)Val)\(/\1(n Node/' name.go cd ../gc rf ' ex { import "cmd/compile/internal/ir" var n ir.Node n.CanInt64() -> ir.CanInt64(n) n.Int64Val() -> ir.Int64Val(n) n.Uint64Val() -> ir.Uint64Val(n) n.BoolVal() -> ir.BoolVal(n) n.StringVal() -> ir.StringVal(n) } ' cd ../ir rf ' mv CanInt64 Int64Val Uint64Val BoolVal StringVal val.go rm Node.CanInt64 Node.Int64Val Node.Uint64Val Node.BoolVal Node.StringVal ' Change-Id: I003140bda1690d770fd608bdd087e6d4ff00fb1f Reviewed-on: https://go-review.googlesource.com/c/go/+/275032 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/const.go | 8 ++-- src/cmd/compile/internal/gc/escape.go | 2 +- src/cmd/compile/internal/gc/noder.go | 6 +-- src/cmd/compile/internal/gc/obj.go | 4 +- src/cmd/compile/internal/gc/order.go | 4 +- src/cmd/compile/internal/gc/sinit.go | 14 +++--- src/cmd/compile/internal/gc/ssa.go | 10 ++-- src/cmd/compile/internal/gc/swt.go | 10 ++-- src/cmd/compile/internal/gc/typecheck.go | 22 ++++----- src/cmd/compile/internal/gc/walk.go | 30 ++++++------ src/cmd/compile/internal/ir/name.go | 56 ---------------------- src/cmd/compile/internal/ir/node.go | 5 -- src/cmd/compile/internal/ir/val.go | 60 +++++++++++++++++++++++- 13 files changed, 113 insertions(+), 118 deletions(-) diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 4a61c77630..8771d82cfa 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -526,7 +526,7 @@ func evalConst(n ir.Node) ir.Node { if need == 1 { var strs []string for _, c := range s { - strs = append(strs, c.StringVal()) + strs = append(strs, ir.StringVal(c)) } return origConst(n, constant.MakeString(strings.Join(strs, ""))) } @@ -537,7 +537,7 @@ func evalConst(n ir.Node) ir.Node { var strs []string i2 := i for i2 < len(s) && ir.IsConst(s[i2], constant.String) { - strs = append(strs, s[i2].StringVal()) + strs = append(strs, ir.StringVal(s[i2])) i2++ } @@ -558,7 +558,7 @@ func evalConst(n ir.Node) ir.Node { switch nl.Type().Kind() { case types.TSTRING: if ir.IsConst(nl, constant.String) { - return origIntConst(n, int64(len(nl.StringVal()))) + return origIntConst(n, int64(len(ir.StringVal(nl)))) } case types.TARRAY: if !hascallchan(nl) { @@ -780,7 +780,7 @@ func indexconst(n ir.Node) int64 { if doesoverflow(v, types.Types[types.TINT]) { return -2 } - return ir.Int64Val(types.Types[types.TINT], v) + return ir.IntVal(types.Types[types.TINT], v) } // isGoConst reports whether n is a Go language constant (as opposed to a diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 9fc3dd2778..622edb9820 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -1769,7 +1769,7 @@ func heapAllocReason(n ir.Node) string { if !smallintconst(r) { return "non-constant size" } - if t := n.Type(); t.Elem().Width != 0 && r.Int64Val() >= maxImplicitStackVarSize/t.Elem().Width { + if t := n.Type(); t.Elem().Width != 0 && ir.Int64Val(r) >= maxImplicitStackVarSize/t.Elem().Width { return "too large for stack" } } diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 9352463f18..61320123a8 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -807,7 +807,7 @@ func (p *noder) sum(x syntax.Expr) ir.Node { n := p.expr(x) if ir.IsConst(n, constant.String) && n.Sym() == nil { nstr = n - chunks = append(chunks, nstr.StringVal()) + chunks = append(chunks, ir.StringVal(nstr)) } for i := len(adds) - 1; i >= 0; i-- { @@ -817,12 +817,12 @@ func (p *noder) sum(x syntax.Expr) ir.Node { if ir.IsConst(r, constant.String) && r.Sym() == nil { if nstr != nil { // Collapse r into nstr instead of adding to n. - chunks = append(chunks, r.StringVal()) + chunks = append(chunks, ir.StringVal(r)) continue } nstr = r - chunks = append(chunks, nstr.StringVal()) + chunks = append(chunks, ir.StringVal(nstr)) } else { if len(chunks) > 1 { nstr.SetVal(constant.MakeString(strings.Join(chunks, ""))) diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 21a50257b8..b1701b30a1 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -263,7 +263,7 @@ func dumpGlobalConst(n ir.Node) { return } } - base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, typesymname(t), ir.Int64Val(t, v)) + base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, typesymname(t), ir.IntVal(t, v)) } func dumpglobls() { @@ -598,7 +598,7 @@ func litsym(n, c ir.Node, wid int) { s.WriteInt(base.Ctxt, n.Offset(), wid, i) case constant.Int: - s.WriteInt(base.Ctxt, n.Offset(), wid, ir.Int64Val(n.Type(), u)) + s.WriteInt(base.Ctxt, n.Offset(), wid, ir.IntVal(n.Type(), u)) case constant.Float: f, _ := constant.Float64Val(u) diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index e4175bbf36..5440806e8e 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -1107,7 +1107,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { haslit := false for _, n1 := range n.List().Slice() { hasbyte = hasbyte || n1.Op() == ir.OBYTES2STR - haslit = haslit || n1.Op() == ir.OLITERAL && len(n1.StringVal()) != 0 + haslit = haslit || n1.Op() == ir.OLITERAL && len(ir.StringVal(n1)) != 0 } if haslit && hasbyte { @@ -1278,7 +1278,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { var t *types.Type switch n.Op() { case ir.OSLICELIT: - t = types.NewArray(n.Type().Elem(), n.Right().Int64Val()) + t = types.NewArray(n.Type().Elem(), ir.Int64Val(n.Right())) case ir.OCALLPART: t = partialCallType(n) } diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index 2dc4281857..3ef976d8aa 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -134,7 +134,7 @@ func (s *InitSchedule) staticcopy(l ir.Node, r ir.Node) bool { case ir.OSLICELIT: // copy slice a := s.inittemps[r] - slicesym(l, a, r.Right().Int64Val()) + slicesym(l, a, ir.Int64Val(r.Right())) return true case ir.OARRAYLIT, ir.OSTRUCTLIT: @@ -213,7 +213,7 @@ func (s *InitSchedule) staticassign(l ir.Node, r ir.Node) bool { case ir.OSTR2BYTES: if l.Class() == ir.PEXTERN && r.Left().Op() == ir.OLITERAL { - sval := r.Left().StringVal() + sval := ir.StringVal(r.Left()) slicebytes(l, sval) return true } @@ -221,7 +221,7 @@ func (s *InitSchedule) staticassign(l ir.Node, r ir.Node) bool { case ir.OSLICELIT: s.initplan(r) // Init slice. - bound := r.Right().Int64Val() + bound := ir.Int64Val(r.Right()) ta := types.NewArray(r.Type().Elem(), bound) ta.SetNoalg(true) a := staticname(ta) @@ -418,7 +418,7 @@ func getdyn(n ir.Node, top bool) initGenType { if !top { return initDynamic } - if n.Right().Int64Val()/4 > int64(n.List().Len()) { + if ir.Int64Val(n.Right())/4 > int64(n.List().Len()) { // <25% of entries have explicit values. // Very rough estimation, it takes 4 bytes of instructions // to initialize 1 byte of result. So don't use a static @@ -594,12 +594,12 @@ func isSmallSliceLit(n ir.Node) bool { r := n.Right() - return smallintconst(r) && (n.Type().Elem().Width == 0 || r.Int64Val() <= smallArrayBytes/n.Type().Elem().Width) + return smallintconst(r) && (n.Type().Elem().Width == 0 || ir.Int64Val(r) <= smallArrayBytes/n.Type().Elem().Width) } func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) { // make an array type corresponding the number of elements we have - t := types.NewArray(n.Type().Elem(), n.Right().Int64Val()) + t := types.NewArray(n.Type().Elem(), ir.Int64Val(n.Right())) dowidth(t) if ctxt == inNonInitFunction { @@ -997,7 +997,7 @@ func oaslit(n ir.Node, init *ir.Nodes) bool { func getlit(lit ir.Node) int { if smallintconst(lit) { - return int(lit.Int64Val()) + return int(ir.Int64Val(lit)) } return -1 } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index d53bd1aa4f..89918e2133 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1271,7 +1271,7 @@ func (s *state) stmt(n ir.Node) { // We're assigning a slicing operation back to its source. // Don't write back fields we aren't changing. See issue #14855. i, j, k := rhs.SliceBounds() - if i != nil && (i.Op() == ir.OLITERAL && i.Val().Kind() == constant.Int && i.Int64Val() == 0) { + if i != nil && (i.Op() == ir.OLITERAL && i.Val().Kind() == constant.Int && ir.Int64Val(i) == 0) { // [0:...] is the same as [:...] i = nil } @@ -1301,7 +1301,7 @@ func (s *state) stmt(n ir.Node) { case ir.OIF: if ir.IsConst(n.Left(), constant.Bool) { s.stmtList(n.Left().Init()) - if n.Left().BoolVal() { + if ir.BoolVal(n.Left()) { s.stmtList(n.Body()) } else { s.stmtList(n.Rlist()) @@ -2041,7 +2041,7 @@ func (s *state) expr(n ir.Node) *ssa.Value { case ir.OLITERAL: switch u := n.Val(); u.Kind() { case constant.Int: - i := ir.Int64Val(n.Type(), u) + i := ir.IntVal(n.Type(), u) switch n.Type().Size() { case 1: return s.constInt8(n.Type(), int8(i)) @@ -2624,7 +2624,7 @@ func (s *state) expr(n ir.Node) *ssa.Value { // Replace "abc"[1] with 'b'. // Delayed until now because "abc"[1] is not an ideal constant. // See test/fixedbugs/issue11370.go. - return s.newValue0I(ssa.OpConst8, types.Types[types.TUINT8], int64(int8(n.Left().StringVal()[n.Right().Int64Val()]))) + return s.newValue0I(ssa.OpConst8, types.Types[types.TUINT8], int64(int8(ir.StringVal(n.Left())[ir.Int64Val(n.Right())]))) } a := s.expr(n.Left()) i := s.expr(n.Right()) @@ -2633,7 +2633,7 @@ func (s *state) expr(n ir.Node) *ssa.Value { ptrtyp := s.f.Config.Types.BytePtr ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a) if ir.IsConst(n.Right(), constant.Int) { - ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, n.Right().Int64Val(), ptr) + ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, ir.Int64Val(n.Right()), ptr) } else { ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i) } diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go index 30179e1dd6..e241721588 100644 --- a/src/cmd/compile/internal/gc/swt.go +++ b/src/cmd/compile/internal/gc/swt.go @@ -365,8 +365,8 @@ func (s *exprSwitch) flush() { // all we need here is consistency. We respect this // sorting below. sort.Slice(cc, func(i, j int) bool { - si := cc[i].lo.StringVal() - sj := cc[j].lo.StringVal() + si := ir.StringVal(cc[i].lo) + sj := ir.StringVal(cc[j].lo) if len(si) != len(sj) { return len(si) < len(sj) } @@ -375,7 +375,7 @@ func (s *exprSwitch) flush() { // runLen returns the string length associated with a // particular run of exprClauses. - runLen := func(run []exprClause) int64 { return int64(len(run[0].lo.StringVal())) } + runLen := func(run []exprClause) int64 { return int64(len(ir.StringVal(run[0].lo))) } // Collapse runs of consecutive strings with the same length. var runs [][]exprClause @@ -411,7 +411,7 @@ func (s *exprSwitch) flush() { merged := cc[:1] for _, c := range cc[1:] { last := &merged[len(merged)-1] - if last.jmp == c.jmp && last.hi.Int64Val()+1 == c.lo.Int64Val() { + if last.jmp == c.jmp && ir.Int64Val(last.hi)+1 == ir.Int64Val(c.lo) { last.hi = c.lo } else { merged = append(merged, c) @@ -446,7 +446,7 @@ func (c *exprClause) test(exprname ir.Node) ir.Node { // Optimize "switch true { ...}" and "switch false { ... }". if ir.IsConst(exprname, constant.Bool) && !c.lo.Type().IsInterface() { - if exprname.BoolVal() { + if ir.BoolVal(exprname) { return c.lo } else { return ir.NodAt(c.pos, ir.ONOT, c.lo, nil) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 55443ba596..b19481311b 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1054,8 +1054,8 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { base.Errorf("invalid %s index %v (index must be non-negative)", why, n.Right()) } else if t.IsArray() && constant.Compare(x, token.GEQ, constant.MakeInt64(t.NumElem())) { base.Errorf("invalid array index %v (out of bounds for %d-element array)", n.Right(), t.NumElem()) - } else if ir.IsConst(n.Left(), constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(n.Left().StringVal())))) { - base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Right(), len(n.Left().StringVal())) + } else if ir.IsConst(n.Left(), constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(ir.StringVal(n.Left()))))) { + base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Right(), len(ir.StringVal(n.Left()))) } else if doesoverflow(x, types.Types[types.TINT]) { base.Errorf("invalid %s index %v (index too large)", why, n.Right()) } @@ -1146,11 +1146,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { l = defaultlit(l, types.Types[types.TINT]) c = defaultlit(c, types.Types[types.TINT]) - if ir.IsConst(l, constant.Int) && l.Int64Val() < 0 { + if ir.IsConst(l, constant.Int) && ir.Int64Val(l) < 0 { base.Fatalf("len for OSLICEHEADER must be non-negative") } - if ir.IsConst(c, constant.Int) && c.Int64Val() < 0 { + if ir.IsConst(c, constant.Int) && ir.Int64Val(c) < 0 { base.Fatalf("cap for OSLICEHEADER must be non-negative") } @@ -2173,8 +2173,8 @@ func checksliceindex(l ir.Node, r ir.Node, tp *types.Type) bool { } else if tp != nil && tp.NumElem() >= 0 && constant.Compare(x, token.GTR, constant.MakeInt64(tp.NumElem())) { base.Errorf("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem()) return false - } else if ir.IsConst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(l.StringVal())))) { - base.Errorf("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.StringVal())) + } else if ir.IsConst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(ir.StringVal(l))))) { + base.Errorf("invalid slice index %v (out of bounds for %d-byte string)", r, len(ir.StringVal(l))) return false } else if doesoverflow(x, types.Types[types.TINT]) { base.Errorf("invalid slice index %v (index too large)", r) @@ -3407,7 +3407,7 @@ func stringtoruneslit(n ir.Node) ir.Node { var l []ir.Node i := 0 - for _, r := range n.Left().StringVal() { + for _, r := range ir.StringVal(n.Left()) { l = append(l, ir.Nod(ir.OKEY, nodintconst(int64(i)), nodintconst(int64(r)))) i++ } @@ -3803,7 +3803,7 @@ func deadcode(fn *ir.Func) { return } case ir.OFOR: - if !ir.IsConst(n.Left(), constant.Bool) || n.Left().BoolVal() { + if !ir.IsConst(n.Left(), constant.Bool) || ir.BoolVal(n.Left()) { return } default: @@ -3833,7 +3833,7 @@ func deadcodeslice(nn *ir.Nodes) { n.SetLeft(deadcodeexpr(n.Left())) if ir.IsConst(n.Left(), constant.Bool) { var body ir.Nodes - if n.Left().BoolVal() { + if ir.BoolVal(n.Left()) { n.SetRlist(ir.Nodes{}) body = n.Body() } else { @@ -3876,7 +3876,7 @@ func deadcodeexpr(n ir.Node) ir.Node { n.SetLeft(deadcodeexpr(n.Left())) n.SetRight(deadcodeexpr(n.Right())) if ir.IsConst(n.Left(), constant.Bool) { - if n.Left().BoolVal() { + if ir.BoolVal(n.Left()) { return n.Right() // true && x => x } else { return n.Left() // false && x => false @@ -3886,7 +3886,7 @@ func deadcodeexpr(n ir.Node) ir.Node { n.SetLeft(deadcodeexpr(n.Left())) n.SetRight(deadcodeexpr(n.Right())) if ir.IsConst(n.Left(), constant.Bool) { - if n.Left().BoolVal() { + if ir.BoolVal(n.Left()) { return n.Left() // true || x => true } else { return n.Right() // false || x => x diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index e72015c05e..ce7de1396b 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1014,7 +1014,7 @@ opswitch: // The SSA backend will handle those. switch et { case types.TINT64: - c := n.Right().Int64Val() + c := ir.Int64Val(n.Right()) if c < 0 { c = -c } @@ -1022,7 +1022,7 @@ opswitch: break opswitch } case types.TUINT64: - c := n.Right().Uint64Val() + c := ir.Uint64Val(n.Right()) if c < 1<<16 { break opswitch } @@ -1072,7 +1072,7 @@ opswitch: base.Errorf("index out of bounds") } } else if ir.IsConst(n.Left(), constant.String) { - n.SetBounded(bounded(r, int64(len(n.Left().StringVal())))) + n.SetBounded(bounded(r, int64(len(ir.StringVal(n.Left()))))) if base.Flag.LowerM != 0 && n.Bounded() && !ir.IsConst(n.Right(), constant.Int) { base.Warn("index bounds check elided") } @@ -1507,7 +1507,7 @@ opswitch: case ir.OSTR2BYTES: s := n.Left() if ir.IsConst(s, constant.String) { - sc := s.StringVal() + sc := ir.StringVal(s) // Allocate a [n]byte of the right size. t := types.NewArray(types.Types[types.TUINT8], int64(len(sc))) @@ -1936,7 +1936,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node { for i := 0; i < len(s); { var strs []string for i < len(s) && ir.IsConst(s[i], constant.String) { - strs = append(strs, s[i].StringVal()) + strs = append(strs, ir.StringVal(s[i])) i++ } if len(strs) > 0 { @@ -2016,7 +2016,7 @@ func walkprint(nn ir.Node, init *ir.Nodes) ir.Node { case types.TSTRING: cs := "" if ir.IsConst(n, constant.String) { - cs = n.StringVal() + cs = ir.StringVal(n) } switch cs { case " ": @@ -2673,7 +2673,7 @@ func addstr(n ir.Node, init *ir.Nodes) ir.Node { sz := int64(0) for _, n1 := range n.List().Slice() { if n1.Op() == ir.OLITERAL { - sz += int64(len(n1.StringVal())) + sz += int64(len(ir.StringVal(n1))) } } @@ -3467,7 +3467,7 @@ func walkcompare(n ir.Node, init *ir.Nodes) ir.Node { func tracecmpArg(n ir.Node, t *types.Type, init *ir.Nodes) ir.Node { // Ugly hack to avoid "constant -1 overflows uintptr" errors, etc. - if n.Op() == ir.OLITERAL && n.Type().IsSigned() && n.Int64Val() < 0 { + if n.Op() == ir.OLITERAL && n.Type().IsSigned() && ir.Int64Val(n) < 0 { n = copyexpr(n, n.Type(), init) } @@ -3537,7 +3537,7 @@ func walkcompareString(n ir.Node, init *ir.Nodes) ir.Node { // Length-only checks are ok, though. maxRewriteLen = 0 } - if s := cs.StringVal(); len(s) <= maxRewriteLen { + if s := ir.StringVal(cs); len(s) <= maxRewriteLen { if len(s) > 0 { ncs = safeexpr(ncs, init) } @@ -3632,7 +3632,7 @@ func bounded(n ir.Node, max int64) bool { bits := int32(8 * n.Type().Width) if smallintconst(n) { - v := n.Int64Val() + v := ir.Int64Val(n) return 0 <= v && v < max } @@ -3641,9 +3641,9 @@ func bounded(n ir.Node, max int64) bool { v := int64(-1) switch { case smallintconst(n.Left()): - v = n.Left().Int64Val() + v = ir.Int64Val(n.Left()) case smallintconst(n.Right()): - v = n.Right().Int64Val() + v = ir.Int64Val(n.Right()) if n.Op() == ir.OANDNOT { v = ^v if !sign { @@ -3657,7 +3657,7 @@ func bounded(n ir.Node, max int64) bool { case ir.OMOD: if !sign && smallintconst(n.Right()) { - v := n.Right().Int64Val() + v := ir.Int64Val(n.Right()) if 0 <= v && v <= max { return true } @@ -3665,7 +3665,7 @@ func bounded(n ir.Node, max int64) bool { case ir.ODIV: if !sign && smallintconst(n.Right()) { - v := n.Right().Int64Val() + v := ir.Int64Val(n.Right()) for bits > 0 && v >= 2 { bits-- v >>= 1 @@ -3674,7 +3674,7 @@ func bounded(n ir.Node, max int64) bool { case ir.ORSH: if !sign && smallintconst(n.Right()) { - v := n.Right().Int64Val() + v := ir.Int64Val(n.Right()) if v > int64(bits) { return true } diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 1d886bb9a1..aeeb63d2d6 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -296,62 +296,6 @@ func (n *Name) SetVal(v constant.Value) { n.val = v } -// Int64Val returns n as an int64. -// n must be an integer or rune constant. -func (n *Name) Int64Val() int64 { - if !IsConst(n, constant.Int) { - base.Fatalf("Int64Val(%v)", n) - } - x, ok := constant.Int64Val(n.Val()) - if !ok { - base.Fatalf("Int64Val(%v)", n) - } - return x -} - -// CanInt64 reports whether it is safe to call Int64Val() on n. -func (n *Name) CanInt64() bool { - if !IsConst(n, constant.Int) { - return false - } - - // if the value inside n cannot be represented as an int64, the - // return value of Int64 is undefined - _, ok := constant.Int64Val(n.Val()) - return ok -} - -// Uint64Val returns n as an uint64. -// n must be an integer or rune constant. -func (n *Name) Uint64Val() uint64 { - if !IsConst(n, constant.Int) { - base.Fatalf("Uint64Val(%v)", n) - } - x, ok := constant.Uint64Val(n.Val()) - if !ok { - base.Fatalf("Uint64Val(%v)", n) - } - return x -} - -// BoolVal returns n as a bool. -// n must be a boolean constant. -func (n *Name) BoolVal() bool { - if !IsConst(n, constant.Bool) { - base.Fatalf("BoolVal(%v)", n) - } - return constant.BoolVal(n.Val()) -} - -// StringVal returns the value of a literal string Node as a string. -// n must be a string constant. -func (n *Name) StringVal() string { - if !IsConst(n, constant.String) { - base.Fatalf("StringVal(%v)", n) - } - return constant.StringVal(n.Val()) -} - // The Class of a variable/function describes the "storage class" // of a variable or function. During parsing, storage classes are // called declaration contexts. diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index cc3ac5765d..42ba4cb0e9 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -87,11 +87,6 @@ type Node interface { MarkReadonly() Val() constant.Value SetVal(v constant.Value) - Int64Val() int64 - Uint64Val() uint64 - CanInt64() bool - BoolVal() bool - StringVal() string // Storage for analysis passes. Esc() uint16 diff --git a/src/cmd/compile/internal/ir/val.go b/src/cmd/compile/internal/ir/val.go index aae965bb4c..ad0df5508d 100644 --- a/src/cmd/compile/internal/ir/val.go +++ b/src/cmd/compile/internal/ir/val.go @@ -32,7 +32,7 @@ func ConstValue(n Node) interface{} { case constant.String: return constant.StringVal(v) case constant.Int: - return Int64Val(n.Type(), v) + return IntVal(n.Type(), v) case constant.Float: return Float64Val(v) case constant.Complex: @@ -42,7 +42,7 @@ func ConstValue(n Node) interface{} { // int64Val returns v converted to int64. // Note: if t is uint64, very large values will be converted to negative int64. -func Int64Val(t *types.Type, v constant.Value) int64 { +func IntVal(t *types.Type, v constant.Value) int64 { if t.IsUnsigned() { if x, ok := constant.Uint64Val(v); ok { return int64(x) @@ -118,3 +118,59 @@ func idealType(ct constant.Kind) *types.Type { } var OKForConst [types.NTYPE]bool + +// CanInt64 reports whether it is safe to call Int64Val() on n. +func CanInt64(n Node) bool { + if !IsConst(n, constant.Int) { + return false + } + + // if the value inside n cannot be represented as an int64, the + // return value of Int64 is undefined + _, ok := constant.Int64Val(n.Val()) + return ok +} + +// Int64Val returns n as an int64. +// n must be an integer or rune constant. +func Int64Val(n Node) int64 { + if !IsConst(n, constant.Int) { + base.Fatalf("Int64Val(%v)", n) + } + x, ok := constant.Int64Val(n.Val()) + if !ok { + base.Fatalf("Int64Val(%v)", n) + } + return x +} + +// Uint64Val returns n as an uint64. +// n must be an integer or rune constant. +func Uint64Val(n Node) uint64 { + if !IsConst(n, constant.Int) { + base.Fatalf("Uint64Val(%v)", n) + } + x, ok := constant.Uint64Val(n.Val()) + if !ok { + base.Fatalf("Uint64Val(%v)", n) + } + return x +} + +// BoolVal returns n as a bool. +// n must be a boolean constant. +func BoolVal(n Node) bool { + if !IsConst(n, constant.Bool) { + base.Fatalf("BoolVal(%v)", n) + } + return constant.BoolVal(n.Val()) +} + +// StringVal returns the value of a literal string Node as a string. +// n must be a string constant. +func StringVal(n Node) string { + if !IsConst(n, constant.String) { + base.Fatalf("StringVal(%v)", n) + } + return constant.StringVal(n.Val()) +} From a2058bac21f40925a33d7f99622c967b65827f29 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 2 Dec 2020 19:26:56 -0800 Subject: [PATCH 111/212] [dev.regabi] cmd/compile: add ConstExpr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, we represent constant-folded expressions with Name, which is suboptimal because Name has a lot of fields to support declared names (which are irrelevant to constant-folded expressions), while constant expressions are fairly common. This CL introduces a new lightweight ConstExpr type that simply wraps an existing expression and associates it with a value. Passes buildall w/ toolstash -cmp. name old time/op new time/op delta Template 252ms ± 3% 254ms ± 1% ~ (p=0.821 n=12+10) Unicode 120ms ± 2% 107ms ± 7% -11.09% (p=0.000 n=12+12) GoTypes 918ms ± 2% 918ms ± 1% ~ (p=0.974 n=12+10) Compiler 5.19s ± 1% 5.18s ± 0% ~ (p=0.190 n=12+11) SSA 12.4s ± 1% 12.3s ± 1% ~ (p=0.283 n=10+12) Flate 152ms ± 2% 148ms ± 4% -2.68% (p=0.007 n=10+12) GoParser 212ms ± 1% 211ms ± 2% ~ (p=0.674 n=10+12) Reflect 543ms ± 3% 542ms ± 3% ~ (p=0.799 n=12+12) Tar 224ms ± 2% 225ms ± 2% ~ (p=0.378 n=12+12) XML 292ms ± 1% 299ms ± 3% +2.18% (p=0.006 n=10+12) name old user-time/op new user-time/op delta Template 243ms ± 4% 244ms ± 5% ~ (p=0.887 n=12+12) Unicode 112ms ± 6% 100ms ±10% -10.76% (p=0.000 n=12+12) GoTypes 898ms ± 3% 895ms ± 3% ~ (p=0.671 n=12+12) Compiler 5.10s ± 1% 5.08s ± 1% ~ (p=0.104 n=12+11) SSA 12.2s ± 2% 12.1s ± 1% ~ (p=0.487 n=11+12) Flate 144ms ± 6% 145ms ± 5% ~ (p=0.695 n=12+11) GoParser 205ms ± 5% 204ms ± 3% ~ (p=0.514 n=12+12) Reflect 528ms ± 3% 531ms ± 4% ~ (p=0.630 n=12+12) Tar 218ms ± 4% 219ms ± 3% ~ (p=0.843 n=12+12) XML 284ms ± 5% 291ms ± 5% ~ (p=0.069 n=11+12) name old alloc/op new alloc/op delta Template 37.0MB ± 0% 36.7MB ± 0% -0.72% (p=0.000 n=12+12) Unicode 31.9MB ± 0% 29.5MB ± 0% -7.60% (p=0.000 n=12+12) GoTypes 119MB ± 0% 118MB ± 0% -0.40% (p=0.000 n=12+12) Compiler 629MB ± 0% 626MB ± 0% -0.36% (p=0.000 n=11+12) SSA 1.45GB ± 0% 1.43GB ± 0% -0.78% (p=0.000 n=12+12) Flate 22.2MB ± 0% 21.9MB ± 0% -1.12% (p=0.000 n=12+12) GoParser 29.4MB ± 0% 29.3MB ± 0% -0.36% (p=0.000 n=12+12) Reflect 76.1MB ± 0% 75.8MB ± 0% -0.38% (p=0.000 n=12+12) Tar 33.4MB ± 0% 33.2MB ± 0% -0.61% (p=0.000 n=12+12) XML 43.2MB ± 0% 42.8MB ± 0% -1.03% (p=0.000 n=11+12) name old allocs/op new allocs/op delta Template 375k ± 0% 375k ± 0% ~ (p=0.854 n=12+12) Unicode 300k ± 0% 300k ± 0% ~ (p=0.766 n=12+12) GoTypes 1.30M ± 0% 1.30M ± 0% ~ (p=0.272 n=12+12) Compiler 5.89M ± 0% 5.89M ± 0% ~ (p=0.478 n=12+12) SSA 14.0M ± 0% 14.0M ± 0% ~ (p=0.266 n=12+12) Flate 226k ± 0% 226k ± 0% ~ (p=0.898 n=12+12) GoParser 313k ± 0% 313k ± 0% -0.01% (p=0.042 n=12+11) Reflect 971k ± 0% 971k ± 0% ~ (p=0.080 n=12+12) Tar 342k ± 0% 342k ± 0% ~ (p=0.600 n=12+12) XML 416k ± 0% 416k ± 0% ~ (p=0.217 n=11+12) name old maxRSS/op new maxRSS/op delta Template 43.1M ± 5% 42.5M ± 5% ~ (p=0.086 n=12+12) Unicode 49.4M ± 2% 47.0M ± 2% -4.88% (p=0.000 n=12+12) GoTypes 85.3M ± 2% 84.6M ± 2% -0.84% (p=0.047 n=11+11) Compiler 394M ± 3% 386M ± 2% -1.97% (p=0.000 n=10+11) SSA 847M ± 4% 821M ± 2% -2.98% (p=0.000 n=11+12) Flate 36.0M ± 7% 35.2M ± 7% ~ (p=0.128 n=12+12) GoParser 39.4M ± 7% 39.5M ± 4% ~ (p=0.413 n=12+11) Reflect 64.0M ± 3% 63.6M ± 3% ~ (p=0.413 n=11+12) Tar 43.3M ± 5% 43.3M ± 5% ~ (p=0.503 n=12+12) XML 47.6M ± 4% 46.4M ± 2% -2.46% (p=0.013 n=11+12) Change-Id: If5781be346351c30b2228807211b5e57f777c506 Reviewed-on: https://go-review.googlesource.com/c/go/+/275033 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/const.go | 27 +++++++-------------------- src/cmd/compile/internal/ir/expr.go | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 8771d82cfa..9aa65f97b6 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -115,22 +115,12 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir return n } - if n.Op() == ir.OLITERAL || n.Op() == ir.ONIL { - // Can't always set n.Type directly on OLITERAL nodes. - // See discussion on CL 20813. - old := n - n = ir.Copy(old) - if old.Op() == ir.OLITERAL { - // Keep untyped constants in their original untyped syntax for error messages. - n.(ir.OrigNode).SetOrig(old) - } - } - // Nil is technically not a constant, so handle it specially. if n.Type().Kind() == types.TNIL { if n.Op() != ir.ONIL { base.Fatalf("unexpected op: %v (%v)", n, n.Op()) } + n = ir.Copy(n) if t == nil { base.Errorf("use of untyped nil") n.SetDiag(true) @@ -158,10 +148,11 @@ func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir case ir.OLITERAL: v := convertVal(n.Val(), t, explicit) if v.Kind() == constant.Unknown { + n = ir.NewConstExpr(n.Val(), n) break } + n = ir.NewConstExpr(v, n) n.SetType(t) - n.SetVal(v) return n case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.OREAL, ir.OIMAG: @@ -541,8 +532,9 @@ func evalConst(n ir.Node) ir.Node { i2++ } - nl := origConst(s[i], constant.MakeString(strings.Join(strs, ""))) - nl.(ir.OrigNode).SetOrig(nl) // it's bigger than just s[i] + nl := ir.Copy(n) + nl.PtrList().Set(s[i:i2]) + nl = origConst(nl, constant.MakeString(strings.Join(strs, ""))) newList = append(newList, nl) i = i2 - 1 } else { @@ -645,12 +637,7 @@ func origConst(n ir.Node, v constant.Value) ir.Node { return n } - orig := n - n = ir.NodAt(orig.Pos(), ir.OLITERAL, nil, nil) - n.(ir.OrigNode).SetOrig(orig) - n.SetType(orig.Type()) - n.SetVal(v) - return n + return ir.NewConstExpr(v, n) } func origBoolConst(n ir.Node, v bool) ir.Node { diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 2a7211cfda..412b7a18f0 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -9,6 +9,7 @@ import ( "cmd/compile/internal/types" "cmd/internal/src" "fmt" + "go/constant" ) // A miniStmt is a miniNode with extra fields common to expressions. @@ -300,6 +301,30 @@ func (n *CompLitExpr) SetOp(op Op) { } } +type ConstExpr struct { + miniExpr + val constant.Value + orig Node +} + +func NewConstExpr(val constant.Value, orig Node) Node { + n := &ConstExpr{orig: orig, val: val} + n.op = OLITERAL + n.pos = orig.Pos() + n.SetType(orig.Type()) + n.SetTypecheck(orig.Typecheck()) + n.SetDiag(orig.Diag()) + return n +} + +func (n *ConstExpr) String() string { return fmt.Sprint(n) } +func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ConstExpr) rawCopy() Node { c := *n; return &c } +func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() } +func (n *ConstExpr) Orig() Node { return n.orig } +func (n *ConstExpr) SetOrig(orig Node) { n.orig = orig } +func (n *ConstExpr) Val() constant.Value { return n.val } + // A ConvExpr is a conversion Type(X). // It may end up being a value or a type. type ConvExpr struct { From b1369d5862bc78eaa902ae637c874e6a6133f1f9 Mon Sep 17 00:00:00 2001 From: Jonathan Albrecht Date: Wed, 2 Dec 2020 10:44:10 -0500 Subject: [PATCH 112/212] math/big: remove the s390x assembly for shlVU and shrVU The s390x assembly for shlVU does a forward copy when the shift amount s is 0. This causes corruption of the result z when z is aliased to the input x. This fix removes the s390x assembly for both shlVU and shrVU so the pure go implementations will be used. Test cases have been added to the existing TestShiftOverlap test to cover shift values of 0, 1 and (_W - 1). Fixes #42838 Change-Id: I75ca0e98f3acfaa6366a26355dcd9dd82499a48b Reviewed-on: https://go-review.googlesource.com/c/go/+/274442 Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Reviewed-by: Matthew Dempsky Trust: Robert Griesemer --- src/math/big/arith_s390x.s | 192 +------------------------------------ src/math/big/arith_test.go | 53 +++++++++- 2 files changed, 53 insertions(+), 192 deletions(-) diff --git a/src/math/big/arith_s390x.s b/src/math/big/arith_s390x.s index 242aca7434..caa4db0829 100644 --- a/src/math/big/arith_s390x.s +++ b/src/math/big/arith_s390x.s @@ -693,199 +693,11 @@ returnC: // func shlVU(z, x []Word, s uint) (c Word) TEXT ·shlVU(SB), NOSPLIT, $0 - MOVD z_len+8(FP), R5 - MOVD $0, R0 - SUB $1, R5 // n-- - BLT X8b // n < 0 (n <= 0) + BR ·shlVU_g(SB) - // n > 0 - MOVD s+48(FP), R4 - CMPBEQ R0, R4, Z80 // handle 0 case beq - MOVD $64, R6 - CMPBEQ R6, R4, Z864 // handle 64 case beq - MOVD z+0(FP), R2 - MOVD x+24(FP), R8 - SLD $3, R5 // n = n*8 - SUB R4, R6, R7 - MOVD (R8)(R5*1), R10 // w1 = x[i-1] - SRD R7, R10, R3 - MOVD R3, c+56(FP) - - MOVD $0, R1 // i = 0 - BR E8 - - // i < n-1 -L8: - MOVD R10, R3 // w = w1 - MOVD -8(R8)(R5*1), R10 // w1 = x[i+1] - - SLD R4, R3 // w<>ŝ - SRD R7, R10, R6 - OR R6, R3 - MOVD R3, (R2)(R5*1) // z[i] = w<>ŝ - SUB $8, R5 // i-- - -E8: - CMPBGT R5, R0, L8 // i < n-1 - - // i >= n-1 -X8a: - SLD R4, R10 // w1<= n-1 - MOVD R10, (R2)(R5*1) - RET - -Z864: - MOVD z+0(FP), R2 - MOVD x+24(FP), R8 - SLD $3, R5 // n = n*8 - MOVD (R8)(R5*1), R3 // w1 = x[n-1] - MOVD R3, c+56(FP) // z[i] = x[n-1] - - BR E864 - - // i < n-1 -L864: - MOVD -8(R8)(R5*1), R3 - - MOVD R3, (R2)(R5*1) // z[i] = x[n-1] - SUB $8, R5 // i-- - -E864: - CMPBGT R5, R0, L864 // i < n-1 - - MOVD R0, (R2) // z[n-1] = 0 - RET - -// CX = R4, r8 = r8, r10 = r2 , r11 = r5, DX = r3, AX = r10 , BX = R1 , 64-count = r7 (R0 set to 0) temp = R6 // func shrVU(z, x []Word, s uint) (c Word) TEXT ·shrVU(SB), NOSPLIT, $0 - MOVD z_len+8(FP), R5 - MOVD $0, R0 - SUB $1, R5 // n-- - BLT X9b // n < 0 (n <= 0) - - // n > 0 - MOVD s+48(FP), R4 - CMPBEQ R0, R4, ZB0 // handle 0 case beq - MOVD $64, R6 - CMPBEQ R6, R4, ZB64 // handle 64 case beq - MOVD z+0(FP), R2 - MOVD x+24(FP), R8 - SLD $3, R5 // n = n*8 - SUB R4, R6, R7 - MOVD (R8), R10 // w1 = x[0] - SLD R7, R10, R3 - MOVD R3, c+56(FP) - - MOVD $0, R1 // i = 0 - BR E9 - - // i < n-1 -L9: - MOVD R10, R3 // w = w1 - MOVD 8(R8)(R1*1), R10 // w1 = x[i+1] - - SRD R4, R3 // w>>s | w1<>s | w1<= n-1 -X9a: - SRD R4, R10 // w1>>s - MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s - RET - -X9b: - MOVD R0, c+56(FP) - RET - -ZB0: - MOVD z+0(FP), R2 - MOVD x+24(FP), R8 - SLD $3, R5 // n = n*8 - - MOVD (R8), R10 // w1 = x[0] - MOVD $0, R3 // R10 << 64 - MOVD R3, c+56(FP) - - MOVD $0, R1 // i = 0 - BR E9Z - - // i < n-1 -L9Z: - MOVD R10, R3 // w = w1 - MOVD 8(R8)(R1*1), R10 // w1 = x[i+1] - - MOVD R3, (R2)(R1*1) // z[i] = w>>s | w1<= n-1 - MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s - RET - -ZB64: - MOVD z+0(FP), R2 - MOVD x+24(FP), R8 - SLD $3, R5 // n = n*8 - MOVD (R8), R3 // w1 = x[0] - MOVD R3, c+56(FP) - - MOVD $0, R1 // i = 0 - BR E964 - - // i < n-1 -L964: - MOVD 8(R8)(R1*1), R3 // w1 = x[i+1] - - MOVD R3, (R2)(R1*1) // z[i] = w>>s | w1<= n-1 - MOVD $0, R10 // w1>>s - MOVD R10, (R2)(R5*1) // z[n-1] = w1>>s - RET + BR ·shrVU_g(SB) // CX = R4, r8 = r8, r9=r9, r10 = r2 , r11 = r5, DX = r3, AX = r6 , BX = R1 , (R0 set to 0) + use R11 + use R7 for i // func mulAddVWW(z, x []Word, y, r Word) (c Word) diff --git a/src/math/big/arith_test.go b/src/math/big/arith_test.go index 808d178459..2aca0effde 100644 --- a/src/math/big/arith_test.go +++ b/src/math/big/arith_test.go @@ -285,20 +285,56 @@ type argVU struct { m string // message. } +var argshlVUIn = []Word{1, 2, 4, 8, 16, 32, 64, 0, 0, 0} +var argshlVUr0 = []Word{1, 2, 4, 8, 16, 32, 64} +var argshlVUr1 = []Word{2, 4, 8, 16, 32, 64, 128} +var argshlVUrWm1 = []Word{1 << (_W - 1), 0, 1, 2, 4, 8, 16} + var argshlVU = []argVU{ // test cases for shlVU {[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0}, 7, 0, 0, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "complete overlap of shlVU"}, {[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0}, 7, 0, 3, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "partial overlap by half of shlVU"}, {[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0, 0, 0, 0}, 7, 0, 6, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "partial overlap by 1 Word of shlVU"}, {[]Word{1, _M, _M, _M, _M, _M, 3 << (_W - 2), 0, 0, 0, 0, 0, 0, 0, 0}, 7, 0, 7, 1, []Word{2, _M - 1, _M, _M, _M, _M, 1<<(_W-1) + 1}, 1, "no overlap of shlVU"}, + // additional test cases with shift values of 0, 1 and (_W-1) + {argshlVUIn, 7, 0, 0, 0, argshlVUr0, 0, "complete overlap of shlVU and shift of 0"}, + {argshlVUIn, 7, 0, 0, 1, argshlVUr1, 0, "complete overlap of shlVU and shift of 1"}, + {argshlVUIn, 7, 0, 0, _W - 1, argshlVUrWm1, 32, "complete overlap of shlVU and shift of _W - 1"}, + {argshlVUIn, 7, 0, 1, 0, argshlVUr0, 0, "partial overlap by 6 Words of shlVU and shift of 0"}, + {argshlVUIn, 7, 0, 1, 1, argshlVUr1, 0, "partial overlap by 6 Words of shlVU and shift of 1"}, + {argshlVUIn, 7, 0, 1, _W - 1, argshlVUrWm1, 32, "partial overlap by 6 Words of shlVU and shift of _W - 1"}, + {argshlVUIn, 7, 0, 2, 0, argshlVUr0, 0, "partial overlap by 5 Words of shlVU and shift of 0"}, + {argshlVUIn, 7, 0, 2, 1, argshlVUr1, 0, "partial overlap by 5 Words of shlVU and shift of 1"}, + {argshlVUIn, 7, 0, 2, _W - 1, argshlVUrWm1, 32, "partial overlap by 5 Words of shlVU abd shift of _W - 1"}, + {argshlVUIn, 7, 0, 3, 0, argshlVUr0, 0, "partial overlap by 4 Words of shlVU and shift of 0"}, + {argshlVUIn, 7, 0, 3, 1, argshlVUr1, 0, "partial overlap by 4 Words of shlVU and shift of 1"}, + {argshlVUIn, 7, 0, 3, _W - 1, argshlVUrWm1, 32, "partial overlap by 4 Words of shlVU and shift of _W - 1"}, } +var argshrVUIn = []Word{0, 0, 0, 1, 2, 4, 8, 16, 32, 64} +var argshrVUr0 = []Word{1, 2, 4, 8, 16, 32, 64} +var argshrVUr1 = []Word{0, 1, 2, 4, 8, 16, 32} +var argshrVUrWm1 = []Word{4, 8, 16, 32, 64, 128, 0} + var argshrVU = []argVU{ // test cases for shrVU {[]Word{0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 1, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "complete overlap of shrVU"}, {[]Word{0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 4, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "partial overlap by half of shrVU"}, {[]Word{0, 0, 0, 0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 7, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "partial overlap by 1 Word of shrVU"}, {[]Word{0, 0, 0, 0, 0, 0, 0, 0, 3, _M, _M, _M, _M, _M, 1 << (_W - 1)}, 7, 8, 1, 1, []Word{1<<(_W-1) + 1, _M, _M, _M, _M, _M >> 1, 1 << (_W - 2)}, 1 << (_W - 1), "no overlap of shrVU"}, + // additional test cases with shift values of 0, 1 and (_W-1) + {argshrVUIn, 7, 3, 3, 0, argshrVUr0, 0, "complete overlap of shrVU and shift of 0"}, + {argshrVUIn, 7, 3, 3, 1, argshrVUr1, 1 << (_W - 1), "complete overlap of shrVU and shift of 1"}, + {argshrVUIn, 7, 3, 3, _W - 1, argshrVUrWm1, 2, "complete overlap of shrVU and shift of _W - 1"}, + {argshrVUIn, 7, 3, 2, 0, argshrVUr0, 0, "partial overlap by 6 Words of shrVU and shift of 0"}, + {argshrVUIn, 7, 3, 2, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 6 Words of shrVU and shift of 1"}, + {argshrVUIn, 7, 3, 2, _W - 1, argshrVUrWm1, 2, "partial overlap by 6 Words of shrVU and shift of _W - 1"}, + {argshrVUIn, 7, 3, 1, 0, argshrVUr0, 0, "partial overlap by 5 Words of shrVU and shift of 0"}, + {argshrVUIn, 7, 3, 1, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 5 Words of shrVU and shift of 1"}, + {argshrVUIn, 7, 3, 1, _W - 1, argshrVUrWm1, 2, "partial overlap by 5 Words of shrVU and shift of _W - 1"}, + {argshrVUIn, 7, 3, 0, 0, argshrVUr0, 0, "partial overlap by 4 Words of shrVU and shift of 0"}, + {argshrVUIn, 7, 3, 0, 1, argshrVUr1, 1 << (_W - 1), "partial overlap by 4 Words of shrVU and shift of 1"}, + {argshrVUIn, 7, 3, 0, _W - 1, argshrVUrWm1, 2, "partial overlap by 4 Words of shrVU and shift of _W - 1"}, } func testShiftFunc(t *testing.T, f func(z, x []Word, s uint) Word, a argVU) { @@ -335,11 +371,24 @@ func TestIssue31084(t *testing.T) { // compute 10^n via 5^n << n. const n = 165 p := nat(nil).expNN(nat{5}, nat{n}, nil) - p = p.shl(p, uint(n)) + p = p.shl(p, n) got := string(p.utoa(10)) want := "1" + strings.Repeat("0", n) if got != want { - t.Errorf("shl(%v, %v)\n\tgot %s; want %s\n", p, uint(n), got, want) + t.Errorf("shl(%v, %v)\n\tgot %s\n\twant %s", p, n, got, want) + } +} + +const issue42838Value = "159309191113245227702888039776771180559110455519261878607388585338616290151305816094308987472018268594098344692611135542392730712890625" + +func TestIssue42838(t *testing.T) { + const s = 192 + z, _, _, _ := nat(nil).scan(strings.NewReader(issue42838Value), 0, false) + z = z.shl(z, s) + got := string(z.utoa(10)) + want := "1" + strings.Repeat("0", s) + if got != want { + t.Errorf("shl(%v, %v)\n\tgot %s\n\twant %s", z, s, got, want) } } From 9b0e8a2c95714e1ddaea8cddb7c37f67ff00144a Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 3 Dec 2020 12:12:23 -0500 Subject: [PATCH 113/212] doc/go1.16: tidy darwin/arm64 port section For #40700. Change-Id: I4f5d93e4ed13864f8b7dcc772d7ae074772b5a3f Reviewed-on: https://go-review.googlesource.com/c/go/+/275175 Trust: Austin Clements Reviewed-by: Cherry Zhang --- doc/go1.16.html | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 88feab30c5..1628c6f437 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -31,7 +31,7 @@ Do not send CLs removing the interior tags from such phrases.

Ports

-

Darwin

+

Darwin and iOS

Go 1.16 adds support of 64-bit ARM architecture on macOS (also known as @@ -43,15 +43,19 @@ Do not send CLs removing the interior tags from such phrases.

- The iOS port, which was previously darwin/arm64, is now - moved to ios/arm64. GOOS=ios implies the + The iOS port, which was previously darwin/arm64, has + been renamed to ios/arm64. GOOS=ios + implies the darwin build tag, just as GOOS=android - implies the linux build tag. + implies the linux build tag. This change should be + transparent to anyone using gomobile to build iOS apps.

- The ios/amd64 port is added, targetting the iOS simulator - running on AMD64-based macOS. + Go 1.16 adds an ios/amd64 port, which targets the iOS + simulator running on AMD64-based macOS. Previously this was + unofficially supported through darwin/amd64 with + the ios build tag set.

NetBSD

From bdc9a837e914a3bd684ef3a24588b2627b1c6c04 Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Tue, 1 Dec 2020 14:19:57 +0100 Subject: [PATCH 114/212] doc/go1.16: add path, path/filepath changes to release notes For #40700 Fixes #42910 Change-Id: Ie380f5a03930d20dd5001c4cc184cadf2db33de7 Reviewed-on: https://go-review.googlesource.com/c/go/+/274475 Trust: Alberto Donizetti Reviewed-by: Dmitri Shuralyov --- doc/go1.16.html | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 1628c6f437..f3bc2fb4d0 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -732,16 +732,24 @@ Do not send CLs removing the interior tags from such phrases.
path
-

- TODO: https://golang.org/cl/264397: validate patterns in Match, Glob +

+ The Match and Glob functions now + return an error if the unmatched part of the pattern has a + syntax error. Previously, the functions returned early on a failed + match, and thus did not report any later syntax error in the + pattern.

path/filepath
-

- TODO: https://golang.org/cl/264397: validate patterns in Match, Glob +

+ The Match and Glob functions now + return an error if the unmatched part of the pattern has a + syntax error. Previously, the functions returned early on a failed + match, and thus did not report any later syntax error in the + pattern.

From 351bc2f38c4291c01299c2add16f1f5a96e54bb4 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 2 Dec 2020 21:38:20 -0800 Subject: [PATCH 115/212] [dev.regabi] cmd/compile: store types.Field on {Selector,CallPart}Expr It's useful to have quick access to the types.Field that a given selector or method value expression refer to. Previously we abused Opt for this, but couldn't do that for OCALLPART because escape analysis uses Opt. Now that we have more flexibility, we can simply add additional pointer fields for this. This also allows getting rid of an unneeded ONAME node for OCALLPART. Passes buildall w/ toolstash -cmp. Change-Id: I980d7bdb19abfd0b6f58a232876861b88dee1e47 Reviewed-on: https://go-review.googlesource.com/c/go/+/275034 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/closure.go | 15 ++------------- src/cmd/compile/internal/gc/iexport.go | 3 +-- src/cmd/compile/internal/gc/inl.go | 3 +++ src/cmd/compile/internal/gc/typecheck.go | 14 +++++++------- src/cmd/compile/internal/gc/walk.go | 2 +- src/cmd/compile/internal/ir/expr.go | 15 ++++++++------- src/cmd/compile/internal/ir/fmt.go | 4 ++-- 7 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index a5441a037a..01e5a953de 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -427,7 +427,7 @@ func typecheckpartialcall(dot ir.Node, sym *types.Sym) *ir.CallPartExpr { fn := makepartialcall(dot, dot.Type(), sym) fn.SetWrapper(true) - return ir.NewCallPartExpr(dot.Pos(), dot.Left(), NewName(sym), fn) + return ir.NewCallPartExpr(dot.Pos(), dot.Left(), dot.(*ir.SelectorExpr).Selection, fn) } // makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed @@ -565,16 +565,5 @@ func walkpartialcall(n *ir.CallPartExpr, init *ir.Nodes) ir.Node { // callpartMethod returns the *types.Field representing the method // referenced by method value n. func callpartMethod(n ir.Node) *types.Field { - if n.Op() != ir.OCALLPART { - base.Fatalf("expected OCALLPART, got %v", n) - } - - // TODO(mdempsky): Optimize this. If necessary, - // makepartialcall could save m for us somewhere. - var m *types.Field - if lookdot0(n.Right().Sym(), n.Left().Type(), &m, false) != 1 { - base.Fatalf("failed to find field for OCALLPART") - } - - return m + return n.(*ir.CallPartExpr).Method } diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 85518bc939..bb6f2b11e6 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -1290,8 +1290,7 @@ func (w *exportWriter) expr(n ir.Node) { w.op(ir.OXDOT) w.pos(n.Pos()) w.expr(n.Left()) - // Right node should be ONAME - w.selector(n.Right().Sym()) + w.selector(n.Sym()) case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH: w.op(ir.OXDOT) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 42125f38f3..64f1b062be 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -430,6 +430,9 @@ func (v *hairyVisitor) visit(n ir.Node) bool { // In any event, let the visitList(n.List()) below take care of the statements, // and don't charge for the OBLOCK itself. The ++ undoes the -- below. v.budget++ + + case ir.OCALLPART: + v.budget-- // Hack for toolstash -cmp. } v.budget-- diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index b19481311b..e2100481aa 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2385,7 +2385,7 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) { me.SetType(methodfunc(m.Type, n.Left().Type())) me.SetOffset(0) me.SetClass(ir.PFUNC) - me.SetOpt(m) + me.(*ir.MethodExpr).Method = m // Issue 25065. Make sure that we emit the symbol for a local method. if base.Ctxt.Flag_dynlink && !inimport && (t.Sym() == nil || t.Sym().Pkg == ir.LocalPkg) { @@ -2448,10 +2448,8 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field { } n.SetOp(ir.ODOTINTER) - } else { - n.SetOpt(f1) } - + n.(*ir.SelectorExpr).Selection = f1 return f1 } @@ -2507,7 +2505,7 @@ func lookdot(n ir.Node, t *types.Type, dostrcmp int) *types.Field { n.SetOffset(f2.Offset) n.SetType(f2.Type) n.SetOp(ir.ODOTMETH) - n.SetOpt(f2) + n.(*ir.SelectorExpr).Selection = f2 return f2 } @@ -3933,8 +3931,10 @@ func methodExprName(n ir.Node) *ir.Name { // MethodFunc is like MethodName, but returns the types.Field instead. func methodExprFunc(n ir.Node) *types.Field { switch n.Op() { - case ir.ODOTMETH, ir.OMETHEXPR: - return n.Opt().(*types.Field) + case ir.ODOTMETH: + return n.(*ir.SelectorExpr).Selection + case ir.OMETHEXPR: + return n.(*ir.MethodExpr).Method case ir.OCALLPART: return callpartMethod(n) } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index ce7de1396b..3d22c66d90 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -3757,7 +3757,7 @@ func usefield(n ir.Node) { if t.IsPtr() { t = t.Elem() } - field := n.Opt().(*types.Field) + field := n.(*ir.SelectorExpr).Selection if field == nil { base.Fatalf("usefield %v %v without paramfld", n.Left().Type(), n.Sym()) } diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 412b7a18f0..18d85a01df 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -205,10 +205,10 @@ type CallPartExpr struct { miniExpr fn *Func X Node - Method *Name + Method *types.Field } -func NewCallPartExpr(pos src.XPos, x Node, method *Name, fn *Func) *CallPartExpr { +func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallPartExpr { n := &CallPartExpr{fn: fn, X: x, Method: method} n.op = OCALLPART n.pos = pos @@ -222,9 +222,8 @@ func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *CallPartExpr) rawCopy() Node { c := *n; return &c } func (n *CallPartExpr) Func() *Func { return n.fn } func (n *CallPartExpr) Left() Node { return n.X } -func (n *CallPartExpr) Right() Node { return n.Method } +func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym } func (n *CallPartExpr) SetLeft(x Node) { n.X = x } -func (n *CallPartExpr) SetRight(x Node) { n.Method = x.(*Name) } // A ClosureExpr is a function literal expression. type ClosureExpr struct { @@ -499,6 +498,7 @@ type MethodExpr struct { sym *types.Sym offset int64 class Class + Method *types.Field } func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr { @@ -596,9 +596,10 @@ func (n *ResultExpr) SetOffset(x int64) { n.offset = x } // A SelectorExpr is a selector expression X.Sym. type SelectorExpr struct { miniExpr - X Node - Sel *types.Sym - offset int64 + X Node + Sel *types.Sym + offset int64 + Selection *types.Field } func NewSelectorExpr(pos src.XPos, x Node, sel *types.Sym) *SelectorExpr { diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 9486d8b021..45a66a2290 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1382,11 +1382,11 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { case OCALLPART: exprFmt(n.Left(), s, nprec, mode) - if n.Right() == nil || n.Right().Sym() == nil { + if n.Sym() == nil { fmt.Fprint(s, ".") return } - mode.Fprintf(s, ".%0S", n.Right().Sym()) + mode.Fprintf(s, ".%0S", n.Sym()) case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: exprFmt(n.Left(), s, nprec, mode) From 7f5a3196c92c9fbe6d691d022202cbbda6e7a431 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 3 Dec 2020 11:09:07 -0500 Subject: [PATCH 116/212] cmd/go/internal/modload: rename constants to reflect that lazy loading is not yet implemented Updates #36460 Updates #42288 Change-Id: I82a3b7e97a8e2f83bae2318ca9fb5c38c0c811cd Reviewed-on: https://go-review.googlesource.com/c/go/+/275172 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod TryBot-Result: Go Bot --- src/cmd/go/internal/modload/modfile.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index ede07be4bf..eb05e9f9c9 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -25,10 +25,11 @@ import ( "golang.org/x/mod/semver" ) -// lazyLoadingVersion is the Go version (plus leading "v") at which lazy module -// loading takes effect. -const lazyLoadingVersionV = "v1.16" -const go116EnableLazyLoading = true +// narrowAllVersionV is the Go version (plus leading "v") at which the +// module-module "all" pattern no longer closes over the dependencies of +// tests outside of the main module. +const narrowAllVersionV = "v1.16" +const go116EnableNarrowAll = true var modFile *modfile.File @@ -296,10 +297,10 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd // (Otherwise — as in Go 1.16+ — the "all" pattern includes only the packages // transitively *imported by* the packages and tests in the main module.) func (i *modFileIndex) allPatternClosesOverTests() bool { - if !go116EnableLazyLoading { + if !go116EnableNarrowAll { return true } - if i != nil && semver.Compare(i.goVersionV, lazyLoadingVersionV) < 0 { + if i != nil && semver.Compare(i.goVersionV, narrowAllVersionV) < 0 { // The module explicitly predates the change in "all" for lazy loading, so // continue to use the older interpretation. (If i == nil, we not in any // module at all and should use the latest semantics.) From bacb307b80747deaf6a017f5b3cee4e3cb115f61 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 3 Dec 2020 12:02:00 -0800 Subject: [PATCH 117/212] test: match gofrontend error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixedbugs/bug487.go:17:17: error: function result count mismatch fixedbugs/bug487.go:18:16: error: function result count mismatch fixedbugs/issue6977.go:37:26: error: duplicate method ‘m’ fixedbugs/issue6977.go:38:21: error: duplicate method ‘m’ fixedbugs/issue6977.go:39:26: error: duplicate method ‘m’ fixedbugs/issue6977.go:40:21: error: duplicate method ‘m’ Change-Id: Ie3c8a4650cd8f4c239bdceac25dc188a6a50ca34 Reviewed-on: https://go-review.googlesource.com/c/go/+/275178 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Cherry Zhang Reviewed-by: Than McIntosh --- test/fixedbugs/bug487.go | 4 ++-- test/fixedbugs/issue6977.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/fixedbugs/bug487.go b/test/fixedbugs/bug487.go index ab61a19a94..e60af6c8e2 100644 --- a/test/fixedbugs/bug487.go +++ b/test/fixedbugs/bug487.go @@ -14,8 +14,8 @@ func G() (int, int, int) { } func F() { - a, b := G() // ERROR "assignment mismatch" - a, b = G() // ERROR "assignment mismatch" + a, b := G() // ERROR "mismatch" + a, b = G() // ERROR "mismatch" _, _ = a, b } diff --git a/test/fixedbugs/issue6977.go b/test/fixedbugs/issue6977.go index 0f657eec41..4525e406b8 100644 --- a/test/fixedbugs/issue6977.go +++ b/test/fixedbugs/issue6977.go @@ -34,7 +34,7 @@ type U3 interface { M; m() } type U4 interface { M; M; M } type U5 interface { U1; U2; U3; U4 } -type U6 interface { m(); m() } // ERROR "duplicate method m" -type U7 interface { M32; m() } // ERROR "duplicate method m" -type U8 interface { m(); M32 } // ERROR "duplicate method m" -type U9 interface { M32; M64 } // ERROR "duplicate method m" +type U6 interface { m(); m() } // ERROR "duplicate method .*m" +type U7 interface { M32; m() } // ERROR "duplicate method .*m" +type U8 interface { m(); M32 } // ERROR "duplicate method .*m" +type U9 interface { M32; M64 } // ERROR "duplicate method .*m" From 4eb7ceba067cf4f3851f2eaf63c9929386594adf Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 3 Dec 2020 13:53:41 -0500 Subject: [PATCH 118/212] doc/go1.16: update runtime and compiler sections This resolves all TODOs for the runtime and compiler and mentions several other changes. For #40700. Fixes #42892. Fixes #42894. Change-Id: I18d14cfe572baf679ecf8b0a4e82c4b866da5a04 Reviewed-on: https://go-review.googlesource.com/c/go/+/275176 Trust: Austin Clements Reviewed-by: Matthew Dempsky --- doc/go1.16.html | 54 +++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index f3bc2fb4d0..462f86fe09 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -286,6 +286,17 @@ Do not send CLs removing the interior tags from such phrases. See the package documentation for more details.

+

+ Setting the GODEBUG environment variable + to inittrace=1 now causes the runtime to emit a single + line to standard error for each package init, + summarizing its execution time and memory allocation. This trace can + be used to find bottlenecks or regressions in Go startup + performance. + The GODEBUG< + documentation describes the format. +

+

On Linux, the runtime now defaults to releasing memory to the operating system promptly (using MADV_DONTNEED), rather @@ -298,10 +309,19 @@ Do not send CLs removing the interior tags from such phrases. variable.

+

+ The race detector's model for channel operations now more precisely + follows the Go memory model. As a result, it + may report now races that it previously missed. +

+

Compiler

-

- TODO +

+ The compiler can now inline functions with + non-labeled for loops, method values, and type + switches. The inliner can also detect more indirect calls where + inlining is possible.

Linker

@@ -762,22 +782,6 @@ Do not send CLs removing the interior tags from such phrases. -
runtime
-
-

- TODO: https://golang.org/cl/37222: make stack traces of endless recursion print only top and bottom 50 -

- -

- TODO: https://golang.org/cl/242258: add 24 byte allocation size class -

- -

- TODO: https://golang.org/cl/254659: implement GODEBUG=inittrace=1 support -

-
-
-
runtime/debug

@@ -804,12 +808,22 @@ Do not send CLs removing the interior tags from such phrases.

syscall
+

+ NewCallback + and + NewCallbackCDecl + now correctly support callback functions with multiple + sub-uintptr-sized arguments in a row. This may + require changing uses of these functions to eliminate manual + padding between small arguments. +

+

- SysProcAttr on Windows has a new NoInheritHandles field that disables inheriting handles when creating a new process. + SysProcAttr on Windows has a new NoInheritHandles field that disables inheriting handles when creating a new process.

- DLLError on Windows now has an Unwrap function for unwrapping its underlying error. + DLLError on Windows now has an Unwrap function for unwrapping its underlying error.

From b635e4b808bf45ebd66e9f687e18b9af6bd634c1 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 1 Dec 2020 17:24:33 -0500 Subject: [PATCH 119/212] time, runtime: don't set timer when = 0 timer when == 0, in the context of timer0When and timerModifiedEarliest, is a sentinel value meaning there are no timers on the heap. TestCheckRuntimeTimerOverflow reaching into the runtime to set a timer to when = 0 when it is otherwise not possible breaks this invariant. After golang.org/cl/258303, we will no longer detect and run this timer, thus blocking any other timers lower on the heap from running. This manifests as random timers failing to fire in other tests. The need to set this overflowed timer to when = 0 is gone with the old timer proc implementation, so we can simply remove it. Fixes #42424 Change-Id: Iea32100136ad8ec1bedfa77b1e7d9ed868812838 Reviewed-on: https://go-review.googlesource.com/c/go/+/274632 Reviewed-by: Ian Lance Taylor Run-TryBot: Michael Pratt TryBot-Result: Go Bot Trust: Michael Pratt --- src/runtime/time.go | 2 ++ src/time/internal_test.go | 10 ---------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/runtime/time.go b/src/runtime/time.go index 75b66f8492..83d93c5686 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -23,6 +23,8 @@ type timer struct { // Timer wakes up at when, and then at when+period, ... (period > 0 only) // each time calling f(arg, now) in the timer goroutine, so f must be // a well-behaved function and not block. + // + // when must be positive on an active timer. when int64 period int64 f func(interface{}, uintptr) diff --git a/src/time/internal_test.go b/src/time/internal_test.go index 35ce69b228..e70b6f34de 100644 --- a/src/time/internal_test.go +++ b/src/time/internal_test.go @@ -53,18 +53,8 @@ func CheckRuntimeTimerOverflow() { t := NewTimer(1) defer func() { - // Subsequent tests won't work correctly if we don't stop the - // overflow timer and kick the timer proc back into service. - // - // The timer proc is now sleeping and can only be awoken by - // adding a timer to the *beginning* of the heap. We can't - // wake it up by calling NewTimer since other tests may have - // left timers running that should have expired before ours. - // Instead we zero the overflow timer duration and start it - // once more. stopTimer(r) t.Stop() - resetTimer(r, 0) }() // If the test fails, we will hang here until the timeout in the From b78b427be5e4c8a51a2b01b39c1ce6c4f39a93dc Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 2 Dec 2020 12:19:13 -0500 Subject: [PATCH 120/212] runtime, time: strictly enforce when, period constraints timer.when must always be positive. addtimer and modtimer already check that it is non-negative; we expand it to include zero. Also upgrade from pinning bad values to throwing, as these values shouldn't be possible to pass (except as below). timeSleep may overflow timer.nextwhen. This would previously have been pinned by resetForSleep, now we fix it manually. runOneTimer may overflow timer.when when adding timer.period. Detect this and pin to maxWhen. addtimer is now too strict to allow TestOverflowRuntimeTimer to test an overflowed timer. Such a timer should not be possible; to help guard against accidental inclusion siftup / siftdown will check timers as it goes. This has been replaced with tests for period and sleep overflows. Change-Id: I17f9739e27ebcb20d87945c635050316fb8e9226 Reviewed-on: https://go-review.googlesource.com/c/go/+/274853 Trust: Michael Pratt Reviewed-by: Michael Knyszek Reviewed-by: Ian Lance Taylor --- src/runtime/time.go | 31 +++++++++++++++++++++++------ src/time/internal_test.go | 42 ++++++++++++++++----------------------- src/time/sleep.go | 2 ++ src/time/sleep_test.go | 23 ++++++++++++++------- 4 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/runtime/time.go b/src/runtime/time.go index 83d93c5686..d338705b7c 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -187,6 +187,9 @@ func timeSleep(ns int64) { t.f = goroutineReady t.arg = gp t.nextwhen = nanotime() + ns + if t.nextwhen < 0 { // check for overflow. + t.nextwhen = maxWhen + } gopark(resetForSleep, unsafe.Pointer(t), waitReasonSleep, traceEvGoSleep, 1) } @@ -244,10 +247,14 @@ func goroutineReady(arg interface{}, seq uintptr) { // That avoids the risk of changing the when field of a timer in some P's heap, // which could cause the heap to become unsorted. func addtimer(t *timer) { - // when must never be negative; otherwise runtimer will overflow - // during its delta calculation and never expire other runtime timers. - if t.when < 0 { - t.when = maxWhen + // when must be positive. A negative value will cause runtimer to + // overflow during its delta calculation and never expire other runtime + // timers. Zero will cause checkTimers to fail to notice the timer. + if t.when <= 0 { + throw("timer when must be positive") + } + if t.period < 0 { + throw("timer period must be non-negative") } if t.status != timerNoStatus { throw("addtimer called with initialized timer") @@ -408,8 +415,11 @@ func dodeltimer0(pp *p) { // This is called by the netpoll code or time.Ticker.Reset or time.Timer.Reset. // Reports whether the timer was modified before it was run. func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) bool { - if when < 0 { - when = maxWhen + if when <= 0 { + throw("timer when must be positive") + } + if period < 0 { + throw("timer period must be non-negative") } status := uint32(timerNoStatus) @@ -848,6 +858,9 @@ func runOneTimer(pp *p, t *timer, now int64) { // Leave in heap but adjust next time to fire. delta := t.when - now t.when += t.period * (1 + -delta/t.period) + if t.when < 0 { // check for overflow. + t.when = maxWhen + } siftdownTimer(pp.timers, 0) if !atomic.Cas(&t.status, timerRunning, timerWaiting) { badTimer() @@ -1066,6 +1079,9 @@ func siftupTimer(t []*timer, i int) { badTimer() } when := t[i].when + if when <= 0 { + badTimer() + } tmp := t[i] for i > 0 { p := (i - 1) / 4 // parent @@ -1086,6 +1102,9 @@ func siftdownTimer(t []*timer, i int) { badTimer() } when := t[i].when + if when <= 0 { + badTimer() + } tmp := t[i] for { c := i*4 + 1 // left child diff --git a/src/time/internal_test.go b/src/time/internal_test.go index e70b6f34de..ffe54e47c2 100644 --- a/src/time/internal_test.go +++ b/src/time/internal_test.go @@ -33,38 +33,30 @@ var DaysIn = daysIn func empty(arg interface{}, seq uintptr) {} -// Test that a runtimeTimer with a duration so large it overflows -// does not cause other timers to hang. +// Test that a runtimeTimer with a period that would overflow when on +// expiration does not throw or cause other timers to hang. // // This test has to be in internal_test.go since it fiddles with // unexported data structures. -func CheckRuntimeTimerOverflow() { - // We manually create a runtimeTimer to bypass the overflow - // detection logic in NewTimer: we're testing the underlying - // runtime.addtimer function. +func CheckRuntimeTimerPeriodOverflow() { + // We manually create a runtimeTimer with huge period, but that expires + // immediately. The public Timer interface would require waiting for + // the entire period before the first update. r := &runtimeTimer{ - when: runtimeNano() + (1<<63 - 1), - f: empty, - arg: nil, + when: runtimeNano(), + period: 1<<63 - 1, + f: empty, + arg: nil, } startTimer(r) + defer stopTimer(r) - // Start a goroutine that should send on t.C right away. - t := NewTimer(1) - - defer func() { - stopTimer(r) - t.Stop() - }() - - // If the test fails, we will hang here until the timeout in the - // testing package fires, which is 10 minutes. It would be nice to - // catch the problem sooner, but there is no reliable way to guarantee - // that timers are run without doing something involving the scheduler. - // Previous failed attempts have tried calling runtime.Gosched and - // runtime.GC, but neither is reliable. So we fall back to hope: - // We hope we don't hang here. - <-t.C + // If this test fails, we will either throw (when siftdownTimer detects + // bad when on update), or other timers will hang (if the timer in a + // heap is in a bad state). There is no reliable way to test this, but + // we wait on a short timer here as a smoke test (alternatively, timers + // in later tests may hang). + <-After(25 * Millisecond) } var ( diff --git a/src/time/sleep.go b/src/time/sleep.go index 22ffd68282..90d8a18a68 100644 --- a/src/time/sleep.go +++ b/src/time/sleep.go @@ -31,6 +31,8 @@ func when(d Duration) int64 { } t := runtimeNano() + int64(d) if t < 0 { + // N.B. runtimeNano() and d are always positive, so addition + // (including overflow) will never result in t == 0. t = 1<<63 - 1 // math.MaxInt64 } return t diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go index ba0016bf49..084ac33f51 100644 --- a/src/time/sleep_test.go +++ b/src/time/sleep_test.go @@ -434,17 +434,29 @@ func TestReset(t *testing.T) { t.Error(err) } -// Test that sleeping for an interval so large it overflows does not -// result in a short sleep duration. +// Test that sleeping (via Sleep or Timer) for an interval so large it +// overflows does not result in a short sleep duration. Nor does it interfere +// with execution of other timers. If it does, timers in this or subsequent +// tests may not fire. func TestOverflowSleep(t *testing.T) { const big = Duration(int64(1<<63 - 1)) + + go func() { + Sleep(big) + // On failure, this may return after the test has completed, so + // we need to panic instead. + panic("big sleep returned") + }() + select { case <-After(big): t.Fatalf("big timeout fired") case <-After(25 * Millisecond): // OK } + const neg = Duration(-1 << 63) + Sleep(neg) // Returns immediately. select { case <-After(neg): // OK @@ -473,13 +485,10 @@ func TestIssue5745(t *testing.T) { t.Error("Should be unreachable.") } -func TestOverflowRuntimeTimer(t *testing.T) { - if testing.Short() { - t.Skip("skipping in short mode, see issue 6874") - } +func TestOverflowPeriodRuntimeTimer(t *testing.T) { // This may hang forever if timers are broken. See comment near // the end of CheckRuntimeTimerOverflow in internal_test.go. - CheckRuntimeTimerOverflow() + CheckRuntimeTimerPeriodOverflow() } func checkZeroPanicString(t *testing.T) { From 37a32a1833a6e55baaa8d971406094148e42f7d1 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Thu, 3 Dec 2020 13:32:11 -0500 Subject: [PATCH 121/212] cmd/compile: make sure address of offset(SP) is rematerializeable An address of offset(SP) may point to the callee args area, and may be used to move things into/out of the args/results. If an address like that is spilled and picked up by the GC, it may hold an arg/result live in the callee, which may not actually be live (e.g. a result not initialized at function entry). Make sure they are rematerializeable, so they are always short-lived and never picked up by the GC. This CL changes 386, PPC64, and Wasm. On AMD64 we already have the rule (line 2159). On other architectures, we already have similar rules like (OffPtr [off] ptr:(SP)) => (MOVDaddr [int32(off)] ptr) to avoid this problem. (Probably me in the past had run into this...) Fixes #42944. Change-Id: Id2ec73ac08f8df1829a9a7ceb8f749d67fe86d1e Reviewed-on: https://go-review.googlesource.com/c/go/+/275174 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/gen/386.rules | 1 + src/cmd/compile/internal/ssa/gen/PPC64.rules | 1 + src/cmd/compile/internal/ssa/gen/Wasm.rules | 1 + src/cmd/compile/internal/ssa/rewrite386.go | 13 +++++++++++ src/cmd/compile/internal/ssa/rewritePPC64.go | 14 ++++++++++++ src/cmd/compile/internal/ssa/rewriteWasm.go | 14 ++++++++++++ src/cmd/compile/internal/wasm/ssa.go | 6 +++++ test/fixedbugs/issue42944.go | 24 ++++++++++++++++++++ 8 files changed, 74 insertions(+) create mode 100644 test/fixedbugs/issue42944.go diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules index 537705c681..fbc12fd672 100644 --- a/src/cmd/compile/internal/ssa/gen/386.rules +++ b/src/cmd/compile/internal/ssa/gen/386.rules @@ -531,6 +531,7 @@ // fold ADDL into LEAL (ADDLconst [c] (LEAL [d] {s} x)) && is32Bit(int64(c)+int64(d)) => (LEAL [c+d] {s} x) (LEAL [c] {s} (ADDLconst [d] x)) && is32Bit(int64(c)+int64(d)) => (LEAL [c+d] {s} x) +(ADDLconst [c] x:(SP)) => (LEAL [c] x) // so it is rematerializeable (LEAL [c] {s} (ADDL x y)) && x.Op != OpSB && y.Op != OpSB => (LEAL1 [c] {s} x y) (ADDL x (LEAL [c] {s} y)) && x.Op != OpSB && y.Op != OpSB => (LEAL1 [c] {s} x y) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index 31b186d167..c064046172 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -845,6 +845,7 @@ (SUB x (MOVDconst [c])) && is32Bit(-c) => (ADDconst [-c] x) (ADDconst [c] (MOVDaddr [d] {sym} x)) && is32Bit(c+int64(d)) => (MOVDaddr [int32(c+int64(d))] {sym} x) +(ADDconst [c] x:(SP)) && is32Bit(c) => (MOVDaddr [int32(c)] x) // so it is rematerializeable (MULL(W|D) x (MOVDconst [c])) && is16Bit(c) => (MULL(W|D)const [int32(c)] x) diff --git a/src/cmd/compile/internal/ssa/gen/Wasm.rules b/src/cmd/compile/internal/ssa/gen/Wasm.rules index ea12c5d617..fc45cd3ed5 100644 --- a/src/cmd/compile/internal/ssa/gen/Wasm.rules +++ b/src/cmd/compile/internal/ssa/gen/Wasm.rules @@ -399,6 +399,7 @@ // folding offset into address (I64AddConst [off] (LoweredAddr {sym} [off2] base)) && isU32Bit(off+int64(off2)) => (LoweredAddr {sym} [int32(off)+off2] base) +(I64AddConst [off] x:(SP)) && isU32Bit(off) => (LoweredAddr [int32(off)] x) // so it is rematerializeable // transforming readonly globals into constants (I64Load [off] (LoweredAddr {sym} [off2] (SB)) _) && symIsRO(sym) && isU32Bit(off+int64(off2)) => (I64Const [int64(read64(sym, off+int64(off2), config.ctxt.Arch.ByteOrder))]) diff --git a/src/cmd/compile/internal/ssa/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go index eca4817b9b..2acdccd568 100644 --- a/src/cmd/compile/internal/ssa/rewrite386.go +++ b/src/cmd/compile/internal/ssa/rewrite386.go @@ -1027,6 +1027,19 @@ func rewriteValue386_Op386ADDLconst(v *Value) bool { v.AddArg(x) return true } + // match: (ADDLconst [c] x:(SP)) + // result: (LEAL [c] x) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if x.Op != OpSP { + break + } + v.reset(Op386LEAL) + v.AuxInt = int32ToAuxInt(c) + v.AddArg(x) + return true + } // match: (ADDLconst [c] (LEAL1 [d] {s} x y)) // cond: is32Bit(int64(c)+int64(d)) // result: (LEAL1 [c+d] {s} x y) diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 7d4cf73fd8..455f9b1388 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -4195,6 +4195,20 @@ func rewriteValuePPC64_OpPPC64ADDconst(v *Value) bool { v.AddArg(x) return true } + // match: (ADDconst [c] x:(SP)) + // cond: is32Bit(c) + // result: (MOVDaddr [int32(c)] x) + for { + c := auxIntToInt64(v.AuxInt) + x := v_0 + if x.Op != OpSP || !(is32Bit(c)) { + break + } + v.reset(OpPPC64MOVDaddr) + v.AuxInt = int32ToAuxInt(int32(c)) + v.AddArg(x) + return true + } // match: (ADDconst [c] (SUBFCconst [d] x)) // cond: is32Bit(c+d) // result: (SUBFCconst [c+d] x) diff --git a/src/cmd/compile/internal/ssa/rewriteWasm.go b/src/cmd/compile/internal/ssa/rewriteWasm.go index 52b6f6bfc7..c8ecefc736 100644 --- a/src/cmd/compile/internal/ssa/rewriteWasm.go +++ b/src/cmd/compile/internal/ssa/rewriteWasm.go @@ -3693,6 +3693,20 @@ func rewriteValueWasm_OpWasmI64AddConst(v *Value) bool { v.AddArg(base) return true } + // match: (I64AddConst [off] x:(SP)) + // cond: isU32Bit(off) + // result: (LoweredAddr [int32(off)] x) + for { + off := auxIntToInt64(v.AuxInt) + x := v_0 + if x.Op != OpSP || !(isU32Bit(off)) { + break + } + v.reset(OpWasmLoweredAddr) + v.AuxInt = int32ToAuxInt(int32(off)) + v.AddArg(x) + return true + } return false } func rewriteValueWasm_OpWasmI64And(v *Value) bool { diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go index a36fbca4e0..9c9f6edc5f 100644 --- a/src/cmd/compile/internal/wasm/ssa.go +++ b/src/cmd/compile/internal/wasm/ssa.go @@ -230,6 +230,12 @@ func ssaGenValueOnStack(s *gc.SSAGenState, v *ssa.Value, extend bool) { } case ssa.OpWasmLoweredAddr: + if v.Aux == nil { // address of off(SP), no symbol + getValue64(s, v.Args[0]) + i64Const(s, v.AuxInt) + s.Prog(wasm.AI64Add) + break + } p := s.Prog(wasm.AGet) p.From.Type = obj.TYPE_ADDR switch v.Aux.(type) { diff --git a/test/fixedbugs/issue42944.go b/test/fixedbugs/issue42944.go new file mode 100644 index 0000000000..bb947bc609 --- /dev/null +++ b/test/fixedbugs/issue42944.go @@ -0,0 +1,24 @@ +// errorcheck -0 -live + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Issue 42944: address of callee args area should only be short-lived +// and never across a call. + +package p + +type T [10]int // trigger DUFFCOPY when passing by value, so it uses the address + +func F() { + var x T + var i int + for { + x = G(i) // no autotmp live at this and next calls + H(i, x) + } +} + +func G(int) T +func H(int, T) From 2c2980aa0cde1a44789103981774e34a4c8a0f2d Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 30 Oct 2020 00:04:00 +0100 Subject: [PATCH 122/212] doc/go1.16: pre-announce GODEBUG=x509ignoreCN=0 removal in Go 1.17 For #40700 Updates #24151 Change-Id: Id63dcaad238f7534bfce8902b8cb3efd8db5942d Reviewed-on: https://go-review.googlesource.com/c/go/+/266539 Trust: Filippo Valsorda Trust: Katie Hockman Reviewed-by: Katie Hockman --- doc/go1.16.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/go1.16.html b/doc/go1.16.html index 462f86fe09..e644ad0575 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -501,6 +501,13 @@ Do not send CLs removing the interior tags from such phrases.

crypto/x509
+

+ The GODEBUG=x509ignoreCN=0 flag will be removed in Go 1.17. + It enables the legacy behavior of treating the CommonName + field on X.509 certificates as a host name when no Subject Alternative + Names are present. +

+

ParseCertificate and CreateCertificate both From 84cb51d7d7a936d56d6287ca075dd578097499a9 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 3 Dec 2020 11:56:29 -0800 Subject: [PATCH 123/212] [dev.regabi] cmd/compile: eliminate more SetOrig This CL consolidates and cleans up fmt.go's logic for skipping past Nodes introduced during typechecking. This allows eliminating SetOrig on ConvExpr and Name. Also changes ConstExpr.SetOrig to a panic for good measure. The only remaining SetOrig uses now are for rewriting multi-value "f(g())" calls and "return g()" statements, and type-checking composite literals. It should be possible to eliminate both of those as well. Passes buildall w/ toolstash -cmp. Change-Id: I478aea1a17dfb7a784293b930bf9081637eb2d7a Reviewed-on: https://go-review.googlesource.com/c/go/+/275179 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/subr.go | 1 - src/cmd/compile/internal/ir/expr.go | 4 +-- src/cmd/compile/internal/ir/fmt.go | 47 +++++++++++++++-------------- src/cmd/compile/internal/ir/name.go | 2 -- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 970f78b355..65eb61e680 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -523,7 +523,6 @@ func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node { r.SetType(t) r.SetTypecheck(1) r.SetImplicit(true) - r.(ir.OrigNode).SetOrig(ir.Orig(n)) return r } diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 18d85a01df..49543f4286 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -321,7 +321,7 @@ func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ConstExpr) rawCopy() Node { c := *n; return &c } func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() } func (n *ConstExpr) Orig() Node { return n.orig } -func (n *ConstExpr) SetOrig(orig Node) { n.orig = orig } +func (n *ConstExpr) SetOrig(orig Node) { panic(n.no("SetOrig")) } func (n *ConstExpr) Val() constant.Value { return n.val } // A ConvExpr is a conversion Type(X). @@ -344,8 +344,6 @@ func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr { func (n *ConvExpr) String() string { return fmt.Sprint(n) } func (n *ConvExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ConvExpr) rawCopy() Node { c := *n; return &c } -func (n *ConvExpr) Orig() Node { return n.orig } -func (n *ConvExpr) SetOrig(x Node) { n.orig = x } func (n *ConvExpr) Left() Node { return n.X } func (n *ConvExpr) SetLeft(x Node) { n.X = x } diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 45a66a2290..bc5536241e 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1071,6 +1071,7 @@ var OpPrec = []int{ OCALL: 8, OCAP: 8, OCLOSE: 8, + OCOMPLIT: 8, OCONVIFACE: 8, OCONVNOP: 8, OCONV: 8, @@ -1179,13 +1180,28 @@ var OpPrec = []int{ } func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { - for n != nil && n.Implicit() && (n.Op() == ODEREF || n.Op() == OADDR) { - n = n.Left() - } + for { + if n == nil { + fmt.Fprint(s, "") + return + } - if n == nil { - fmt.Fprint(s, "") - return + // We always want the original, if any. + if o := Orig(n); o != n { + n = o + continue + } + + // Skip implicit operations introduced during typechecking. + switch n.Op() { + case OADDR, ODEREF, OCONV, OCONVNOP, OCONVIFACE: + if n.Implicit() { + n = n.Left() + continue + } + } + + break } nprec := OpPrec[n.Op()] @@ -1206,15 +1222,9 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { fmt.Fprint(s, "nil") case OLITERAL: // this is a bit of a mess - if mode == FErr { - if orig := Orig(n); orig != nil && orig != n { - exprFmt(orig, s, prec, mode) - return - } - if n.Sym() != nil { - fmt.Fprint(s, smodeString(n.Sym(), mode)) - return - } + if mode == FErr && n.Sym() != nil { + fmt.Fprint(s, smodeString(n.Sym(), mode)) + return } needUnparen := false @@ -1558,13 +1568,6 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { func nodeFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { t := n.Type() - - // We almost always want the original. - // TODO(gri) Why the special case for OLITERAL? - if n.Op() != OLITERAL && Orig(n) != nil { - n = Orig(n) - } - if flag&FmtLong != 0 && t != nil { if t.Kind() == types.TNIL { fmt.Fprint(s, "nil") diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index aeeb63d2d6..67d4d2b391 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -155,8 +155,6 @@ func (n *Name) rawCopy() Node { c := *n; return &c } func (n *Name) Name() *Name { return n } func (n *Name) Sym() *types.Sym { return n.sym } func (n *Name) SetSym(x *types.Sym) { n.sym = x } -func (n *Name) Orig() Node { return n.orig } -func (n *Name) SetOrig(x Node) { n.orig = x } func (n *Name) SubOp() Op { return n.subOp } func (n *Name) SetSubOp(x Op) { n.subOp = x } func (n *Name) Class() Class { return n.class } From cc386bd05ad8076f1d7e5a4d9a13c1276fd26ac6 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 4 Dec 2020 01:09:13 +0100 Subject: [PATCH 124/212] doc/go1.16: fix broken tag For #40700 Change-Id: I0083db494284d6142e1b8b981fca4ac30af2012a Reviewed-on: https://go-review.googlesource.com/c/go/+/275312 Reviewed-by: Ian Lance Taylor Trust: Filippo Valsorda --- doc/go1.16.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index e644ad0575..eaa8e46572 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -287,7 +287,7 @@ Do not send CLs removing the interior tags from such phrases.

- Setting the GODEBUG environment variable + Setting the GODEBUG environment variable to inittrace=1 now causes the runtime to emit a single line to standard error for each package init, summarizing its execution time and memory allocation. This trace can From b67b7ddabcc8e1a4b5819f03d47777bf5ddedbcc Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Tue, 1 Dec 2020 14:12:22 +0100 Subject: [PATCH 125/212] doc/go1.16: add reflect changes to release notes For #40700 Fixes #42911 Change-Id: I1bd729f72ae3a29d190ffc34a40c3d0b59ebbbb4 Reviewed-on: https://go-review.googlesource.com/c/go/+/274474 Trust: Alberto Donizetti Reviewed-by: Dmitri Shuralyov --- doc/go1.16.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index eaa8e46572..1c22c21758 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -783,8 +783,10 @@ Do not send CLs removing the interior tags from such phrases.

reflect
-

- TODO: https://golang.org/cl/248341: support multiple keys in struct tags +

+ StructTag now allows multiple space-separated keys + in key:value pairs, as in `json xml:"field1"` + (equivalent to `json:"field1" xml:"field1"`).

From 37588ffcb221c12c12882b591a16243ae2799fd1 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 2 Dec 2020 15:09:12 -0500 Subject: [PATCH 126/212] cmd/go, embed: exclude .* and _* from embedded directory trees Discussion on #42328 led to a decision to exclude files matching .* and _* from embedded directory results when embedding an entire directory tree. This CL implements that new behavior. Fixes #42328. Change-Id: I6188994e96348b3449c7d9d3d0d181cfbf2d4db1 Reviewed-on: https://go-review.googlesource.com/c/go/+/275092 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/go/internal/load/pkg.go | 17 +++++++++++---- src/embed/embed.go | 5 ++++- src/embed/internal/embedtest/embed_test.go | 21 +++++++++++++++++++ .../embedtest/testdata/.hidden/.more/tip.txt | 1 + .../embedtest/testdata/.hidden/_more/tip.txt | 1 + .../embedtest/testdata/.hidden/fortune.txt | 2 ++ .../embedtest/testdata/.hidden/more/tip.txt | 1 + .../embedtest/testdata/_hidden/fortune.txt | 2 ++ 8 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 src/embed/internal/embedtest/testdata/.hidden/.more/tip.txt create mode 100644 src/embed/internal/embedtest/testdata/.hidden/_more/tip.txt create mode 100644 src/embed/internal/embedtest/testdata/.hidden/fortune.txt create mode 100644 src/embed/internal/embedtest/testdata/.hidden/more/tip.txt create mode 100644 src/embed/internal/embedtest/testdata/_hidden/fortune.txt diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 30ca33b663..cbc683da2b 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -1998,6 +1998,16 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri return err } rel := filepath.ToSlash(path[len(p.Dir)+1:]) + name := info.Name() + if path != file && (isBadEmbedName(name) || name[0] == '.' || name[0] == '_') { + // Ignore bad names, assuming they won't go into modules. + // Also avoid hidden files that user may not know about. + // See golang.org/issue/42328. + if info.IsDir() { + return fs.SkipDir + } + return nil + } if info.IsDir() { if _, err := fsys.Stat(filepath.Join(path, "go.mod")); err == nil { return filepath.SkipDir @@ -2007,10 +2017,6 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri if !info.Mode().IsRegular() { return nil } - if isBadEmbedName(info.Name()) { - // Ignore bad names, assuming they won't go into modules. - return nil - } count++ if have[rel] != pid { have[rel] = pid @@ -2050,6 +2056,9 @@ func validEmbedPattern(pattern string) bool { // as existing for embedding. func isBadEmbedName(name string) bool { switch name { + // Empty string should be impossible but make it bad. + case "": + return true // Version control directories won't be present in module. case ".bzr", ".hg", ".git", ".svn": return true diff --git a/src/embed/embed.go b/src/embed/embed.go index b22975cc3a..29e0adf1a6 100644 --- a/src/embed/embed.go +++ b/src/embed/embed.go @@ -59,12 +59,15 @@ // as Go double-quoted or back-quoted string literals. // // If a pattern names a directory, all files in the subtree rooted at that directory are -// embedded (recursively), so the variable in the above example is equivalent to: +// embedded (recursively), except that files with names beginning with ‘.’ or ‘_’ +// are excluded. So the variable in the above example is almost equivalent to: // // // content is our static web server content. // //go:embed image template html/index.html // var content embed.FS // +// The difference is that ‘image/*’ embeds ‘image/.tempfile’ while ‘image’ does not. +// // The //go:embed directive can be used with both exported and unexported variables, // depending on whether the package wants to make the data available to other packages. // Similarly, it can be used with both global and function-local variables, diff --git a/src/embed/internal/embedtest/embed_test.go b/src/embed/internal/embedtest/embed_test.go index c82ca9fed2..b1707a4c04 100644 --- a/src/embed/internal/embedtest/embed_test.go +++ b/src/embed/internal/embedtest/embed_test.go @@ -101,3 +101,24 @@ func TestDir(t *testing.T) { testDir(t, all, "testdata/i/j", "k/") testDir(t, all, "testdata/i/j/k", "k8s.txt") } + +func TestHidden(t *testing.T) { + //go:embed testdata + var dir embed.FS + + //go:embed testdata/* + var star embed.FS + + t.Logf("//go:embed testdata") + + testDir(t, dir, "testdata", + "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt") + + t.Logf("//go:embed testdata/*") + + testDir(t, star, "testdata", + ".hidden/", "_hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt") + + testDir(t, star, "testdata/.hidden", + "fortune.txt", "more/") // but not .more or _more +} diff --git a/src/embed/internal/embedtest/testdata/.hidden/.more/tip.txt b/src/embed/internal/embedtest/testdata/.hidden/.more/tip.txt new file mode 100644 index 0000000000..71b9c6955d --- /dev/null +++ b/src/embed/internal/embedtest/testdata/.hidden/.more/tip.txt @@ -0,0 +1 @@ +#define struct union /* Great space saver */ diff --git a/src/embed/internal/embedtest/testdata/.hidden/_more/tip.txt b/src/embed/internal/embedtest/testdata/.hidden/_more/tip.txt new file mode 100644 index 0000000000..71b9c6955d --- /dev/null +++ b/src/embed/internal/embedtest/testdata/.hidden/_more/tip.txt @@ -0,0 +1 @@ +#define struct union /* Great space saver */ diff --git a/src/embed/internal/embedtest/testdata/.hidden/fortune.txt b/src/embed/internal/embedtest/testdata/.hidden/fortune.txt new file mode 100644 index 0000000000..31f2013f94 --- /dev/null +++ b/src/embed/internal/embedtest/testdata/.hidden/fortune.txt @@ -0,0 +1,2 @@ +WARNING: terminal is not fully functional + - (press RETURN) diff --git a/src/embed/internal/embedtest/testdata/.hidden/more/tip.txt b/src/embed/internal/embedtest/testdata/.hidden/more/tip.txt new file mode 100644 index 0000000000..71b9c6955d --- /dev/null +++ b/src/embed/internal/embedtest/testdata/.hidden/more/tip.txt @@ -0,0 +1 @@ +#define struct union /* Great space saver */ diff --git a/src/embed/internal/embedtest/testdata/_hidden/fortune.txt b/src/embed/internal/embedtest/testdata/_hidden/fortune.txt new file mode 100644 index 0000000000..31f2013f94 --- /dev/null +++ b/src/embed/internal/embedtest/testdata/_hidden/fortune.txt @@ -0,0 +1,2 @@ +WARNING: terminal is not fully functional + - (press RETURN) From 73580645087b84c3470943155e5e94eacf83bb86 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 3 Dec 2020 17:29:39 -0500 Subject: [PATCH 127/212] doc/go1.16: preannounce dropping macOS 10.12 support Go 1.16 will be the last to support macOS 10.12 Sierra. Go 1.17 will require macOS 10.13 High Sierra. For #23011. Change-Id: I80052bdde4d9f1c5d71b67b85f65fb0b40856750 Reviewed-on: https://go-review.googlesource.com/c/go/+/275299 Trust: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor --- doc/go1.16.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/go1.16.html b/doc/go1.16.html index 1c22c21758..4d4b459009 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -58,6 +58,11 @@ Do not send CLs removing the interior tags from such phrases. the ios build tag set.

+

+ Go 1.16 is the last release that will run on macOS 10.12 Sierra. + Go 1.17 will require macOS 10.13 High Sierra or later. +

+

NetBSD

From 21cfadf0dc1e93c339e319c502f14ee42973c44d Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Thu, 3 Dec 2020 16:53:30 -0500 Subject: [PATCH 128/212] runtime: avoid receiving preemotion signal while exec'ing The iOS kernel has the same problem as the macOS kernel. Extend the workaround of #41702 (CL 262438 and CL 262817) to iOS. Updates #35851. Change-Id: I7ccec00dc96643c08c5be8b385394856d0fa0f64 Reviewed-on: https://go-review.googlesource.com/c/go/+/275293 Trust: Cherry Zhang Reviewed-by: Ian Lance Taylor --- src/runtime/proc.go | 4 ++-- src/runtime/signal_unix.go | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 0319de5fde..64e102fb0a 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -1363,7 +1363,7 @@ found: checkdead() unlock(&sched.lock) - if GOOS == "darwin" { + if GOOS == "darwin" || GOOS == "ios" { // Make sure pendingPreemptSignals is correct when an M exits. // For #41702. if atomic.Load(&m.signalPending) != 0 { @@ -3852,7 +3852,7 @@ func syscall_runtime_BeforeExec() { // On Darwin, wait for all pending preemption signals to // be received. See issue #41702. - if GOOS == "darwin" { + if GOOS == "darwin" || GOOS == "ios" { for int32(atomic.Load(&pendingPreemptSignals)) > 0 { osyield() } diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 6aad079f03..e8f39c3321 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -336,7 +336,7 @@ func doSigPreempt(gp *g, ctxt *sigctxt) { atomic.Xadd(&gp.m.preemptGen, 1) atomic.Store(&gp.m.signalPending, 0) - if GOOS == "darwin" { + if GOOS == "darwin" || GOOS == "ios" { atomic.Xadd(&pendingPreemptSignals, -1) } } @@ -352,12 +352,12 @@ const preemptMSupported = true func preemptM(mp *m) { // On Darwin, don't try to preempt threads during exec. // Issue #41702. - if GOOS == "darwin" { + if GOOS == "darwin" || GOOS == "ios" { execLock.rlock() } if atomic.Cas(&mp.signalPending, 0, 1) { - if GOOS == "darwin" { + if GOOS == "darwin" || GOOS == "ios" { atomic.Xadd(&pendingPreemptSignals, 1) } @@ -369,7 +369,7 @@ func preemptM(mp *m) { signalM(mp, sigPreempt) } - if GOOS == "darwin" { + if GOOS == "darwin" || GOOS == "ios" { execLock.runlock() } } @@ -432,7 +432,7 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { // no non-Go signal handler for sigPreempt. // The default behavior for sigPreempt is to ignore // the signal, so badsignal will be a no-op anyway. - if GOOS == "darwin" { + if GOOS == "darwin" || GOOS == "ios" { atomic.Xadd(&pendingPreemptSignals, -1) } return From 5d4569197eeef42862b8ea87a7e8ccda1cd061a0 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 3 Dec 2020 16:14:07 -0500 Subject: [PATCH 129/212] cmd/go/internal/modload: fix minor errors in comments Change-Id: I38848e7bcd5dfa9f7feb415e1c54921768bf1ab8 Reviewed-on: https://go-review.googlesource.com/c/go/+/275295 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/load.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 732c4af92b..a0f93d028a 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -61,8 +61,8 @@ package modload // Similarly, if the LoadTests flag is set but the "all" pattern does not close // over test dependencies, then when we load the test of a package that is in // "all" but outside the main module, the dependencies of that test will not -// necessarily themselves be in "all". That configuration does not arise in Go -// 1.11–1.15, but it will be possible with lazy loading in Go 1.16+. +// necessarily themselves be in "all". (That configuration does not arise in Go +// 1.11–1.15, but it will be possible in Go 1.16+.) // // Loading proceeds from the roots, using a parallel work-queue with a limit on // the amount of active work (to avoid saturating disks, CPU cores, and/or @@ -158,8 +158,8 @@ type PackageOpts struct { // UseVendorAll causes the "all" package pattern to be interpreted as if // running "go mod vendor" (or building with "-mod=vendor"). // - // Once lazy loading is implemented, this will be a no-op for modules that - // declare 'go 1.16' or higher. + // This is a no-op for modules that declare 'go 1.16' or higher, for which this + // is the default (and only) interpretation of the "all" pattern in module mode. UseVendorAll bool // AllowErrors indicates that LoadPackages should not terminate the process if From 478bde3a4388997924a02ee9296864866d8ba3ba Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 2 Dec 2020 12:49:20 -0500 Subject: [PATCH 130/212] io/fs: add Sub Sub provides a convenient way to refer to a subdirectory automatically in future operations, like Unix's chdir(2). The CL also includes updates to fstest to check Sub implementations. As part of updating fstest, I changed the meaning of TestFS's expected list to introduce a special case: if you list no expected files, that means the FS must be empty. In general it's OK not to list all the expected files, but if you list none, that's almost certainly a mistake - if your FS were broken and empty, you wouldn't find out. Making no expected files mean "must be empty" makes the mistake less likely - if your file system ever worked, then your test will keep it working. That change found a testing bug: embedtest was making exactly that mistake. Fixes #42322. Change-Id: I63fd4aa866b30061a0e51ca9a1927e576d6ec41e Reviewed-on: https://go-review.googlesource.com/c/go/+/274856 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- doc/go1.16.html | 2 +- src/embed/internal/embedtest/embed_test.go | 2 +- src/io/fs/readdir_test.go | 12 +- src/io/fs/readfile_test.go | 16 +++ src/io/fs/sub.go | 127 +++++++++++++++++++++ src/io/fs/sub_test.go | 57 +++++++++ src/os/file.go | 7 ++ src/testing/fstest/mapfs.go | 10 ++ src/testing/fstest/testfs.go | 42 +++++++ 9 files changed, 271 insertions(+), 4 deletions(-) create mode 100644 src/io/fs/sub.go create mode 100644 src/io/fs/sub_test.go diff --git a/doc/go1.16.html b/doc/go1.16.html index 4d4b459009..62d9b97db8 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -384,7 +384,7 @@ Do not send CLs removing the interior tags from such phrases. the new embed.FS type implements fs.FS, as does zip.Reader. - The new os.Dir function + The new os.DirFS function provides an implementation of fs.FS backed by a tree of operating system files.

diff --git a/src/embed/internal/embedtest/embed_test.go b/src/embed/internal/embedtest/embed_test.go index b1707a4c04..c6a7bea7a3 100644 --- a/src/embed/internal/embedtest/embed_test.go +++ b/src/embed/internal/embedtest/embed_test.go @@ -65,7 +65,7 @@ func TestGlobal(t *testing.T) { testFiles(t, global, "testdata/hello.txt", "hello, world\n") testFiles(t, global, "testdata/glass.txt", "I can eat glass and it doesn't hurt me.\n") - if err := fstest.TestFS(global); err != nil { + if err := fstest.TestFS(global, "concurrency.txt", "testdata/hello.txt"); err != nil { t.Fatal(err) } diff --git a/src/io/fs/readdir_test.go b/src/io/fs/readdir_test.go index 46a4bc2788..405bfa67ca 100644 --- a/src/io/fs/readdir_test.go +++ b/src/io/fs/readdir_test.go @@ -16,12 +16,12 @@ func (readDirOnly) Open(name string) (File, error) { return nil, ErrNotExist } func TestReadDir(t *testing.T) { check := func(desc string, dirs []DirEntry, err error) { t.Helper() - if err != nil || len(dirs) != 1 || dirs[0].Name() != "hello.txt" { + if err != nil || len(dirs) != 2 || dirs[0].Name() != "hello.txt" || dirs[1].Name() != "sub" { var names []string for _, d := range dirs { names = append(names, d.Name()) } - t.Errorf("ReadDir(%s) = %v, %v, want %v, nil", desc, names, err, []string{"hello.txt"}) + t.Errorf("ReadDir(%s) = %v, %v, want %v, nil", desc, names, err, []string{"hello.txt", "sub"}) } } @@ -32,4 +32,12 @@ func TestReadDir(t *testing.T) { // Test that ReadDir uses Open when the method is not present. dirs, err = ReadDir(openOnly{testFsys}, ".") check("openOnly", dirs, err) + + // Test that ReadDir on Sub of . works (sub_test checks non-trivial subs). + sub, err := Sub(testFsys, ".") + if err != nil { + t.Fatal(err) + } + dirs, err = ReadDir(sub, ".") + check("sub(.)", dirs, err) } diff --git a/src/io/fs/readfile_test.go b/src/io/fs/readfile_test.go index 0afa334ace..07219c1445 100644 --- a/src/io/fs/readfile_test.go +++ b/src/io/fs/readfile_test.go @@ -18,6 +18,12 @@ var testFsys = fstest.MapFS{ ModTime: time.Now(), Sys: &sysValue, }, + "sub/goodbye.txt": { + Data: []byte("goodbye, world"), + Mode: 0456, + ModTime: time.Now(), + Sys: &sysValue, + }, } var sysValue int @@ -40,4 +46,14 @@ func TestReadFile(t *testing.T) { if string(data) != "hello, world" || err != nil { t.Fatalf(`ReadFile(openOnly, "hello.txt") = %q, %v, want %q, nil`, data, err, "hello, world") } + + // Test that ReadFile on Sub of . works (sub_test checks non-trivial subs). + sub, err := Sub(testFsys, ".") + if err != nil { + t.Fatal(err) + } + data, err = ReadFile(sub, "hello.txt") + if string(data) != "hello, world" || err != nil { + t.Fatalf(`ReadFile(sub(.), "hello.txt") = %q, %v, want %q, nil`, data, err, "hello, world") + } } diff --git a/src/io/fs/sub.go b/src/io/fs/sub.go new file mode 100644 index 0000000000..381f409504 --- /dev/null +++ b/src/io/fs/sub.go @@ -0,0 +1,127 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fs + +import ( + "errors" + "path" +) + +// A SubFS is a file system with a Sub method. +type SubFS interface { + FS + + // Sub returns an FS corresponding to the subtree rooted at dir. + Sub(dir string) (FS, error) +} + +// Sub returns an FS corresponding to the subtree rooted at fsys's dir. +// +// If fs implements SubFS, Sub calls returns fsys.Sub(dir). +// Otherwise, if dir is ".", Sub returns fsys unchanged. +// Otherwise, Sub returns a new FS implementation sub that, +// in effect, implements sub.Open(dir) as fsys.Open(path.Join(dir, name)). +// The implementation also translates calls to ReadDir, ReadFile, and Glob appropriately. +// +// Note that Sub(os.DirFS("/"), "prefix") is equivalent to os.DirFS("/prefix") +// and that neither of them guarantees to avoid operating system +// accesses outside "/prefix", because the implementation of os.DirFS +// does not check for symbolic links inside "/prefix" that point to +// other directories. That is, os.DirFS is not a general substitute for a +// chroot-style security mechanism, and Sub does not change that fact. +func Sub(fsys FS, dir string) (FS, error) { + if !ValidPath(dir) { + return nil, &PathError{Op: "sub", Path: dir, Err: errors.New("invalid name")} + } + if dir == "." { + return fsys, nil + } + if fsys, ok := fsys.(SubFS); ok { + return fsys.Sub(dir) + } + return &subFS{fsys, dir}, nil +} + +type subFS struct { + fsys FS + dir string +} + +// fullName maps name to the fully-qualified name dir/name. +func (f *subFS) fullName(op string, name string) (string, error) { + if !ValidPath(name) { + return "", &PathError{Op: op, Path: name, Err: errors.New("invalid name")} + } + return path.Join(f.dir, name), nil +} + +// shorten maps name, which should start with f.dir, back to the suffix after f.dir. +func (f *subFS) shorten(name string) (rel string, ok bool) { + if name == f.dir { + return ".", true + } + if len(name) >= len(f.dir)+2 && name[len(f.dir)] == '/' && name[:len(f.dir)] == f.dir { + return name[len(f.dir)+1:], true + } + return "", false +} + +// fixErr shortens any reported names in PathErrors by stripping dir. +func (f *subFS) fixErr(err error) error { + if e, ok := err.(*PathError); ok { + if short, ok := f.shorten(e.Path); ok { + e.Path = short + } + } + return err +} + +func (f *subFS) Open(name string) (File, error) { + full, err := f.fullName("open", name) + if err != nil { + return nil, err + } + file, err := f.fsys.Open(full) + return file, f.fixErr(err) +} + +func (f *subFS) ReadDir(name string) ([]DirEntry, error) { + full, err := f.fullName("open", name) + if err != nil { + return nil, err + } + dir, err := ReadDir(f.fsys, full) + return dir, f.fixErr(err) +} + +func (f *subFS) ReadFile(name string) ([]byte, error) { + full, err := f.fullName("open", name) + if err != nil { + return nil, err + } + data, err := ReadFile(f.fsys, full) + return data, f.fixErr(err) +} + +func (f *subFS) Glob(pattern string) ([]string, error) { + // Check pattern is well-formed. + if _, err := path.Match(pattern, ""); err != nil { + return nil, err + } + if pattern == "." { + return []string{"."}, nil + } + + full := f.dir + "/" + pattern + list, err := Glob(f.fsys, full) + for i, name := range list { + name, ok := f.shorten(name) + if !ok { + return nil, errors.New("invalid result from inner fsys Glob: " + name + " not in " + f.dir) // can't use fmt in this package + } + list[i] = name + } + return list, f.fixErr(err) +} diff --git a/src/io/fs/sub_test.go b/src/io/fs/sub_test.go new file mode 100644 index 0000000000..451b0efb02 --- /dev/null +++ b/src/io/fs/sub_test.go @@ -0,0 +1,57 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fs_test + +import ( + . "io/fs" + "testing" +) + +type subOnly struct{ SubFS } + +func (subOnly) Open(name string) (File, error) { return nil, ErrNotExist } + +func TestSub(t *testing.T) { + check := func(desc string, sub FS, err error) { + t.Helper() + if err != nil { + t.Errorf("Sub(sub): %v", err) + return + } + data, err := ReadFile(sub, "goodbye.txt") + if string(data) != "goodbye, world" || err != nil { + t.Errorf(`ReadFile(%s, "goodbye.txt" = %q, %v, want %q, nil`, desc, string(data), err, "goodbye, world") + } + + dirs, err := ReadDir(sub, ".") + if err != nil || len(dirs) != 1 || dirs[0].Name() != "goodbye.txt" { + var names []string + for _, d := range dirs { + names = append(names, d.Name()) + } + t.Errorf(`ReadDir(%s, ".") = %v, %v, want %v, nil`, desc, names, err, []string{"goodbye.txt"}) + } + } + + // Test that Sub uses the method when present. + sub, err := Sub(subOnly{testFsys}, "sub") + check("subOnly", sub, err) + + // Test that Sub uses Open when the method is not present. + sub, err = Sub(openOnly{testFsys}, "sub") + check("openOnly", sub, err) + + _, err = sub.Open("nonexist") + if err == nil { + t.Fatal("Open(nonexist): succeeded") + } + pe, ok := err.(*PathError) + if !ok { + t.Fatalf("Open(nonexist): error is %T, want *PathError", err) + } + if pe.Path != "nonexist" { + t.Fatalf("Open(nonexist): err.Path = %q, want %q", pe.Path, "nonexist") + } +} diff --git a/src/os/file.go b/src/os/file.go index 304b055dbe..416bc0efa6 100644 --- a/src/os/file.go +++ b/src/os/file.go @@ -609,6 +609,13 @@ func isWindowsNulName(name string) bool { } // DirFS returns a file system (an fs.FS) for the tree of files rooted at the directory dir. +// +// Note that DirFS("/prefix") only guarantees that the Open calls it makes to the +// operating system will begin with "/prefix": DirFS("/prefix").Open("file") is the +// same as os.Open("/prefix/file"). So if /prefix/file is a symbolic link pointing outside +// the /prefix tree, then using DirFS does not stop the access any more than using +// os.Open does. DirFS is therefore not a general substitute for a chroot-style security +// mechanism when the directory tree contains arbitrary content. func DirFS(dir string) fs.FS { return dirFS(dir) } diff --git a/src/testing/fstest/mapfs.go b/src/testing/fstest/mapfs.go index 10e56f5b3c..a5d4a23fac 100644 --- a/src/testing/fstest/mapfs.go +++ b/src/testing/fstest/mapfs.go @@ -132,6 +132,16 @@ func (fsys MapFS) Glob(pattern string) ([]string, error) { return fs.Glob(fsOnly{fsys}, pattern) } +type noSub struct { + MapFS +} + +func (noSub) Sub() {} // not the fs.SubFS signature + +func (fsys MapFS) Sub(dir string) (fs.FS, error) { + return fs.Sub(noSub{fsys}, dir) +} + // A mapFileInfo implements fs.FileInfo and fs.DirEntry for a given map file. type mapFileInfo struct { name string diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go index 4912a271b2..2602bdf0cc 100644 --- a/src/testing/fstest/testfs.go +++ b/src/testing/fstest/testfs.go @@ -22,6 +22,8 @@ import ( // It walks the entire tree of files in fsys, // opening and checking that each file behaves correctly. // It also checks that the file system contains at least the expected files. +// As a special case, if no expected files are listed, fsys must be empty. +// Otherwise, fsys must only contain at least the listed files: it can also contain others. // // If TestFS finds any misbehaviors, it returns an error reporting all of them. // The error text spans multiple lines, one per detected misbehavior. @@ -33,6 +35,32 @@ import ( // } // func TestFS(fsys fs.FS, expected ...string) error { + if err := testFS(fsys, expected...); err != nil { + return err + } + for _, name := range expected { + if i := strings.Index(name, "/"); i >= 0 { + dir, dirSlash := name[:i], name[:i+1] + var subExpected []string + for _, name := range expected { + if strings.HasPrefix(name, dirSlash) { + subExpected = append(subExpected, name[len(dirSlash):]) + } + } + sub, err := fs.Sub(fsys, dir) + if err != nil { + return err + } + if err := testFS(sub, subExpected...); err != nil { + return fmt.Errorf("testing fs.Sub(fsys, %s): %v", dir, err) + } + break // one sub-test is enough + } + } + return nil +} + +func testFS(fsys fs.FS, expected ...string) error { t := fsTester{fsys: fsys} t.checkDir(".") t.checkOpen(".") @@ -43,6 +71,20 @@ func TestFS(fsys fs.FS, expected ...string) error { for _, file := range t.files { found[file] = true } + delete(found, ".") + if len(expected) == 0 && len(found) > 0 { + var list []string + for k := range found { + if k != "." { + list = append(list, k) + } + } + sort.Strings(list) + if len(list) > 15 { + list = append(list[:10], "...") + } + t.errorf("expected empty file system but found files:\n%s", strings.Join(list, "\n")) + } for _, name := range expected { if !found[name] { t.errorf("expected but not found: %s", name) From 99ecfcae31e52a297195b2c1d1d9326e16d6c775 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 15:40:46 -0500 Subject: [PATCH 131/212] [dev.regabi] cmd/compile: swap inlining order of if then vs else blocks The upcoming general iterators will process nodes in source code order, meaning that the "then" block comes before the "else" block. But for an if node, "then" is Body while "else" is Rlist, and the inliner processes Rlist first. The order of processing changes the order of inlining decisions, which can affect which functions are inlined, but in general won't affect much. (It's not like we know that we should prefer to inline functions in else bodies over then bodies.) Swapping these is not safe for toolstash -cmp. Doing it in a separate CL lets the upcoming CLs all be toolstash-safe. Change-Id: Id16172849239b0564930d2bbff1260ad6d03d5ab Reviewed-on: https://go-review.googlesource.com/c/go/+/275308 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/inl.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 64f1b062be..980ba7429a 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -638,6 +638,14 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { } } + inlnodelist(n.Body(), maxCost, inlMap) + s = n.Body().Slice() + for i, n1 := range s { + if n1.Op() == ir.OINLCALL { + s[i] = inlconv2stmt(n1) + } + } + inlnodelist(n.Rlist(), maxCost, inlMap) if n.Op() == ir.OAS2FUNC && n.Rlist().First().Op() == ir.OINLCALL { @@ -658,14 +666,6 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { } } - inlnodelist(n.Body(), maxCost, inlMap) - s = n.Body().Slice() - for i, n1 := range s { - if n1.Op() == ir.OINLCALL { - s[i] = inlconv2stmt(n1) - } - } - // with all the branches out of the way, it is now time to // transmogrify this node itself unless inhibited by the // switch at the top of this function. From 989a3f5041d2055e165e363d3fb2d27e75e2fa38 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 2 Dec 2020 22:42:24 -0500 Subject: [PATCH 132/212] [dev.regabi] cmd/compile: adjustments to Copy and DeepCopy DeepCopy is not called DeepSepCopy, so it should use Copy, not SepCopy. Also, the old gc.treecopy, which became ir.DeepCopy, only copied the Left, Right, and List fields - not Init, Rlist, Body - and I didn't notice when I moved it over. A general utility function should of course copy the whole node, so do that. Finally, the semantics of Copy should not depend on whether a particular child node is held directly in a field or in a slice, so make Copy duplicate the slice backing arrays as well. (Logically, those backing arrays are part of the node storage.) Passes buildall w/ toolstash -cmp. Change-Id: I18fbe3f2b40078f566ed6370684d5585052b36a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/275309 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/copy.go | 43 +++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/ir/copy.go b/src/cmd/compile/internal/ir/copy.go index a356074bb8..705de0195b 100644 --- a/src/cmd/compile/internal/ir/copy.go +++ b/src/cmd/compile/internal/ir/copy.go @@ -61,9 +61,33 @@ func Copy(n Node) Node { if n, ok := n.(OrigNode); ok && n.Orig() == n { copy.(OrigNode).SetOrig(copy) } + + // Copy lists so that updates to n.List[0] + // don't affect copy.List[0] and vice versa, + // same as updates to Left and Right. + // TODO(rsc): Eventually the Node implementations will need to do this. + if l := copy.List(); l.Len() > 0 { + copy.SetList(copyList(l)) + } + if l := copy.Rlist(); l.Len() > 0 { + copy.SetRlist(copyList(l)) + } + if l := copy.Init(); l.Len() > 0 { + copy.SetInit(copyList(l)) + } + if l := copy.Body(); l.Len() > 0 { + copy.SetBody(copyList(l)) + } + return copy } +func copyList(x Nodes) Nodes { + out := make([]Node, x.Len()) + copy(out, x.Slice()) + return AsNodes(out) +} + // A Node can implement DeepCopyNode to provide a custom implementation // of DeepCopy. If the compiler only needs access to a Node's structure during // DeepCopy, then a Node can implement DeepCopyNode instead of providing @@ -94,10 +118,15 @@ func DeepCopy(pos src.XPos, n Node) Node { switch n.Op() { default: - m := SepCopy(n) + m := Copy(n) m.SetLeft(DeepCopy(pos, n.Left())) m.SetRight(DeepCopy(pos, n.Right())) - m.PtrList().Set(deepCopyList(pos, n.List().Slice())) + // deepCopyList instead of DeepCopyList + // because Copy already copied all these slices. + deepCopyList(pos, m.PtrList().Slice()) + deepCopyList(pos, m.PtrRlist().Slice()) + deepCopyList(pos, m.PtrInit().Slice()) + deepCopyList(pos, m.PtrBody().Slice()) if pos.IsKnown() { m.SetPos(pos) } @@ -118,10 +147,18 @@ func DeepCopy(pos src.XPos, n Node) Node { } } -func deepCopyList(pos src.XPos, list []Node) []Node { +// DeepCopyList returns a list of deep copies (using DeepCopy) of the nodes in list. +func DeepCopyList(pos src.XPos, list []Node) []Node { var out []Node for _, n := range list { out = append(out, DeepCopy(pos, n)) } return out } + +// deepCopyList edits list to point to deep copies of its elements. +func deepCopyList(pos src.XPos, list []Node) { + for i, n := range list { + list[i] = DeepCopy(pos, n) + } +} From 7fcf5b994cf24dc7eda4d65d448e25489dd357f6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 2 Dec 2020 22:54:33 -0500 Subject: [PATCH 133/212] [dev.regabi] cmd/compile: replace inlcopy with ir.DeepCopy Now inlcopy and ir.DeepCopy are semantically the same, so drop the inlcopy implementation. Passes buildall w/ toolstash -cmp. Change-Id: Id2abb39a412a8e57167a29be5ecf76e990dc9d3d Reviewed-on: https://go-review.googlesource.com/c/go/+/275310 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/inl.go | 37 +----------------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 980ba7429a..efd6fea844 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -218,7 +218,7 @@ func caninl(fn *ir.Func) { n.Func().Inl = &ir.Inline{ Cost: inlineMaxBudget - visitor.budget, Dcl: pruneUnusedAutos(n.Defn.Func().Dcl, &visitor), - Body: inlcopylist(fn.Body().Slice()), + Body: ir.DeepCopyList(src.NoXPos, fn.Body().Slice()), } if base.Flag.LowerM > 1 { @@ -447,41 +447,6 @@ func (v *hairyVisitor) visit(n ir.Node) bool { v.visitList(n.Init()) || v.visitList(n.Body()) } -// inlcopylist (together with inlcopy) recursively copies a list of nodes, except -// that it keeps the same ONAME, OTYPE, and OLITERAL nodes. It is used for copying -// the body and dcls of an inlineable function. -func inlcopylist(ll []ir.Node) []ir.Node { - s := make([]ir.Node, 0, len(ll)) - for _, n := range ll { - s = append(s, inlcopy(n)) - } - return s -} - -func inlcopy(n ir.Node) ir.Node { - if n == nil { - return nil - } - - switch n.Op() { - case ir.ONAME, ir.OTYPE, ir.OLITERAL, ir.ONIL: - return n - } - - m := ir.Copy(n) - if n.Op() != ir.OCALLPART && m.Func() != nil { - base.Fatalf("unexpected Func: %v", m) - } - m.SetLeft(inlcopy(n.Left())) - m.SetRight(inlcopy(n.Right())) - m.PtrList().Set(inlcopylist(n.List().Slice())) - m.PtrRlist().Set(inlcopylist(n.Rlist().Slice())) - m.PtrInit().Set(inlcopylist(n.Init().Slice())) - m.PtrBody().Set(inlcopylist(n.Body().Slice())) - - return m -} - func countNodes(n ir.Node) int { if n == nil { return 0 From 0d1b44c6457bcfad611252175934e82f73440475 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 12:57:38 -0500 Subject: [PATCH 134/212] [dev.regabi] cmd/compile: introduce IR visitors This CL introduces the general visitor functionality that will replace the Left, SetLeft, Right, SetRight, etc methods in the Node interface. For now, the CL defines the functionality in terms of those methods, but eventually the Nodes themselves will implement DoChildren and EditChildren and be relieved of implementing Left, SetLeft, and so on. The CL also updates Inspect (which moved to visit.go) and DeepCopy to use the new functionality. The Find helper is not used in this CL but will be used in a future one. Passes buildall w/ toolstash -cmp. Change-Id: Id0eea654a884ab3ea25f48bd8bdd71712b5dcb44 Reviewed-on: https://go-review.googlesource.com/c/go/+/275311 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/copy.go | 57 ++---- src/cmd/compile/internal/ir/node.go | 20 -- src/cmd/compile/internal/ir/visit.go | 273 +++++++++++++++++++++++++++ 3 files changed, 289 insertions(+), 61 deletions(-) create mode 100644 src/cmd/compile/internal/ir/visit.go diff --git a/src/cmd/compile/internal/ir/copy.go b/src/cmd/compile/internal/ir/copy.go index 705de0195b..2f340df1ab 100644 --- a/src/cmd/compile/internal/ir/copy.go +++ b/src/cmd/compile/internal/ir/copy.go @@ -107,44 +107,26 @@ type DeepCopyNode interface { // // If a Node wishes to provide an alternate implementation, it can // implement a DeepCopy method: see the DeepCopyNode interface. +// +// TODO(rsc): Once Nodes implement EditChildren, remove the DeepCopyNode interface. func DeepCopy(pos src.XPos, n Node) Node { - if n == nil { - return nil - } - - if n, ok := n.(DeepCopyNode); ok { - return n.DeepCopy(pos) - } - - switch n.Op() { - default: - m := Copy(n) - m.SetLeft(DeepCopy(pos, n.Left())) - m.SetRight(DeepCopy(pos, n.Right())) - // deepCopyList instead of DeepCopyList - // because Copy already copied all these slices. - deepCopyList(pos, m.PtrList().Slice()) - deepCopyList(pos, m.PtrRlist().Slice()) - deepCopyList(pos, m.PtrInit().Slice()) - deepCopyList(pos, m.PtrBody().Slice()) + var edit func(Node) Node + edit = func(x Node) Node { + if x, ok := x.(DeepCopyNode); ok { + return x.DeepCopy(pos) + } + switch x.Op() { + case OPACK, ONAME, ONONAME, OLITERAL, ONIL, OTYPE: + return x + } + x = Copy(x) if pos.IsKnown() { - m.SetPos(pos) + x.SetPos(pos) } - if m.Name() != nil { - Dump("DeepCopy", n) - base.Fatalf("DeepCopy Name") - } - return m - - case OPACK: - // OPACK nodes are never valid in const value declarations, - // but allow them like any other declared symbol to avoid - // crashing (golang.org/issue/11361). - fallthrough - - case ONAME, ONONAME, OLITERAL, ONIL, OTYPE: - return n + EditChildren(x, edit) + return x } + return edit(n) } // DeepCopyList returns a list of deep copies (using DeepCopy) of the nodes in list. @@ -155,10 +137,3 @@ func DeepCopyList(pos src.XPos, list []Node) []Node { } return out } - -// deepCopyList edits list to point to deep copies of its elements. -func deepCopyList(pos src.XPos, list []Node) { - for i, n := range list { - list[i] = DeepCopy(pos, n) - } -} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 42ba4cb0e9..c3184a3a0b 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -521,26 +521,6 @@ func (n *Nodes) AppendNodes(n2 *Nodes) { n2.slice = nil } -// inspect invokes f on each node in an AST in depth-first order. -// If f(n) returns false, inspect skips visiting n's children. -func Inspect(n Node, f func(Node) bool) { - if n == nil || !f(n) { - return - } - InspectList(n.Init(), f) - Inspect(n.Left(), f) - Inspect(n.Right(), f) - InspectList(n.List(), f) - InspectList(n.Body(), f) - InspectList(n.Rlist(), f) -} - -func InspectList(l Nodes, f func(Node) bool) { - for _, n := range l.Slice() { - Inspect(n, f) - } -} - // nodeQueue is a FIFO queue of *Node. The zero value of nodeQueue is // a ready-to-use empty queue. type NodeQueue struct { diff --git a/src/cmd/compile/internal/ir/visit.go b/src/cmd/compile/internal/ir/visit.go new file mode 100644 index 0000000000..a239fd1532 --- /dev/null +++ b/src/cmd/compile/internal/ir/visit.go @@ -0,0 +1,273 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// IR visitors for walking the IR tree. +// +// The lowest level helpers are DoChildren and EditChildren, +// which nodes help implement (TODO(rsc): eventually) and +// provide control over whether and when recursion happens +// during the walk of the IR. +// +// Although these are both useful directly, two simpler patterns +// are fairly common and also provided: Inspect and Scan. + +package ir + +import "errors" + +// DoChildren calls do(x) on each of n's non-nil child nodes x. +// If any call returns a non-nil error, DoChildren stops and returns that error. +// Otherwise, DoChildren returns nil. +// +// Note that DoChildren(n, do) only calls do(x) for n's immediate children. +// If x's children should be processed, then do(x) must call DoChildren(x, do). +// +// DoChildren allows constructing general traversals of the IR graph +// that can stop early if needed. The most general usage is: +// +// var do func(ir.Node) error +// do = func(x ir.Node) error { +// ... processing BEFORE visting children ... +// if ... should visit children ... { +// ir.DoChildren(x, do) +// ... processing AFTER visting children ... +// } +// if ... should stop parent DoChildren call from visiting siblings ... { +// return non-nil error +// } +// return nil +// } +// do(root) +// +// Since DoChildren does not generate any errors itself, if the do function +// never wants to stop the traversal, it can assume that DoChildren itself +// will always return nil, simplifying to: +// +// var do func(ir.Node) error +// do = func(x ir.Node) error { +// ... processing BEFORE visting children ... +// if ... should visit children ... { +// ir.DoChildren(x, do) +// } +// ... processing AFTER visting children ... +// return nil +// } +// do(root) +// +// The Inspect function illustrates a further simplification of the pattern, +// only considering processing before visiting children, and letting +// that processing decide whether children are visited at all: +// +// func Inspect(n ir.Node, inspect func(ir.Node) bool) { +// var do func(ir.Node) error +// do = func(x ir.Node) error { +// if inspect(x) { +// ir.DoChildren(x, do) +// } +// return nil +// } +// if n != nil { +// do(n) +// } +// } +// +// The Find function illustrates a different simplification of the pattern, +// visiting each node and then its children, recursively, until finding +// a node x such that find(x) returns a non-nil result, +// at which point the entire traversal stops: +// +// func Find(n ir.Node, find func(ir.Node) interface{}) interface{} { +// stop := errors.New("stop") +// var found interface{} +// var do func(ir.Node) error +// do = func(x ir.Node) error { +// if v := find(x); v != nil { +// found = v +// return stop +// } +// return DoChildren(x, do) +// } +// do(n) +// return found +// } +// +// Inspect and Find are presented above as examples of how to use +// DoChildren effectively, but of course, usage that fits within the +// simplifications captured by Inspect or Find will be best served +// by directly calling the ones provided by this package. +func DoChildren(n Node, do func(Node) error) error { + if n == nil { + return nil + } + if err := DoList(n.Init(), do); err != nil { + return err + } + if l := n.Left(); l != nil { + if err := do(l); err != nil { + return err + } + } + if r := n.Right(); r != nil { + if err := do(r); err != nil { + return err + } + } + if err := DoList(n.List(), do); err != nil { + return err + } + if err := DoList(n.Body(), do); err != nil { + return err + } + if err := DoList(n.Rlist(), do); err != nil { + return err + } + return nil +} + +// DoList calls f on each non-nil node x in the list, in list order. +// If any call returns a non-nil error, DoList stops and returns that error. +// Otherwise DoList returns nil. +// +// Note that DoList only calls do on the nodes in the list, not their children. +// If x's children should be processed, do(x) must call DoChildren(x, do) itself. +func DoList(list Nodes, do func(Node) error) error { + for _, x := range list.Slice() { + if x != nil { + if err := do(x); err != nil { + return err + } + } + } + return nil +} + +// Inspect visits each node x in the IR tree rooted at n +// in a depth-first preorder traversal, calling inspect on each node visited. +// If inspect(x) returns false, then Inspect skips over x's children. +// +// Note that the meaning of the boolean result in the callback function +// passed to Inspect differs from that of Scan. +// During Scan, if scan(x) returns false, then Scan stops the scan. +// During Inspect, if inspect(x) returns false, then Inspect skips x's children +// but continues with the remainder of the tree (x's siblings and so on). +func Inspect(n Node, inspect func(Node) bool) { + var do func(Node) error + do = func(x Node) error { + if inspect(x) { + DoChildren(x, do) + } + return nil + } + if n != nil { + do(n) + } +} + +// InspectList calls Inspect(x, inspect) for each node x in the list. +func InspectList(list Nodes, inspect func(Node) bool) { + for _, x := range list.Slice() { + Inspect(x, inspect) + } +} + +var stop = errors.New("stop") + +// Find looks for a non-nil node x in the IR tree rooted at n +// for which find(x) returns a non-nil value. +// Find considers nodes in a depth-first, preorder traversal. +// When Find finds a node x such that find(x) != nil, +// Find ends the traversal and returns the value of find(x) immediately. +// Otherwise Find returns nil. +func Find(n Node, find func(Node) interface{}) interface{} { + if n == nil { + return nil + } + var found interface{} + var do func(Node) error + do = func(x Node) error { + if v := find(x); v != nil { + found = v + return stop + } + return DoChildren(x, do) + } + do(n) + return found +} + +// FindList calls Find(x, ok) for each node x in the list, in order. +// If any call find(x) returns a non-nil result, FindList stops and +// returns that result, skipping the remainder of the list. +// Otherwise FindList returns nil. +func FindList(list Nodes, find func(Node) interface{}) interface{} { + for _, x := range list.Slice() { + if v := Find(x, find); v != nil { + return v + } + } + return nil +} + +// EditChildren edits the child nodes of n, replacing each child x with edit(x). +// +// Note that EditChildren(n, edit) only calls edit(x) for n's immediate children. +// If x's children should be processed, then edit(x) must call EditChildren(x, edit). +// +// EditChildren allows constructing general editing passes of the IR graph. +// The most general usage is: +// +// var edit func(ir.Node) ir.Node +// edit = func(x ir.Node) ir.Node { +// ... processing BEFORE editing children ... +// if ... should edit children ... { +// EditChildren(x, edit) +// ... processing AFTER editing children ... +// } +// ... return x ... +// } +// n = edit(n) +// +// EditChildren edits the node in place. To edit a copy, call Copy first. +// As an example, a simple deep copy implementation would be: +// +// func deepCopy(n ir.Node) ir.Node { +// var edit func(ir.Node) ir.Node +// edit = func(x ir.Node) ir.Node { +// x = ir.Copy(x) +// ir.EditChildren(x, edit) +// return x +// } +// return edit(n) +// } +// +// Of course, in this case it is better to call ir.DeepCopy than to build one anew. +func EditChildren(n Node, edit func(Node) Node) { + if n == nil { + return + } + editList(n.Init(), edit) + if l := n.Left(); l != nil { + n.SetLeft(edit(l)) + } + if r := n.Right(); r != nil { + n.SetRight(edit(r)) + } + editList(n.List(), edit) + editList(n.Body(), edit) + editList(n.Rlist(), edit) +} + +// editList calls edit on each non-nil node x in the list, +// saving the result of edit back into the list. +// +// Note that editList only calls edit on the nodes in the list, not their children. +// If x's children should be processed, edit(x) must call EditChildren(x, edit) itself. +func editList(list Nodes, edit func(Node) Node) { + s := list.Slice() + for i, x := range list.Slice() { + if x != nil { + s[i] = edit(x) + } + } +} From b9df26d7a86e0b402f4ae5fd0cb44bab46b6331e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 2 Dec 2020 20:18:47 -0500 Subject: [PATCH 135/212] [dev.regabi] cmd/compile: use ir.Find for "search" traversals This CL converts all the generic searching traversal to use ir.Find instead of relying on direct access to Left, Right, and so on. Passes buildall w/ toolstash -cmp. Change-Id: I4d951aef630c00bf333f24be79565cc564694d04 Reviewed-on: https://go-review.googlesource.com/c/go/+/275372 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/alg.go | 37 +---- src/cmd/compile/internal/gc/const.go | 72 ++++----- src/cmd/compile/internal/gc/inl.go | 192 +++++++++-------------- src/cmd/compile/internal/gc/order.go | 9 +- src/cmd/compile/internal/gc/sinit.go | 6 +- src/cmd/compile/internal/gc/typecheck.go | 88 +++++------ src/cmd/compile/internal/gc/walk.go | 184 ++++++++++------------ 7 files changed, 247 insertions(+), 341 deletions(-) diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go index b2716399a5..c786a27415 100644 --- a/src/cmd/compile/internal/gc/alg.go +++ b/src/cmd/compile/internal/gc/alg.go @@ -782,37 +782,14 @@ func geneq(t *types.Type) *obj.LSym { return closure } -func hasCall(n ir.Node) bool { - if n.Op() == ir.OCALL || n.Op() == ir.OCALLFUNC { - return true - } - if n.Left() != nil && hasCall(n.Left()) { - return true - } - if n.Right() != nil && hasCall(n.Right()) { - return true - } - for _, x := range n.Init().Slice() { - if hasCall(x) { - return true +func hasCall(fn *ir.Func) bool { + found := ir.Find(fn, func(n ir.Node) interface{} { + if op := n.Op(); op == ir.OCALL || op == ir.OCALLFUNC { + return n } - } - for _, x := range n.Body().Slice() { - if hasCall(x) { - return true - } - } - for _, x := range n.List().Slice() { - if hasCall(x) { - return true - } - } - for _, x := range n.Rlist().Slice() { - if hasCall(x) { - return true - } - } - return false + return nil + }) + return found != nil } // eqfield returns the node diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 9aa65f97b6..6cd414a419 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -553,7 +553,7 @@ func evalConst(n ir.Node) ir.Node { return origIntConst(n, int64(len(ir.StringVal(nl)))) } case types.TARRAY: - if !hascallchan(nl) { + if !hasCallOrChan(nl) { return origIntConst(n, nl.Type().NumElem()) } } @@ -779,49 +779,35 @@ func isGoConst(n ir.Node) bool { return n.Op() == ir.OLITERAL } -func hascallchan(n ir.Node) bool { - if n == nil { - return false - } - switch n.Op() { - case ir.OAPPEND, - ir.OCALL, - ir.OCALLFUNC, - ir.OCALLINTER, - ir.OCALLMETH, - ir.OCAP, - ir.OCLOSE, - ir.OCOMPLEX, - ir.OCOPY, - ir.ODELETE, - ir.OIMAG, - ir.OLEN, - ir.OMAKE, - ir.ONEW, - ir.OPANIC, - ir.OPRINT, - ir.OPRINTN, - ir.OREAL, - ir.ORECOVER, - ir.ORECV: - return true - } - - if hascallchan(n.Left()) || hascallchan(n.Right()) { - return true - } - for _, n1 := range n.List().Slice() { - if hascallchan(n1) { - return true +// hasCallOrChan reports whether n contains any calls or channel operations. +func hasCallOrChan(n ir.Node) bool { + found := ir.Find(n, func(n ir.Node) interface{} { + switch n.Op() { + case ir.OAPPEND, + ir.OCALL, + ir.OCALLFUNC, + ir.OCALLINTER, + ir.OCALLMETH, + ir.OCAP, + ir.OCLOSE, + ir.OCOMPLEX, + ir.OCOPY, + ir.ODELETE, + ir.OIMAG, + ir.OLEN, + ir.OMAKE, + ir.ONEW, + ir.OPANIC, + ir.OPRINT, + ir.OPRINTN, + ir.OREAL, + ir.ORECOVER, + ir.ORECV: + return n } - } - for _, n2 := range n.Rlist().Slice() { - if hascallchan(n2) { - return true - } - } - - return false + return nil + }) + return found != nil } // A constSet represents a set of Go constant expressions. diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index efd6fea844..09ec0b6f99 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -33,6 +33,7 @@ import ( "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/src" + "errors" "fmt" "go/constant" "strings" @@ -206,14 +207,10 @@ func caninl(fn *ir.Func) { extraCallCost: cc, usedLocals: make(map[ir.Node]bool), } - if visitor.visitList(fn.Body()) { + if visitor.tooHairy(fn) { reason = visitor.reason return } - if visitor.budget < 0 { - reason = fmt.Sprintf("function too complex: cost %d exceeds budget %d", inlineMaxBudget-visitor.budget, inlineMaxBudget) - return - } n.Func().Inl = &ir.Inline{ Cost: inlineMaxBudget - visitor.budget, @@ -296,21 +293,29 @@ type hairyVisitor struct { reason string extraCallCost int32 usedLocals map[ir.Node]bool + do func(ir.Node) error } -// Look for anything we want to punt on. -func (v *hairyVisitor) visitList(ll ir.Nodes) bool { - for _, n := range ll.Slice() { - if v.visit(n) { - return true - } +var errBudget = errors.New("too expensive") + +func (v *hairyVisitor) tooHairy(fn *ir.Func) bool { + v.do = v.doNode // cache closure + + err := ir.DoChildren(fn, v.do) + if err != nil { + v.reason = err.Error() + return true + } + if v.budget < 0 { + v.reason = fmt.Sprintf("function too complex: cost %d exceeds budget %d", inlineMaxBudget-v.budget, inlineMaxBudget) + return true } return false } -func (v *hairyVisitor) visit(n ir.Node) bool { +func (v *hairyVisitor) doNode(n ir.Node) error { if n == nil { - return false + return nil } switch n.Op() { @@ -323,8 +328,7 @@ func (v *hairyVisitor) visit(n ir.Node) bool { if n.Left().Op() == ir.ONAME && n.Left().Class() == ir.PFUNC && isRuntimePkg(n.Left().Sym().Pkg) { fn := n.Left().Sym().Name if fn == "getcallerpc" || fn == "getcallersp" { - v.reason = "call to " + fn - return true + return errors.New("call to " + fn) } if fn == "throw" { v.budget -= inlineExtraThrowCost @@ -380,8 +384,7 @@ func (v *hairyVisitor) visit(n ir.Node) bool { case ir.ORECOVER: // recover matches the argument frame pointer to find // the right panic value, so it needs an argument frame. - v.reason = "call to recover" - return true + return errors.New("call to recover") case ir.OCLOSURE, ir.ORANGE, @@ -390,21 +393,19 @@ func (v *hairyVisitor) visit(n ir.Node) bool { ir.ODEFER, ir.ODCLTYPE, // can't print yet ir.ORETJMP: - v.reason = "unhandled op " + n.Op().String() - return true + return errors.New("unhandled op " + n.Op().String()) case ir.OAPPEND: v.budget -= inlineExtraAppendCost case ir.ODCLCONST, ir.OFALL: // These nodes don't produce code; omit from inlining budget. - return false + return nil case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH: // ORANGE, OSELECT in "unhandled" above if n.Sym() != nil { - v.reason = "labeled control" - return true + return errors.New("labeled control") } case ir.OBREAK, ir.OCONTINUE: @@ -416,8 +417,17 @@ func (v *hairyVisitor) visit(n ir.Node) bool { case ir.OIF: if ir.IsConst(n.Left(), constant.Bool) { // This if and the condition cost nothing. - return v.visitList(n.Init()) || v.visitList(n.Body()) || - v.visitList(n.Rlist()) + // TODO(rsc): It seems strange that we visit the dead branch. + if err := ir.DoList(n.Init(), v.do); err != nil { + return err + } + if err := ir.DoList(n.Body(), v.do); err != nil { + return err + } + if err := ir.DoList(n.Rlist(), v.do); err != nil { + return err + } + return nil } case ir.ONAME: @@ -439,34 +449,22 @@ func (v *hairyVisitor) visit(n ir.Node) bool { // When debugging, don't stop early, to get full cost of inlining this function if v.budget < 0 && base.Flag.LowerM < 2 && !logopt.Enabled() { - return true + return errBudget } - return v.visit(n.Left()) || v.visit(n.Right()) || - v.visitList(n.List()) || v.visitList(n.Rlist()) || - v.visitList(n.Init()) || v.visitList(n.Body()) + return ir.DoChildren(n, v.do) } -func countNodes(n ir.Node) int { - if n == nil { - return 0 - } - cnt := 1 - cnt += countNodes(n.Left()) - cnt += countNodes(n.Right()) - for _, n1 := range n.Init().Slice() { - cnt += countNodes(n1) - } - for _, n1 := range n.Body().Slice() { - cnt += countNodes(n1) - } - for _, n1 := range n.List().Slice() { - cnt += countNodes(n1) - } - for _, n1 := range n.Rlist().Slice() { - cnt += countNodes(n1) - } - return cnt +func isBigFunc(fn *ir.Func) bool { + budget := inlineBigFunctionNodes + over := ir.Find(fn, func(n ir.Node) interface{} { + budget-- + if budget <= 0 { + return n + } + return nil + }) + return over != nil } // Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any @@ -475,7 +473,7 @@ func inlcalls(fn *ir.Func) { savefn := Curfn Curfn = fn maxCost := int32(inlineMaxBudget) - if countNodes(fn) >= inlineBigFunctionNodes { + if isBigFunc(fn) { maxCost = inlineBigFunctionMaxCost } // Map to keep track of functions that have been inlined at a particular @@ -742,82 +740,45 @@ FindRHS: base.Fatalf("RHS is nil: %v", defn) } - unsafe, _ := reassigned(n.(*ir.Name)) - if unsafe { + if reassigned(n.(*ir.Name)) { return nil } return rhs } +var errFound = errors.New("found") + // reassigned takes an ONAME node, walks the function in which it is defined, and returns a boolean // indicating whether the name has any assignments other than its declaration. // The second return value is the first such assignment encountered in the walk, if any. It is mostly // useful for -m output documenting the reason for inhibited optimizations. // NB: global variables are always considered to be re-assigned. // TODO: handle initial declaration not including an assignment and followed by a single assignment? -func reassigned(n *ir.Name) (bool, ir.Node) { - if n.Op() != ir.ONAME { - base.Fatalf("reassigned %v", n) +func reassigned(name *ir.Name) bool { + if name.Op() != ir.ONAME { + base.Fatalf("reassigned %v", name) } // no way to reliably check for no-reassignment of globals, assume it can be - if n.Curfn == nil { - return true, nil + if name.Curfn == nil { + return true } - f := n.Curfn - v := reassignVisitor{name: n} - a := v.visitList(f.Body()) - return a != nil, a -} - -type reassignVisitor struct { - name ir.Node -} - -func (v *reassignVisitor) visit(n ir.Node) ir.Node { - if n == nil { - return nil - } - switch n.Op() { - case ir.OAS: - if n.Left() == v.name && n != v.name.Name().Defn { - return n - } - case ir.OAS2, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2DOTTYPE: - for _, p := range n.List().Slice() { - if p == v.name && n != v.name.Name().Defn { + a := ir.Find(name.Curfn, func(n ir.Node) interface{} { + switch n.Op() { + case ir.OAS: + if n.Left() == name && n != name.Defn { return n } + case ir.OAS2, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2DOTTYPE: + for _, p := range n.List().Slice() { + if p == name && n != name.Defn { + return n + } + } } - } - if a := v.visit(n.Left()); a != nil { - return a - } - if a := v.visit(n.Right()); a != nil { - return a - } - if a := v.visitList(n.List()); a != nil { - return a - } - if a := v.visitList(n.Rlist()); a != nil { - return a - } - if a := v.visitList(n.Init()); a != nil { - return a - } - if a := v.visitList(n.Body()); a != nil { - return a - } - return nil -} - -func (v *reassignVisitor) visitList(l ir.Nodes) ir.Node { - for _, n := range l.Slice() { - if a := v.visit(n); a != nil { - return a - } - } - return nil + return nil + }) + return a != nil } func inlParam(t *types.Field, as ir.Node, inlvars map[*ir.Name]ir.Node) ir.Node { @@ -1140,6 +1101,7 @@ func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool) bases: make(map[*src.PosBase]*src.PosBase), newInlIndex: newIndex, } + subst.edit = subst.node body := subst.list(ir.AsNodes(fn.Inl.Body)) @@ -1248,6 +1210,8 @@ type inlsubst struct { // newInlIndex is the index of the inlined call frame to // insert for inlined nodes. newInlIndex int + + edit func(ir.Node) ir.Node // cached copy of subst.node method value closure } // list inlines a list of nodes. @@ -1334,21 +1298,13 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { return m } - m := ir.Copy(n) - m.SetPos(subst.updatedPos(m.Pos())) - m.PtrInit().Set(nil) - if n.Op() == ir.OCLOSURE { base.Fatalf("cannot inline function containing closure: %+v", n) } - m.SetLeft(subst.node(n.Left())) - m.SetRight(subst.node(n.Right())) - m.PtrList().Set(subst.list(n.List())) - m.PtrRlist().Set(subst.list(n.Rlist())) - m.PtrInit().Set(append(m.Init().Slice(), subst.list(n.Init())...)) - m.PtrBody().Set(subst.list(n.Body())) - + m := ir.Copy(n) + m.SetPos(subst.updatedPos(m.Pos())) + ir.EditChildren(m, subst.edit) return m } diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 5440806e8e..1680d9d920 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -1062,6 +1062,10 @@ func (o *Order) exprListInPlace(l ir.Nodes) { // prealloc[x] records the allocation to use for x. var prealloc = map[ir.Node]ir.Node{} +func (o *Order) exprNoLHS(n ir.Node) ir.Node { + return o.expr(n, nil) +} + // expr orders a single expression, appending side // effects to o.out as needed. // If this is part of an assignment lhs = *np, lhs is given. @@ -1079,10 +1083,7 @@ func (o *Order) expr(n, lhs ir.Node) ir.Node { switch n.Op() { default: - n.SetLeft(o.expr(n.Left(), nil)) - n.SetRight(o.expr(n.Right(), nil)) - o.exprList(n.List()) - o.exprList(n.Rlist()) + ir.EditChildren(n, o.exprNoLHS) // Addition of strings turns into a function call. // Allocate a temporary to hold the strings. diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index 3ef976d8aa..20abbfef8c 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -60,7 +60,8 @@ func (s *InitSchedule) tryStaticInit(n ir.Node) bool { if n.Op() != ir.OAS { return false } - if ir.IsBlank(n.Left()) && candiscard(n.Right()) { + if ir.IsBlank(n.Left()) && !hasSideEffects(n.Right()) { + // Discard. return true } lno := setlineno(n) @@ -548,7 +549,8 @@ func fixedlit(ctxt initContext, kind initKind, n ir.Node, var_ ir.Node, init *ir for _, r := range n.List().Slice() { a, value := splitnode(r) - if a == ir.BlankNode && candiscard(value) { + if a == ir.BlankNode && !hasSideEffects(value) { + // Discard. continue } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index e2100481aa..a8acd468c9 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3669,51 +3669,52 @@ func checkmake(t *types.Type, arg string, np *ir.Node) bool { return true } -func markbreak(labels *map[*types.Sym]ir.Node, n ir.Node, implicit ir.Node) { - if n == nil { - return +// markBreak marks control statements containing break statements with SetHasBreak(true). +func markBreak(fn *ir.Func) { + var labels map[*types.Sym]ir.Node + var implicit ir.Node + + var mark func(ir.Node) error + mark = func(n ir.Node) error { + switch n.Op() { + default: + ir.DoChildren(n, mark) + + case ir.OBREAK: + if n.Sym() == nil { + if implicit != nil { + implicit.SetHasBreak(true) + } + } else { + if lab := labels[n.Sym()]; lab != nil { + lab.SetHasBreak(true) + } + } + + case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OTYPESW, ir.OSELECT, ir.ORANGE: + old := implicit + implicit = n + sym := n.Sym() + if sym != nil { + if labels == nil { + // Map creation delayed until we need it - most functions don't. + labels = make(map[*types.Sym]ir.Node) + } + labels[sym] = n + } + ir.DoChildren(n, mark) + if sym != nil { + delete(labels, sym) + } + implicit = old + } + return nil } - switch n.Op() { - case ir.OBREAK: - if n.Sym() == nil { - if implicit != nil { - implicit.SetHasBreak(true) - } - } else { - if lab := (*labels)[n.Sym()]; lab != nil { - lab.SetHasBreak(true) - } - } - case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OTYPESW, ir.OSELECT, ir.ORANGE: - implicit = n - if sym := n.Sym(); sym != nil { - if *labels == nil { - // Map creation delayed until we need it - most functions don't. - *labels = make(map[*types.Sym]ir.Node) - } - (*labels)[sym] = n - defer delete(*labels, sym) - } - fallthrough - default: - markbreak(labels, n.Left(), implicit) - markbreak(labels, n.Right(), implicit) - markbreaklist(labels, n.Init(), implicit) - markbreaklist(labels, n.Body(), implicit) - markbreaklist(labels, n.List(), implicit) - markbreaklist(labels, n.Rlist(), implicit) - } + mark(fn) } -func markbreaklist(labels *map[*types.Sym]ir.Node, l ir.Nodes, implicit ir.Node) { - s := l.Slice() - for i := 0; i < len(s); i++ { - markbreak(labels, s[i], implicit) - } -} - -// isterminating reports whether the Nodes list ends with a terminating statement. +// isTermNodes reports whether the Nodes list ends with a terminating statement. func isTermNodes(l ir.Nodes) bool { s := l.Slice() c := len(s) @@ -3723,7 +3724,7 @@ func isTermNodes(l ir.Nodes) bool { return isTermNode(s[c-1]) } -// Isterminating reports whether the node n, the last one in a +// isTermNode reports whether the node n, the last one in a // statement list, is a terminating statement. func isTermNode(n ir.Node) bool { switch n.Op() { @@ -3776,8 +3777,7 @@ func isTermNode(n ir.Node) bool { // checkreturn makes sure that fn terminates appropriately. func checkreturn(fn *ir.Func) { if fn.Type().NumResults() != 0 && fn.Body().Len() != 0 { - var labels map[*types.Sym]ir.Node - markbreaklist(&labels, fn.Body(), nil) + markBreak(fn) if !isTermNodes(fn.Body()) { base.ErrorfAt(fn.Endlineno, "missing return at end of function") } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 3d22c66d90..bbc08ab953 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -3786,107 +3786,91 @@ func usefield(n ir.Node) { Curfn.FieldTrack[sym] = struct{}{} } -func candiscardlist(l ir.Nodes) bool { - for _, n := range l.Slice() { - if !candiscard(n) { - return false +// hasSideEffects reports whether n contains any operations that could have observable side effects. +func hasSideEffects(n ir.Node) bool { + found := ir.Find(n, func(n ir.Node) interface{} { + switch n.Op() { + // Assume side effects unless we know otherwise. + default: + return n + + // No side effects here (arguments are checked separately). + case ir.ONAME, + ir.ONONAME, + ir.OTYPE, + ir.OPACK, + ir.OLITERAL, + ir.ONIL, + ir.OADD, + ir.OSUB, + ir.OOR, + ir.OXOR, + ir.OADDSTR, + ir.OADDR, + ir.OANDAND, + ir.OBYTES2STR, + ir.ORUNES2STR, + ir.OSTR2BYTES, + ir.OSTR2RUNES, + ir.OCAP, + ir.OCOMPLIT, + ir.OMAPLIT, + ir.OSTRUCTLIT, + ir.OARRAYLIT, + ir.OSLICELIT, + ir.OPTRLIT, + ir.OCONV, + ir.OCONVIFACE, + ir.OCONVNOP, + ir.ODOT, + ir.OEQ, + ir.ONE, + ir.OLT, + ir.OLE, + ir.OGT, + ir.OGE, + ir.OKEY, + ir.OSTRUCTKEY, + ir.OLEN, + ir.OMUL, + ir.OLSH, + ir.ORSH, + ir.OAND, + ir.OANDNOT, + ir.ONEW, + ir.ONOT, + ir.OBITNOT, + ir.OPLUS, + ir.ONEG, + ir.OOROR, + ir.OPAREN, + ir.ORUNESTR, + ir.OREAL, + ir.OIMAG, + ir.OCOMPLEX: + return nil + + // Only possible side effect is division by zero. + case ir.ODIV, ir.OMOD: + if n.Right().Op() != ir.OLITERAL || constant.Sign(n.Right().Val()) == 0 { + return n + } + + // Only possible side effect is panic on invalid size, + // but many makechan and makemap use size zero, which is definitely OK. + case ir.OMAKECHAN, ir.OMAKEMAP: + if !ir.IsConst(n.Left(), constant.Int) || constant.Sign(n.Left().Val()) != 0 { + return n + } + + // Only possible side effect is panic on invalid size. + // TODO(rsc): Merge with previous case (probably breaks toolstash -cmp). + case ir.OMAKESLICE, ir.OMAKESLICECOPY: + return n } - } - return true -} - -func candiscard(n ir.Node) bool { - if n == nil { - return true - } - - switch n.Op() { - default: - return false - - // Discardable as long as the subpieces are. - case ir.ONAME, - ir.ONONAME, - ir.OTYPE, - ir.OPACK, - ir.OLITERAL, - ir.ONIL, - ir.OADD, - ir.OSUB, - ir.OOR, - ir.OXOR, - ir.OADDSTR, - ir.OADDR, - ir.OANDAND, - ir.OBYTES2STR, - ir.ORUNES2STR, - ir.OSTR2BYTES, - ir.OSTR2RUNES, - ir.OCAP, - ir.OCOMPLIT, - ir.OMAPLIT, - ir.OSTRUCTLIT, - ir.OARRAYLIT, - ir.OSLICELIT, - ir.OPTRLIT, - ir.OCONV, - ir.OCONVIFACE, - ir.OCONVNOP, - ir.ODOT, - ir.OEQ, - ir.ONE, - ir.OLT, - ir.OLE, - ir.OGT, - ir.OGE, - ir.OKEY, - ir.OSTRUCTKEY, - ir.OLEN, - ir.OMUL, - ir.OLSH, - ir.ORSH, - ir.OAND, - ir.OANDNOT, - ir.ONEW, - ir.ONOT, - ir.OBITNOT, - ir.OPLUS, - ir.ONEG, - ir.OOROR, - ir.OPAREN, - ir.ORUNESTR, - ir.OREAL, - ir.OIMAG, - ir.OCOMPLEX: - break - - // Discardable as long as we know it's not division by zero. - case ir.ODIV, ir.OMOD: - if n.Right().Op() == ir.OLITERAL && constant.Sign(n.Right().Val()) != 0 { - break - } - return false - - // Discardable as long as we know it won't fail because of a bad size. - case ir.OMAKECHAN, ir.OMAKEMAP: - if ir.IsConst(n.Left(), constant.Int) && constant.Sign(n.Left().Val()) == 0 { - break - } - return false - - // Difficult to tell what sizes are okay. - case ir.OMAKESLICE: - return false - - case ir.OMAKESLICECOPY: - return false - } - - if !candiscard(n.Left()) || !candiscard(n.Right()) || !candiscardlist(n.Init()) || !candiscardlist(n.Body()) || !candiscardlist(n.List()) || !candiscardlist(n.Rlist()) { - return false - } - - return true + return nil + }) + return found != nil } // Rewrite From d855b30fe48fe108921733c8d86e42063a5c601f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 14:06:41 -0500 Subject: [PATCH 136/212] [dev.regabi] cmd/compile: use ir.EditChildren for inline rewriting This CL rephrases the general inlining rewriter in terms of ir.EditChildren. It is the final part of the code that was processing arbitrary nodes using Left, SetLeft, and so on. After this CL, there should be none left except for the implementations of DoChildren and EditChildren, which fall next. Passes buildall w/ toolstash -cmp. Change-Id: I9c36053360cd040710716f0b39397a80114be713 Reviewed-on: https://go-review.googlesource.com/c/go/+/275373 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/escape.go | 1 + src/cmd/compile/internal/gc/inl.go | 103 ++++++----------------- src/cmd/compile/internal/gc/typecheck.go | 5 ++ src/cmd/compile/internal/ir/expr.go | 12 +++ 4 files changed, 46 insertions(+), 75 deletions(-) diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 622edb9820..32bc7b297b 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -803,6 +803,7 @@ func (e *Escape) call(ks []EscHole, call, where ir.Node) { switch call.Op() { default: + ir.Dump("esc", call) base.Fatalf("unexpected call op: %v", call.Op()) case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 09ec0b6f99..8402852424 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -483,10 +483,11 @@ func inlcalls(fn *ir.Func) { // Most likely, the inlining will stop before we even hit the beginning of // the cycle again, but the map catches the unusual case. inlMap := make(map[*ir.Func]bool) - fn = inlnode(fn, maxCost, inlMap).(*ir.Func) - if fn != Curfn { - base.Fatalf("inlnode replaced curfn") + var edit func(ir.Node) ir.Node + edit = func(n ir.Node) ir.Node { + return inlnode(n, maxCost, inlMap, edit) } + ir.EditChildren(fn, edit) Curfn = savefn } @@ -521,13 +522,6 @@ func inlconv2list(n ir.Node) []ir.Node { return s } -func inlnodelist(l ir.Nodes, maxCost int32, inlMap map[*ir.Func]bool) { - s := l.Slice() - for i := range s { - s[i] = inlnode(s[i], maxCost, inlMap) - } -} - // inlnode recurses over the tree to find inlineable calls, which will // be turned into OINLCALLs by mkinlcall. When the recursion comes // back up will examine left, right, list, rlist, ninit, ntest, nincr, @@ -541,7 +535,7 @@ func inlnodelist(l ir.Nodes, maxCost int32, inlMap map[*ir.Func]bool) { // shorter and less complicated. // The result of inlnode MUST be assigned back to n, e.g. // n.Left = inlnode(n.Left) -func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { +func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.Node) ir.Node) ir.Node { if n == nil { return n } @@ -567,49 +561,7 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { lno := setlineno(n) - inlnodelist(n.Init(), maxCost, inlMap) - init := n.Init().Slice() - for i, n1 := range init { - if n1.Op() == ir.OINLCALL { - init[i] = inlconv2stmt(n1) - } - } - - n.SetLeft(inlnode(n.Left(), maxCost, inlMap)) - if n.Left() != nil && n.Left().Op() == ir.OINLCALL { - n.SetLeft(inlconv2expr(n.Left())) - } - - n.SetRight(inlnode(n.Right(), maxCost, inlMap)) - if n.Right() != nil && n.Right().Op() == ir.OINLCALL { - if n.Op() == ir.OFOR || n.Op() == ir.OFORUNTIL { - n.SetRight(inlconv2stmt(n.Right())) - } else { - n.SetRight(inlconv2expr(n.Right())) - } - } - - inlnodelist(n.List(), maxCost, inlMap) - s := n.List().Slice() - convert := inlconv2expr - if n.Op() == ir.OBLOCK { - convert = inlconv2stmt - } - for i, n1 := range s { - if n1 != nil && n1.Op() == ir.OINLCALL { - s[i] = convert(n1) - } - } - - inlnodelist(n.Body(), maxCost, inlMap) - s = n.Body().Slice() - for i, n1 := range s { - if n1.Op() == ir.OINLCALL { - s[i] = inlconv2stmt(n1) - } - } - - inlnodelist(n.Rlist(), maxCost, inlMap) + ir.EditChildren(n, edit) if n.Op() == ir.OAS2FUNC && n.Rlist().First().Op() == ir.OINLCALL { n.PtrRlist().Set(inlconv2list(n.Rlist().First())) @@ -618,17 +570,6 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { n = typecheck(n, ctxStmt) } - s = n.Rlist().Slice() - for i, n1 := range s { - if n1.Op() == ir.OINLCALL { - if n.Op() == ir.OIF { - s[i] = inlconv2stmt(n1) - } else { - s[i] = inlconv2expr(n1) - } - } - } - // with all the branches out of the way, it is now time to // transmogrify this node itself unless inhibited by the // switch at the top of this function. @@ -639,8 +580,10 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { } } + var call ir.Node switch n.Op() { case ir.OCALLFUNC: + call = n if base.Flag.LowerM > 3 { fmt.Printf("%v:call to func %+v\n", ir.Line(n), n.Left()) } @@ -648,10 +591,11 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { break } if fn := inlCallee(n.Left()); fn != nil && fn.Inl != nil { - n = mkinlcall(n, fn, maxCost, inlMap) + n = mkinlcall(n, fn, maxCost, inlMap, edit) } case ir.OCALLMETH: + call = n if base.Flag.LowerM > 3 { fmt.Printf("%v:call to meth %L\n", ir.Line(n), n.Left().Right()) } @@ -661,10 +605,25 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { base.Fatalf("no function type for [%p] %+v\n", n.Left(), n.Left()) } - n = mkinlcall(n, methodExprName(n.Left()).Func(), maxCost, inlMap) + n = mkinlcall(n, methodExprName(n.Left()).Func(), maxCost, inlMap, edit) } base.Pos = lno + + if n.Op() == ir.OINLCALL { + switch call.(*ir.CallExpr).Use { + default: + ir.Dump("call", call) + base.Fatalf("call missing use") + case ir.CallUseExpr: + n = inlconv2expr(n) + case ir.CallUseStmt: + n = inlconv2stmt(n) + case ir.CallUseList: + // leave for caller to convert + } + } + return n } @@ -805,7 +764,7 @@ var inlgen int // parameters. // The result of mkinlcall MUST be assigned back to n, e.g. // n.Left = mkinlcall(n.Left, fn, isddd) -func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool) ir.Node { +func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.Node) ir.Node) ir.Node { if fn.Inl == nil { if logopt.Enabled() { logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(Curfn), @@ -1131,13 +1090,7 @@ func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool) // instead we emit the things that the body needs // and each use must redo the inlining. // luckily these are small. - inlnodelist(call.Body(), maxCost, inlMap) - s := call.Body().Slice() - for i, n1 := range s { - if n1.Op() == ir.OINLCALL { - s[i] = inlconv2stmt(n1) - } - } + ir.EditChildren(call, edit) if base.Flag.LowerM > 2 { fmt.Printf("%v: After inlining %+v\n\n", ir.Line(call), call) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index a8acd468c9..65c5f2abce 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1280,6 +1280,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // call and call like case ir.OCALL: + n.(*ir.CallExpr).Use = ir.CallUseExpr + if top == ctxStmt { + n.(*ir.CallExpr).Use = ir.CallUseStmt + } typecheckslice(n.Init().Slice(), ctxStmt) // imported rewritten f(g()) calls (#30907) n.SetLeft(typecheck(n.Left(), ctxExpr|ctxType|ctxCallee)) if n.Left().Diag() { @@ -3294,6 +3298,7 @@ func typecheckas2(n ir.Node) { if cr != cl { goto mismatch } + r.(*ir.CallExpr).Use = ir.CallUseList n.SetOp(ir.OAS2FUNC) for i, l := range n.List().Slice() { f := r.Type().Field(i) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 49543f4286..9600d13d8e 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -148,6 +148,17 @@ func (n *BinaryExpr) SetOp(op Op) { } } +// A CallUse records how the result of the call is used: +type CallUse int + +const ( + _ CallUse = iota + + CallUseExpr // single expression result is used + CallUseList // list of results are used + CallUseStmt // results not used - call is a statement +) + // A CallExpr is a function call X(Args). type CallExpr struct { miniExpr @@ -157,6 +168,7 @@ type CallExpr struct { Rargs Nodes // TODO(rsc): Delete. body Nodes // TODO(rsc): Delete. DDD bool + Use CallUse noInline bool } From 18f2df7e810ac221d05577b746f2bf4e3cd789f4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 18:43:18 -0500 Subject: [PATCH 137/212] [dev.regabi] cmd/compile: implement copy for nodes Put each node in charge of making copies of its own slices. This removes a generic use of Body, SetBody, and so on in func Copy, heading toward removing those even from being used in package ir. Passes buildall w/ toolstash -cmp. Change-Id: I249b7fe54cf72e9d2f0467b10f3f257abf9b29b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/275374 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/copy.go | 26 +- src/cmd/compile/internal/ir/expr.go | 404 ++++++++++++++++++---------- src/cmd/compile/internal/ir/func.go | 2 +- src/cmd/compile/internal/ir/name.go | 4 +- src/cmd/compile/internal/ir/node.go | 19 +- src/cmd/compile/internal/ir/stmt.go | 310 +++++++++++++-------- src/cmd/compile/internal/ir/type.go | 48 +++- 7 files changed, 532 insertions(+), 281 deletions(-) diff --git a/src/cmd/compile/internal/ir/copy.go b/src/cmd/compile/internal/ir/copy.go index 2f340df1ab..8d174d6e53 100644 --- a/src/cmd/compile/internal/ir/copy.go +++ b/src/cmd/compile/internal/ir/copy.go @@ -43,7 +43,7 @@ func Orig(n Node) Node { // SepCopy returns a separate shallow copy of n, // breaking any Orig link to any other nodes. func SepCopy(n Node) Node { - n = n.rawCopy() + n = n.copy() if n, ok := n.(OrigNode); ok { n.SetOrig(n) } @@ -57,29 +57,11 @@ func SepCopy(n Node) Node { // The specific semantics surrounding Orig are subtle but right for most uses. // See issues #26855 and #27765 for pitfalls. func Copy(n Node) Node { - copy := n.rawCopy() + c := n.copy() if n, ok := n.(OrigNode); ok && n.Orig() == n { - copy.(OrigNode).SetOrig(copy) + c.(OrigNode).SetOrig(c) } - - // Copy lists so that updates to n.List[0] - // don't affect copy.List[0] and vice versa, - // same as updates to Left and Right. - // TODO(rsc): Eventually the Node implementations will need to do this. - if l := copy.List(); l.Len() > 0 { - copy.SetList(copyList(l)) - } - if l := copy.Rlist(); l.Len() > 0 { - copy.SetRlist(copyList(l)) - } - if l := copy.Init(); l.Len() > 0 { - copy.SetInit(copyList(l)) - } - if l := copy.Body(); l.Len() > 0 { - copy.SetBody(copyList(l)) - } - - return copy + return c } func copyList(x Nodes) Nodes { diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 9600d13d8e..7431a56d94 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -76,10 +76,16 @@ func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr { func (n *AddStringExpr) String() string { return fmt.Sprint(n) } func (n *AddStringExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AddStringExpr) rawCopy() Node { c := *n; return &c } -func (n *AddStringExpr) List() Nodes { return n.list } -func (n *AddStringExpr) PtrList() *Nodes { return &n.list } -func (n *AddStringExpr) SetList(x Nodes) { n.list = x } +func (n *AddStringExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.list = c.list.Copy() + return &c +} + +func (n *AddStringExpr) List() Nodes { return n.list } +func (n *AddStringExpr) PtrList() *Nodes { return &n.list } +func (n *AddStringExpr) SetList(x Nodes) { n.list = x } // An AddrExpr is an address-of expression &X. // It may end up being a normal address-of or an allocation of a composite literal. @@ -98,11 +104,16 @@ func NewAddrExpr(pos src.XPos, x Node) *AddrExpr { func (n *AddrExpr) String() string { return fmt.Sprint(n) } func (n *AddrExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AddrExpr) rawCopy() Node { c := *n; return &c } -func (n *AddrExpr) Left() Node { return n.X } -func (n *AddrExpr) SetLeft(x Node) { n.X = x } -func (n *AddrExpr) Right() Node { return n.Alloc } -func (n *AddrExpr) SetRight(x Node) { n.Alloc = x } +func (n *AddrExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *AddrExpr) Left() Node { return n.X } +func (n *AddrExpr) SetLeft(x Node) { n.X = x } +func (n *AddrExpr) Right() Node { return n.Alloc } +func (n *AddrExpr) SetRight(x Node) { n.Alloc = x } func (n *AddrExpr) SetOp(op Op) { switch op { @@ -130,11 +141,16 @@ func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr { func (n *BinaryExpr) String() string { return fmt.Sprint(n) } func (n *BinaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *BinaryExpr) rawCopy() Node { c := *n; return &c } -func (n *BinaryExpr) Left() Node { return n.X } -func (n *BinaryExpr) SetLeft(x Node) { n.X = x } -func (n *BinaryExpr) Right() Node { return n.Y } -func (n *BinaryExpr) SetRight(y Node) { n.Y = y } +func (n *BinaryExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *BinaryExpr) Left() Node { return n.X } +func (n *BinaryExpr) SetLeft(x Node) { n.X = x } +func (n *BinaryExpr) Right() Node { return n.Y } +func (n *BinaryExpr) SetRight(y Node) { n.Y = y } func (n *BinaryExpr) SetOp(op Op) { switch op { @@ -183,24 +199,32 @@ func NewCallExpr(pos src.XPos, fun Node, args []Node) *CallExpr { func (n *CallExpr) String() string { return fmt.Sprint(n) } func (n *CallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CallExpr) rawCopy() Node { c := *n; return &c } -func (n *CallExpr) Orig() Node { return n.orig } -func (n *CallExpr) SetOrig(x Node) { n.orig = x } -func (n *CallExpr) Left() Node { return n.X } -func (n *CallExpr) SetLeft(x Node) { n.X = x } -func (n *CallExpr) List() Nodes { return n.Args } -func (n *CallExpr) PtrList() *Nodes { return &n.Args } -func (n *CallExpr) SetList(x Nodes) { n.Args = x } -func (n *CallExpr) Rlist() Nodes { return n.Rargs } -func (n *CallExpr) PtrRlist() *Nodes { return &n.Rargs } -func (n *CallExpr) SetRlist(x Nodes) { n.Rargs = x } -func (n *CallExpr) IsDDD() bool { return n.DDD } -func (n *CallExpr) SetIsDDD(x bool) { n.DDD = x } -func (n *CallExpr) NoInline() bool { return n.noInline } -func (n *CallExpr) SetNoInline(x bool) { n.noInline = x } -func (n *CallExpr) Body() Nodes { return n.body } -func (n *CallExpr) PtrBody() *Nodes { return &n.body } -func (n *CallExpr) SetBody(x Nodes) { n.body = x } +func (n *CallExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.Args = c.Args.Copy() + c.Rargs = c.Rargs.Copy() + c.body = c.body.Copy() + return &c +} + +func (n *CallExpr) Orig() Node { return n.orig } +func (n *CallExpr) SetOrig(x Node) { n.orig = x } +func (n *CallExpr) Left() Node { return n.X } +func (n *CallExpr) SetLeft(x Node) { n.X = x } +func (n *CallExpr) List() Nodes { return n.Args } +func (n *CallExpr) PtrList() *Nodes { return &n.Args } +func (n *CallExpr) SetList(x Nodes) { n.Args = x } +func (n *CallExpr) Rlist() Nodes { return n.Rargs } +func (n *CallExpr) PtrRlist() *Nodes { return &n.Rargs } +func (n *CallExpr) SetRlist(x Nodes) { n.Rargs = x } +func (n *CallExpr) IsDDD() bool { return n.DDD } +func (n *CallExpr) SetIsDDD(x bool) { n.DDD = x } +func (n *CallExpr) NoInline() bool { return n.noInline } +func (n *CallExpr) SetNoInline(x bool) { n.noInline = x } +func (n *CallExpr) Body() Nodes { return n.body } +func (n *CallExpr) PtrBody() *Nodes { return &n.body } +func (n *CallExpr) SetBody(x Nodes) { n.body = x } func (n *CallExpr) SetOp(op Op) { switch op { @@ -231,11 +255,16 @@ func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallP func (n *CallPartExpr) String() string { return fmt.Sprint(n) } func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CallPartExpr) rawCopy() Node { c := *n; return &c } -func (n *CallPartExpr) Func() *Func { return n.fn } -func (n *CallPartExpr) Left() Node { return n.X } -func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym } -func (n *CallPartExpr) SetLeft(x Node) { n.X = x } +func (n *CallPartExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *CallPartExpr) Func() *Func { return n.fn } +func (n *CallPartExpr) Left() Node { return n.X } +func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym } +func (n *CallPartExpr) SetLeft(x Node) { n.X = x } // A ClosureExpr is a function literal expression. type ClosureExpr struct { @@ -252,8 +281,13 @@ func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr { func (n *ClosureExpr) String() string { return fmt.Sprint(n) } func (n *ClosureExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ClosureExpr) rawCopy() Node { c := *n; return &c } -func (n *ClosureExpr) Func() *Func { return n.fn } +func (n *ClosureExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *ClosureExpr) Func() *Func { return n.fn } // A ClosureRead denotes reading a variable stored within a closure struct. type ClosureRead struct { @@ -270,9 +304,14 @@ func NewClosureRead(typ *types.Type, offset int64) *ClosureRead { func (n *ClosureRead) String() string { return fmt.Sprint(n) } func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ClosureRead) rawCopy() Node { c := *n; return &c } -func (n *ClosureRead) Type() *types.Type { return n.typ } -func (n *ClosureRead) Offset() int64 { return n.offset } +func (n *ClosureRead) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *ClosureRead) Type() *types.Type { return n.typ } +func (n *ClosureRead) Offset() int64 { return n.offset } // A CompLitExpr is a composite literal Type{Vals}. // Before type-checking, the type is Ntype. @@ -294,14 +333,20 @@ func NewCompLitExpr(pos src.XPos, typ Ntype, list []Node) *CompLitExpr { func (n *CompLitExpr) String() string { return fmt.Sprint(n) } func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CompLitExpr) rawCopy() Node { c := *n; return &c } -func (n *CompLitExpr) Orig() Node { return n.orig } -func (n *CompLitExpr) SetOrig(x Node) { n.orig = x } -func (n *CompLitExpr) Right() Node { return n.Ntype } -func (n *CompLitExpr) SetRight(x Node) { n.Ntype = toNtype(x) } -func (n *CompLitExpr) List() Nodes { return n.list } -func (n *CompLitExpr) PtrList() *Nodes { return &n.list } -func (n *CompLitExpr) SetList(x Nodes) { n.list = x } +func (n *CompLitExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.list = c.list.Copy() + return &c +} + +func (n *CompLitExpr) Orig() Node { return n.orig } +func (n *CompLitExpr) SetOrig(x Node) { n.orig = x } +func (n *CompLitExpr) Right() Node { return n.Ntype } +func (n *CompLitExpr) SetRight(x Node) { n.Ntype = toNtype(x) } +func (n *CompLitExpr) List() Nodes { return n.list } +func (n *CompLitExpr) PtrList() *Nodes { return &n.list } +func (n *CompLitExpr) SetList(x Nodes) { n.list = x } func (n *CompLitExpr) SetOp(op Op) { switch op { @@ -330,11 +375,12 @@ func NewConstExpr(val constant.Value, orig Node) Node { func (n *ConstExpr) String() string { return fmt.Sprint(n) } func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ConstExpr) rawCopy() Node { c := *n; return &c } -func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() } -func (n *ConstExpr) Orig() Node { return n.orig } -func (n *ConstExpr) SetOrig(orig Node) { panic(n.no("SetOrig")) } -func (n *ConstExpr) Val() constant.Value { return n.val } +func (n *ConstExpr) copy() Node { c := *n; return &c } + +func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() } +func (n *ConstExpr) Orig() Node { return n.orig } +func (n *ConstExpr) SetOrig(orig Node) { panic(n.no("SetOrig")) } +func (n *ConstExpr) Val() constant.Value { return n.val } // A ConvExpr is a conversion Type(X). // It may end up being a value or a type. @@ -355,9 +401,15 @@ func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr { func (n *ConvExpr) String() string { return fmt.Sprint(n) } func (n *ConvExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ConvExpr) rawCopy() Node { c := *n; return &c } -func (n *ConvExpr) Left() Node { return n.X } -func (n *ConvExpr) SetLeft(x Node) { n.X = x } +func (n *ConvExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *ConvExpr) rawCopy() Node { c := *n; return &c } +func (n *ConvExpr) Left() Node { return n.X } +func (n *ConvExpr) SetLeft(x Node) { n.X = x } func (n *ConvExpr) SetOp(op Op) { switch op { @@ -385,13 +437,18 @@ func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr { func (n *IndexExpr) String() string { return fmt.Sprint(n) } func (n *IndexExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *IndexExpr) rawCopy() Node { c := *n; return &c } -func (n *IndexExpr) Left() Node { return n.X } -func (n *IndexExpr) SetLeft(x Node) { n.X = x } -func (n *IndexExpr) Right() Node { return n.Index } -func (n *IndexExpr) SetRight(y Node) { n.Index = y } -func (n *IndexExpr) IndexMapLValue() bool { return n.Assigned } -func (n *IndexExpr) SetIndexMapLValue(x bool) { n.Assigned = x } +func (n *IndexExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *IndexExpr) Left() Node { return n.X } +func (n *IndexExpr) SetLeft(x Node) { n.X = x } +func (n *IndexExpr) Right() Node { return n.Index } +func (n *IndexExpr) SetRight(y Node) { n.Index = y } +func (n *IndexExpr) IndexMapLValue() bool { return n.Assigned } +func (n *IndexExpr) SetIndexMapLValue(x bool) { n.Assigned = x } func (n *IndexExpr) SetOp(op Op) { switch op { @@ -422,15 +479,20 @@ func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr { func (n *KeyExpr) String() string { return fmt.Sprint(n) } func (n *KeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *KeyExpr) rawCopy() Node { c := *n; return &c } -func (n *KeyExpr) Left() Node { return n.Key } -func (n *KeyExpr) SetLeft(x Node) { n.Key = x } -func (n *KeyExpr) Right() Node { return n.Value } -func (n *KeyExpr) SetRight(y Node) { n.Value = y } -func (n *KeyExpr) Sym() *types.Sym { return n.sym } -func (n *KeyExpr) SetSym(x *types.Sym) { n.sym = x } -func (n *KeyExpr) Offset() int64 { return n.offset } -func (n *KeyExpr) SetOffset(x int64) { n.offset = x } +func (n *KeyExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *KeyExpr) Left() Node { return n.Key } +func (n *KeyExpr) SetLeft(x Node) { n.Key = x } +func (n *KeyExpr) Right() Node { return n.Value } +func (n *KeyExpr) SetRight(y Node) { n.Value = y } +func (n *KeyExpr) Sym() *types.Sym { return n.sym } +func (n *KeyExpr) SetSym(x *types.Sym) { n.sym = x } +func (n *KeyExpr) Offset() int64 { return n.offset } +func (n *KeyExpr) SetOffset(x int64) { n.offset = x } func (n *KeyExpr) SetOp(op Op) { switch op { @@ -459,13 +521,20 @@ func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { func (n *InlinedCallExpr) String() string { return fmt.Sprint(n) } func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *InlinedCallExpr) rawCopy() Node { c := *n; return &c } -func (n *InlinedCallExpr) Body() Nodes { return n.body } -func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.body } -func (n *InlinedCallExpr) SetBody(x Nodes) { n.body = x } -func (n *InlinedCallExpr) Rlist() Nodes { return n.ReturnVars } -func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars } -func (n *InlinedCallExpr) SetRlist(x Nodes) { n.ReturnVars = x } +func (n *InlinedCallExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.body = c.body.Copy() + c.ReturnVars = c.ReturnVars.Copy() + return &c +} + +func (n *InlinedCallExpr) Body() Nodes { return n.body } +func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.body } +func (n *InlinedCallExpr) SetBody(x Nodes) { n.body = x } +func (n *InlinedCallExpr) Rlist() Nodes { return n.ReturnVars } +func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars } +func (n *InlinedCallExpr) SetRlist(x Nodes) { n.ReturnVars = x } // A MakeExpr is a make expression: make(Type[, Len[, Cap]]). // Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY, @@ -485,11 +554,16 @@ func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr { func (n *MakeExpr) String() string { return fmt.Sprint(n) } func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *MakeExpr) rawCopy() Node { c := *n; return &c } -func (n *MakeExpr) Left() Node { return n.Len } -func (n *MakeExpr) SetLeft(x Node) { n.Len = x } -func (n *MakeExpr) Right() Node { return n.Cap } -func (n *MakeExpr) SetRight(x Node) { n.Cap = x } +func (n *MakeExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *MakeExpr) Left() Node { return n.Len } +func (n *MakeExpr) SetLeft(x Node) { n.Len = x } +func (n *MakeExpr) Right() Node { return n.Cap } +func (n *MakeExpr) SetRight(x Node) { n.Cap = x } func (n *MakeExpr) SetOp(op Op) { switch op { @@ -521,17 +595,22 @@ func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr { func (n *MethodExpr) String() string { return fmt.Sprint(n) } func (n *MethodExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *MethodExpr) rawCopy() Node { c := *n; return &c } -func (n *MethodExpr) Left() Node { return n.X } -func (n *MethodExpr) SetLeft(x Node) { n.X = x } -func (n *MethodExpr) Right() Node { return n.M } -func (n *MethodExpr) SetRight(y Node) { n.M = y } -func (n *MethodExpr) Sym() *types.Sym { return n.sym } -func (n *MethodExpr) SetSym(x *types.Sym) { n.sym = x } -func (n *MethodExpr) Offset() int64 { return n.offset } -func (n *MethodExpr) SetOffset(x int64) { n.offset = x } -func (n *MethodExpr) Class() Class { return n.class } -func (n *MethodExpr) SetClass(x Class) { n.class = x } +func (n *MethodExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *MethodExpr) Left() Node { return n.X } +func (n *MethodExpr) SetLeft(x Node) { n.X = x } +func (n *MethodExpr) Right() Node { return n.M } +func (n *MethodExpr) SetRight(y Node) { n.M = y } +func (n *MethodExpr) Sym() *types.Sym { return n.sym } +func (n *MethodExpr) SetSym(x *types.Sym) { n.sym = x } +func (n *MethodExpr) Offset() int64 { return n.offset } +func (n *MethodExpr) SetOffset(x int64) { n.offset = x } +func (n *MethodExpr) Class() Class { return n.class } +func (n *MethodExpr) SetClass(x Class) { n.class = x } // A NilExpr represents the predefined untyped constant nil. // (It may be copied and assigned a type, though.) @@ -549,9 +628,14 @@ func NewNilExpr(pos src.XPos) *NilExpr { func (n *NilExpr) String() string { return fmt.Sprint(n) } func (n *NilExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *NilExpr) rawCopy() Node { c := *n; return &c } -func (n *NilExpr) Sym() *types.Sym { return n.sym } -func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x } +func (n *NilExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *NilExpr) Sym() *types.Sym { return n.sym } +func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x } // A ParenExpr is a parenthesized expression (X). // It may end up being a value or a type. @@ -569,9 +653,14 @@ func NewParenExpr(pos src.XPos, x Node) *ParenExpr { func (n *ParenExpr) String() string { return fmt.Sprint(n) } func (n *ParenExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ParenExpr) rawCopy() Node { c := *n; return &c } -func (n *ParenExpr) Left() Node { return n.X } -func (n *ParenExpr) SetLeft(x Node) { n.X = x } +func (n *ParenExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *ParenExpr) Left() Node { return n.X } +func (n *ParenExpr) SetLeft(x Node) { n.X = x } func (*ParenExpr) CanBeNtype() {} @@ -599,9 +688,14 @@ func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr { func (n *ResultExpr) String() string { return fmt.Sprint(n) } func (n *ResultExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ResultExpr) rawCopy() Node { c := *n; return &c } -func (n *ResultExpr) Offset() int64 { return n.offset } -func (n *ResultExpr) SetOffset(x int64) { n.offset = x } +func (n *ResultExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *ResultExpr) Offset() int64 { return n.offset } +func (n *ResultExpr) SetOffset(x int64) { n.offset = x } // A SelectorExpr is a selector expression X.Sym. type SelectorExpr struct { @@ -631,13 +725,18 @@ func (n *SelectorExpr) SetOp(op Op) { func (n *SelectorExpr) String() string { return fmt.Sprint(n) } func (n *SelectorExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SelectorExpr) rawCopy() Node { c := *n; return &c } -func (n *SelectorExpr) Left() Node { return n.X } -func (n *SelectorExpr) SetLeft(x Node) { n.X = x } -func (n *SelectorExpr) Sym() *types.Sym { return n.Sel } -func (n *SelectorExpr) SetSym(x *types.Sym) { n.Sel = x } -func (n *SelectorExpr) Offset() int64 { return n.offset } -func (n *SelectorExpr) SetOffset(x int64) { n.offset = x } +func (n *SelectorExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *SelectorExpr) Left() Node { return n.X } +func (n *SelectorExpr) SetLeft(x Node) { n.X = x } +func (n *SelectorExpr) Sym() *types.Sym { return n.Sel } +func (n *SelectorExpr) SetSym(x *types.Sym) { n.Sel = x } +func (n *SelectorExpr) Offset() int64 { return n.offset } +func (n *SelectorExpr) SetOffset(x int64) { n.offset = x } // Before type-checking, bytes.Buffer is a SelectorExpr. // After type-checking it becomes a Name. @@ -659,12 +758,18 @@ func NewSliceExpr(pos src.XPos, op Op, x Node) *SliceExpr { func (n *SliceExpr) String() string { return fmt.Sprint(n) } func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SliceExpr) rawCopy() Node { c := *n; return &c } -func (n *SliceExpr) Left() Node { return n.X } -func (n *SliceExpr) SetLeft(x Node) { n.X = x } -func (n *SliceExpr) List() Nodes { return n.list } -func (n *SliceExpr) PtrList() *Nodes { return &n.list } -func (n *SliceExpr) SetList(x Nodes) { n.list = x } +func (n *SliceExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.list = c.list.Copy() + return &c +} + +func (n *SliceExpr) Left() Node { return n.X } +func (n *SliceExpr) SetLeft(x Node) { n.X = x } +func (n *SliceExpr) List() Nodes { return n.list } +func (n *SliceExpr) PtrList() *Nodes { return &n.list } +func (n *SliceExpr) SetList(x Nodes) { n.list = x } func (n *SliceExpr) SetOp(op Op) { switch op { @@ -761,12 +866,17 @@ func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *Slic func (n *SliceHeaderExpr) String() string { return fmt.Sprint(n) } func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SliceHeaderExpr) rawCopy() Node { c := *n; return &c } -func (n *SliceHeaderExpr) Left() Node { return n.Ptr } -func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x } -func (n *SliceHeaderExpr) List() Nodes { return n.lenCap } -func (n *SliceHeaderExpr) PtrList() *Nodes { return &n.lenCap } -func (n *SliceHeaderExpr) SetList(x Nodes) { n.lenCap = x } +func (n *SliceHeaderExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *SliceHeaderExpr) Left() Node { return n.Ptr } +func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x } +func (n *SliceHeaderExpr) List() Nodes { return n.lenCap } +func (n *SliceHeaderExpr) PtrList() *Nodes { return &n.lenCap } +func (n *SliceHeaderExpr) SetList(x Nodes) { n.lenCap = x } // A StarExpr is a dereference expression *X. // It may end up being a value or a type. @@ -784,9 +894,14 @@ func NewStarExpr(pos src.XPos, x Node) *StarExpr { func (n *StarExpr) String() string { return fmt.Sprint(n) } func (n *StarExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *StarExpr) rawCopy() Node { c := *n; return &c } -func (n *StarExpr) Left() Node { return n.X } -func (n *StarExpr) SetLeft(x Node) { n.X = x } +func (n *StarExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *StarExpr) Left() Node { return n.X } +func (n *StarExpr) SetLeft(x Node) { n.X = x } func (*StarExpr) CanBeNtype() {} @@ -828,14 +943,20 @@ func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr { func (n *TypeAssertExpr) String() string { return fmt.Sprint(n) } func (n *TypeAssertExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *TypeAssertExpr) rawCopy() Node { c := *n; return &c } -func (n *TypeAssertExpr) Left() Node { return n.X } -func (n *TypeAssertExpr) SetLeft(x Node) { n.X = x } -func (n *TypeAssertExpr) Right() Node { return n.Ntype } -func (n *TypeAssertExpr) SetRight(x Node) { n.Ntype = x } // TODO: toNtype(x) -func (n *TypeAssertExpr) List() Nodes { return n.Itab } -func (n *TypeAssertExpr) PtrList() *Nodes { return &n.Itab } -func (n *TypeAssertExpr) SetList(x Nodes) { n.Itab = x } +func (n *TypeAssertExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.Itab = c.Itab.Copy() + return &c +} + +func (n *TypeAssertExpr) Left() Node { return n.X } +func (n *TypeAssertExpr) SetLeft(x Node) { n.X = x } +func (n *TypeAssertExpr) Right() Node { return n.Ntype } +func (n *TypeAssertExpr) SetRight(x Node) { n.Ntype = x } // TODO: toNtype(x) +func (n *TypeAssertExpr) List() Nodes { return n.Itab } +func (n *TypeAssertExpr) PtrList() *Nodes { return &n.Itab } +func (n *TypeAssertExpr) SetList(x Nodes) { n.Itab = x } func (n *TypeAssertExpr) SetOp(op Op) { switch op { @@ -862,9 +983,14 @@ func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr { func (n *UnaryExpr) String() string { return fmt.Sprint(n) } func (n *UnaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *UnaryExpr) rawCopy() Node { c := *n; return &c } -func (n *UnaryExpr) Left() Node { return n.X } -func (n *UnaryExpr) SetLeft(x Node) { n.X = x } +func (n *UnaryExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *UnaryExpr) Left() Node { return n.X } +func (n *UnaryExpr) SetLeft(x Node) { n.X = x } func (n *UnaryExpr) SetOp(op Op) { switch op { diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 98830fb502..ae803cd6a5 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -117,7 +117,7 @@ func NewFunc(pos src.XPos) *Func { func (f *Func) String() string { return fmt.Sprint(f) } func (f *Func) Format(s fmt.State, verb rune) { FmtNode(f, s, verb) } -func (f *Func) rawCopy() Node { panic(f.no("rawCopy")) } +func (f *Func) copy() Node { panic(f.no("copy")) } func (f *Func) Func() *Func { return f } func (f *Func) Body() Nodes { return f.body } func (f *Func) PtrBody() *Nodes { return &f.body } diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 67d4d2b391..dc8c58e4f4 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -151,7 +151,7 @@ func newNameAt(pos src.XPos, op Op, sym *types.Sym) *Name { func (n *Name) String() string { return fmt.Sprint(n) } func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *Name) rawCopy() Node { c := *n; return &c } +func (n *Name) copy() Node { c := *n; return &c } func (n *Name) Name() *Name { return n } func (n *Name) Sym() *types.Sym { return n.sym } func (n *Name) SetSym(x *types.Sym) { n.sym = x } @@ -323,7 +323,7 @@ type PkgName struct { func (p *PkgName) String() string { return fmt.Sprint(p) } func (p *PkgName) Format(s fmt.State, verb rune) { FmtNode(p, s, verb) } -func (p *PkgName) rawCopy() Node { c := *p; return &c } +func (p *PkgName) copy() Node { c := *p; return &c } func (p *PkgName) Sym() *types.Sym { return p.sym } func (*PkgName) CanBeNtype() {} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index c3184a3a0b..705eb9e47e 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -27,8 +27,8 @@ type Node interface { Pos() src.XPos SetPos(x src.XPos) - // For making copies. Mainly used by Copy and SepCopy. - rawCopy() Node + // For making copies. For Copy and SepCopy. + copy() Node // Abstract graph structure, for generic traversals. Op() Op @@ -521,6 +521,21 @@ func (n *Nodes) AppendNodes(n2 *Nodes) { n2.slice = nil } +// Copy returns a copy of the content of the slice. +func (n Nodes) Copy() Nodes { + var c Nodes + if n.slice == nil { + return c + } + c.slice = new([]Node) + if *n.slice == nil { + return c + } + *c.slice = make([]Node, n.Len()) + copy(*c.slice, n.Slice()) + return c +} + // nodeQueue is a FIFO queue of *Node. The zero value of nodeQueue is // a ready-to-use empty queue. type NodeQueue struct { diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index a6bbab4889..5af6a62cf2 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -31,7 +31,7 @@ func NewDecl(pos src.XPos, op Op, x Node) *Decl { func (n *Decl) String() string { return fmt.Sprint(n) } func (n *Decl) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *Decl) rawCopy() Node { c := *n; return &c } +func (n *Decl) copy() Node { c := *n; return &c } func (n *Decl) Left() Node { return n.X } func (n *Decl) SetLeft(x Node) { n.X = x } @@ -70,7 +70,13 @@ func NewAssignListStmt(pos src.XPos, lhs, rhs []Node) *AssignListStmt { func (n *AssignListStmt) String() string { return fmt.Sprint(n) } func (n *AssignListStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AssignListStmt) rawCopy() Node { c := *n; return &c } +func (n *AssignListStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Lhs = c.Lhs.Copy() + c.Rhs = c.Rhs.Copy() + return &c +} func (n *AssignListStmt) List() Nodes { return n.Lhs } func (n *AssignListStmt) PtrList() *Nodes { return &n.Lhs } @@ -112,7 +118,11 @@ func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt { func (n *AssignStmt) String() string { return fmt.Sprint(n) } func (n *AssignStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AssignStmt) rawCopy() Node { c := *n; return &c } +func (n *AssignStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} func (n *AssignStmt) Left() Node { return n.X } func (n *AssignStmt) SetLeft(x Node) { n.X = x } @@ -151,7 +161,11 @@ func NewAssignOpStmt(pos src.XPos, op Op, x, y Node) *AssignOpStmt { func (n *AssignOpStmt) String() string { return fmt.Sprint(n) } func (n *AssignOpStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AssignOpStmt) rawCopy() Node { c := *n; return &c } +func (n *AssignOpStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} func (n *AssignOpStmt) Left() Node { return n.X } func (n *AssignOpStmt) SetLeft(x Node) { n.X = x } @@ -180,10 +194,16 @@ func NewBlockStmt(pos src.XPos, list []Node) *BlockStmt { func (n *BlockStmt) String() string { return fmt.Sprint(n) } func (n *BlockStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *BlockStmt) rawCopy() Node { c := *n; return &c } -func (n *BlockStmt) List() Nodes { return n.list } -func (n *BlockStmt) PtrList() *Nodes { return &n.list } -func (n *BlockStmt) SetList(x Nodes) { n.list = x } +func (n *BlockStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.list = c.list.Copy() + return &c +} + +func (n *BlockStmt) List() Nodes { return n.list } +func (n *BlockStmt) PtrList() *Nodes { return &n.list } +func (n *BlockStmt) SetList(x Nodes) { n.list = x } // A BranchStmt is a break, continue, fallthrough, or goto statement. // @@ -209,9 +229,14 @@ func NewBranchStmt(pos src.XPos, op Op, label *types.Sym) *BranchStmt { func (n *BranchStmt) String() string { return fmt.Sprint(n) } func (n *BranchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *BranchStmt) rawCopy() Node { c := *n; return &c } -func (n *BranchStmt) Sym() *types.Sym { return n.Label } -func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym } +func (n *BranchStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *BranchStmt) Sym() *types.Sym { return n.Label } +func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym } // A CaseStmt is a case statement in a switch or select: case List: Body. type CaseStmt struct { @@ -233,18 +258,26 @@ func NewCaseStmt(pos src.XPos, list, body []Node) *CaseStmt { func (n *CaseStmt) String() string { return fmt.Sprint(n) } func (n *CaseStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CaseStmt) rawCopy() Node { c := *n; return &c } -func (n *CaseStmt) List() Nodes { return n.list } -func (n *CaseStmt) PtrList() *Nodes { return &n.list } -func (n *CaseStmt) SetList(x Nodes) { n.list = x } -func (n *CaseStmt) Body() Nodes { return n.body } -func (n *CaseStmt) PtrBody() *Nodes { return &n.body } -func (n *CaseStmt) SetBody(x Nodes) { n.body = x } -func (n *CaseStmt) Rlist() Nodes { return n.Vars } -func (n *CaseStmt) PtrRlist() *Nodes { return &n.Vars } -func (n *CaseStmt) SetRlist(x Nodes) { n.Vars = x } -func (n *CaseStmt) Left() Node { return n.Comm } -func (n *CaseStmt) SetLeft(x Node) { n.Comm = x } +func (n *CaseStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Vars = c.Vars.Copy() + c.list = c.list.Copy() + c.body = c.body.Copy() + return &c +} + +func (n *CaseStmt) List() Nodes { return n.list } +func (n *CaseStmt) PtrList() *Nodes { return &n.list } +func (n *CaseStmt) SetList(x Nodes) { n.list = x } +func (n *CaseStmt) Body() Nodes { return n.body } +func (n *CaseStmt) PtrBody() *Nodes { return &n.body } +func (n *CaseStmt) SetBody(x Nodes) { n.body = x } +func (n *CaseStmt) Rlist() Nodes { return n.Vars } +func (n *CaseStmt) PtrRlist() *Nodes { return &n.Vars } +func (n *CaseStmt) SetRlist(x Nodes) { n.Vars = x } +func (n *CaseStmt) Left() Node { return n.Comm } +func (n *CaseStmt) SetLeft(x Node) { n.Comm = x } // A DeferStmt is a defer statement: defer Call. type DeferStmt struct { @@ -261,7 +294,11 @@ func NewDeferStmt(pos src.XPos, call Node) *DeferStmt { func (n *DeferStmt) String() string { return fmt.Sprint(n) } func (n *DeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *DeferStmt) rawCopy() Node { c := *n; return &c } +func (n *DeferStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} func (n *DeferStmt) Left() Node { return n.Call } func (n *DeferStmt) SetLeft(x Node) { n.Call = x } @@ -289,21 +326,28 @@ func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStm func (n *ForStmt) String() string { return fmt.Sprint(n) } func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ForStmt) rawCopy() Node { c := *n; return &c } -func (n *ForStmt) Sym() *types.Sym { return n.Label } -func (n *ForStmt) SetSym(x *types.Sym) { n.Label = x } -func (n *ForStmt) Left() Node { return n.Cond } -func (n *ForStmt) SetLeft(x Node) { n.Cond = x } -func (n *ForStmt) Right() Node { return n.Post } -func (n *ForStmt) SetRight(x Node) { n.Post = x } -func (n *ForStmt) Body() Nodes { return n.body } -func (n *ForStmt) PtrBody() *Nodes { return &n.body } -func (n *ForStmt) SetBody(x Nodes) { n.body = x } -func (n *ForStmt) List() Nodes { return n.Late } -func (n *ForStmt) PtrList() *Nodes { return &n.Late } -func (n *ForStmt) SetList(x Nodes) { n.Late = x } -func (n *ForStmt) HasBreak() bool { return n.hasBreak } -func (n *ForStmt) SetHasBreak(b bool) { n.hasBreak = b } +func (n *ForStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Late = c.Late.Copy() + c.body = c.body.Copy() + return &c +} + +func (n *ForStmt) Sym() *types.Sym { return n.Label } +func (n *ForStmt) SetSym(x *types.Sym) { n.Label = x } +func (n *ForStmt) Left() Node { return n.Cond } +func (n *ForStmt) SetLeft(x Node) { n.Cond = x } +func (n *ForStmt) Right() Node { return n.Post } +func (n *ForStmt) SetRight(x Node) { n.Post = x } +func (n *ForStmt) Body() Nodes { return n.body } +func (n *ForStmt) PtrBody() *Nodes { return &n.body } +func (n *ForStmt) SetBody(x Nodes) { n.body = x } +func (n *ForStmt) List() Nodes { return n.Late } +func (n *ForStmt) PtrList() *Nodes { return &n.Late } +func (n *ForStmt) SetList(x Nodes) { n.Late = x } +func (n *ForStmt) HasBreak() bool { return n.hasBreak } +func (n *ForStmt) SetHasBreak(b bool) { n.hasBreak = b } func (n *ForStmt) SetOp(op Op) { if op != OFOR && op != OFORUNTIL { @@ -327,7 +371,11 @@ func NewGoStmt(pos src.XPos, call Node) *GoStmt { func (n *GoStmt) String() string { return fmt.Sprint(n) } func (n *GoStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *GoStmt) rawCopy() Node { c := *n; return &c } +func (n *GoStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} func (n *GoStmt) Left() Node { return n.Call } func (n *GoStmt) SetLeft(x Node) { n.Call = x } @@ -352,17 +400,24 @@ func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt { func (n *IfStmt) String() string { return fmt.Sprint(n) } func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *IfStmt) rawCopy() Node { c := *n; return &c } -func (n *IfStmt) Left() Node { return n.Cond } -func (n *IfStmt) SetLeft(x Node) { n.Cond = x } -func (n *IfStmt) Body() Nodes { return n.body } -func (n *IfStmt) PtrBody() *Nodes { return &n.body } -func (n *IfStmt) SetBody(x Nodes) { n.body = x } -func (n *IfStmt) Rlist() Nodes { return n.Else } -func (n *IfStmt) PtrRlist() *Nodes { return &n.Else } -func (n *IfStmt) SetRlist(x Nodes) { n.Else = x } -func (n *IfStmt) Likely() bool { return n.likely } -func (n *IfStmt) SetLikely(x bool) { n.likely = x } +func (n *IfStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.body = c.body.Copy() + c.Else = c.Else.Copy() + return &c +} + +func (n *IfStmt) Left() Node { return n.Cond } +func (n *IfStmt) SetLeft(x Node) { n.Cond = x } +func (n *IfStmt) Body() Nodes { return n.body } +func (n *IfStmt) PtrBody() *Nodes { return &n.body } +func (n *IfStmt) SetBody(x Nodes) { n.body = x } +func (n *IfStmt) Rlist() Nodes { return n.Else } +func (n *IfStmt) PtrRlist() *Nodes { return &n.Else } +func (n *IfStmt) SetRlist(x Nodes) { n.Else = x } +func (n *IfStmt) Likely() bool { return n.likely } +func (n *IfStmt) SetLikely(x bool) { n.likely = x } // An InlineMarkStmt is a marker placed just before an inlined body. type InlineMarkStmt struct { @@ -379,9 +434,14 @@ func NewInlineMarkStmt(pos src.XPos, index int64) *InlineMarkStmt { func (n *InlineMarkStmt) String() string { return fmt.Sprint(n) } func (n *InlineMarkStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *InlineMarkStmt) rawCopy() Node { c := *n; return &c } -func (n *InlineMarkStmt) Offset() int64 { return n.Index } -func (n *InlineMarkStmt) SetOffset(x int64) { n.Index = x } +func (n *InlineMarkStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *InlineMarkStmt) Offset() int64 { return n.Index } +func (n *InlineMarkStmt) SetOffset(x int64) { n.Index = x } // A LabelStmt is a label statement (just the label, not including the statement it labels). type LabelStmt struct { @@ -398,9 +458,14 @@ func NewLabelStmt(pos src.XPos, label *types.Sym) *LabelStmt { func (n *LabelStmt) String() string { return fmt.Sprint(n) } func (n *LabelStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *LabelStmt) rawCopy() Node { c := *n; return &c } -func (n *LabelStmt) Sym() *types.Sym { return n.Label } -func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x } +func (n *LabelStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} + +func (n *LabelStmt) Sym() *types.Sym { return n.Label } +func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x } // A RangeStmt is a range loop: for Vars = range X { Stmts } // Op can be OFOR or OFORUNTIL (!Cond). @@ -426,23 +491,30 @@ func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt { func (n *RangeStmt) String() string { return fmt.Sprint(n) } func (n *RangeStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *RangeStmt) rawCopy() Node { c := *n; return &c } -func (n *RangeStmt) Sym() *types.Sym { return n.Label } -func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x } -func (n *RangeStmt) Right() Node { return n.X } -func (n *RangeStmt) SetRight(x Node) { n.X = x } -func (n *RangeStmt) Body() Nodes { return n.body } -func (n *RangeStmt) PtrBody() *Nodes { return &n.body } -func (n *RangeStmt) SetBody(x Nodes) { n.body = x } -func (n *RangeStmt) List() Nodes { return n.Vars } -func (n *RangeStmt) PtrList() *Nodes { return &n.Vars } -func (n *RangeStmt) SetList(x Nodes) { n.Vars = x } -func (n *RangeStmt) HasBreak() bool { return n.hasBreak } -func (n *RangeStmt) SetHasBreak(b bool) { n.hasBreak = b } -func (n *RangeStmt) Colas() bool { return n.Def } -func (n *RangeStmt) SetColas(b bool) { n.Def = b } -func (n *RangeStmt) Type() *types.Type { return n.typ } -func (n *RangeStmt) SetType(x *types.Type) { n.typ = x } +func (n *RangeStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Vars = c.Vars.Copy() + c.body = c.body.Copy() + return &c +} + +func (n *RangeStmt) Sym() *types.Sym { return n.Label } +func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x } +func (n *RangeStmt) Right() Node { return n.X } +func (n *RangeStmt) SetRight(x Node) { n.X = x } +func (n *RangeStmt) Body() Nodes { return n.body } +func (n *RangeStmt) PtrBody() *Nodes { return &n.body } +func (n *RangeStmt) SetBody(x Nodes) { n.body = x } +func (n *RangeStmt) List() Nodes { return n.Vars } +func (n *RangeStmt) PtrList() *Nodes { return &n.Vars } +func (n *RangeStmt) SetList(x Nodes) { n.Vars = x } +func (n *RangeStmt) HasBreak() bool { return n.hasBreak } +func (n *RangeStmt) SetHasBreak(b bool) { n.hasBreak = b } +func (n *RangeStmt) Colas() bool { return n.Def } +func (n *RangeStmt) SetColas(b bool) { n.Def = b } +func (n *RangeStmt) Type() *types.Type { return n.typ } +func (n *RangeStmt) SetType(x *types.Type) { n.typ = x } // A ReturnStmt is a return statement. type ReturnStmt struct { @@ -462,13 +534,19 @@ func NewReturnStmt(pos src.XPos, results []Node) *ReturnStmt { func (n *ReturnStmt) String() string { return fmt.Sprint(n) } func (n *ReturnStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ReturnStmt) rawCopy() Node { c := *n; return &c } -func (n *ReturnStmt) Orig() Node { return n.orig } -func (n *ReturnStmt) SetOrig(x Node) { n.orig = x } -func (n *ReturnStmt) List() Nodes { return n.Results } -func (n *ReturnStmt) PtrList() *Nodes { return &n.Results } -func (n *ReturnStmt) SetList(x Nodes) { n.Results = x } -func (n *ReturnStmt) IsDDD() bool { return false } // typecheckargs asks +func (n *ReturnStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Results = c.Results.Copy() + return &c +} + +func (n *ReturnStmt) Orig() Node { return n.orig } +func (n *ReturnStmt) SetOrig(x Node) { n.orig = x } +func (n *ReturnStmt) List() Nodes { return n.Results } +func (n *ReturnStmt) PtrList() *Nodes { return &n.Results } +func (n *ReturnStmt) SetList(x Nodes) { n.Results = x } +func (n *ReturnStmt) IsDDD() bool { return false } // typecheckargs asks // A SelectStmt is a block: { Cases }. type SelectStmt struct { @@ -491,17 +569,24 @@ func NewSelectStmt(pos src.XPos, cases []Node) *SelectStmt { func (n *SelectStmt) String() string { return fmt.Sprint(n) } func (n *SelectStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SelectStmt) rawCopy() Node { c := *n; return &c } -func (n *SelectStmt) List() Nodes { return n.Cases } -func (n *SelectStmt) PtrList() *Nodes { return &n.Cases } -func (n *SelectStmt) SetList(x Nodes) { n.Cases = x } -func (n *SelectStmt) Sym() *types.Sym { return n.Label } -func (n *SelectStmt) SetSym(x *types.Sym) { n.Label = x } -func (n *SelectStmt) HasBreak() bool { return n.hasBreak } -func (n *SelectStmt) SetHasBreak(x bool) { n.hasBreak = x } -func (n *SelectStmt) Body() Nodes { return n.Compiled } -func (n *SelectStmt) PtrBody() *Nodes { return &n.Compiled } -func (n *SelectStmt) SetBody(x Nodes) { n.Compiled = x } +func (n *SelectStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Cases = c.Cases.Copy() + c.Compiled = c.Compiled.Copy() + return &c +} + +func (n *SelectStmt) List() Nodes { return n.Cases } +func (n *SelectStmt) PtrList() *Nodes { return &n.Cases } +func (n *SelectStmt) SetList(x Nodes) { n.Cases = x } +func (n *SelectStmt) Sym() *types.Sym { return n.Label } +func (n *SelectStmt) SetSym(x *types.Sym) { n.Label = x } +func (n *SelectStmt) HasBreak() bool { return n.hasBreak } +func (n *SelectStmt) SetHasBreak(x bool) { n.hasBreak = x } +func (n *SelectStmt) Body() Nodes { return n.Compiled } +func (n *SelectStmt) PtrBody() *Nodes { return &n.Compiled } +func (n *SelectStmt) SetBody(x Nodes) { n.Compiled = x } // A SendStmt is a send statement: X <- Y. type SendStmt struct { @@ -519,7 +604,11 @@ func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt { func (n *SendStmt) String() string { return fmt.Sprint(n) } func (n *SendStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SendStmt) rawCopy() Node { c := *n; return &c } +func (n *SendStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} func (n *SendStmt) Left() Node { return n.Chan } func (n *SendStmt) SetLeft(x Node) { n.Chan = x } @@ -548,19 +637,26 @@ func NewSwitchStmt(pos src.XPos, tag Node, cases []Node) *SwitchStmt { func (n *SwitchStmt) String() string { return fmt.Sprint(n) } func (n *SwitchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SwitchStmt) rawCopy() Node { c := *n; return &c } -func (n *SwitchStmt) Left() Node { return n.Tag } -func (n *SwitchStmt) SetLeft(x Node) { n.Tag = x } -func (n *SwitchStmt) List() Nodes { return n.Cases } -func (n *SwitchStmt) PtrList() *Nodes { return &n.Cases } -func (n *SwitchStmt) SetList(x Nodes) { n.Cases = x } -func (n *SwitchStmt) Body() Nodes { return n.Compiled } -func (n *SwitchStmt) PtrBody() *Nodes { return &n.Compiled } -func (n *SwitchStmt) SetBody(x Nodes) { n.Compiled = x } -func (n *SwitchStmt) Sym() *types.Sym { return n.Label } -func (n *SwitchStmt) SetSym(x *types.Sym) { n.Label = x } -func (n *SwitchStmt) HasBreak() bool { return n.hasBreak } -func (n *SwitchStmt) SetHasBreak(x bool) { n.hasBreak = x } +func (n *SwitchStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Cases = c.Cases.Copy() + c.Compiled = c.Compiled.Copy() + return &c +} + +func (n *SwitchStmt) Left() Node { return n.Tag } +func (n *SwitchStmt) SetLeft(x Node) { n.Tag = x } +func (n *SwitchStmt) List() Nodes { return n.Cases } +func (n *SwitchStmt) PtrList() *Nodes { return &n.Cases } +func (n *SwitchStmt) SetList(x Nodes) { n.Cases = x } +func (n *SwitchStmt) Body() Nodes { return n.Compiled } +func (n *SwitchStmt) PtrBody() *Nodes { return &n.Compiled } +func (n *SwitchStmt) SetBody(x Nodes) { n.Compiled = x } +func (n *SwitchStmt) Sym() *types.Sym { return n.Label } +func (n *SwitchStmt) SetSym(x *types.Sym) { n.Label = x } +func (n *SwitchStmt) HasBreak() bool { return n.hasBreak } +func (n *SwitchStmt) SetHasBreak(x bool) { n.hasBreak = x } // A TypeSwitchGuard is the [Name :=] X.(type) in a type switch. type TypeSwitchGuard struct { @@ -581,7 +677,7 @@ func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard { func (n *TypeSwitchGuard) String() string { return fmt.Sprint(n) } func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *TypeSwitchGuard) rawCopy() Node { c := *n; return &c } +func (n *TypeSwitchGuard) copy() Node { c := *n; return &c } func (n *TypeSwitchGuard) Left() Node { if n.name == nil { diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index d2f5bb9239..a8af99034d 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -74,7 +74,7 @@ func NewChanType(pos src.XPos, elem Node, dir types.ChanDir) *ChanType { func (n *ChanType) String() string { return fmt.Sprint(n) } func (n *ChanType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ChanType) rawCopy() Node { c := *n; return &c } +func (n *ChanType) copy() Node { c := *n; return &c } func (n *ChanType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -104,7 +104,7 @@ func NewMapType(pos src.XPos, key, elem Node) *MapType { func (n *MapType) String() string { return fmt.Sprint(n) } func (n *MapType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *MapType) rawCopy() Node { c := *n; return &c } +func (n *MapType) copy() Node { c := *n; return &c } func (n *MapType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Key = nil @@ -134,7 +134,12 @@ func NewStructType(pos src.XPos, fields []*Field) *StructType { func (n *StructType) String() string { return fmt.Sprint(n) } func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *StructType) rawCopy() Node { c := *n; return &c } +func (n *StructType) copy() Node { + c := *n + c.Fields = copyFields(c.Fields) + return &c +} + func (n *StructType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Fields = nil @@ -171,7 +176,12 @@ func NewInterfaceType(pos src.XPos, methods []*Field) *InterfaceType { func (n *InterfaceType) String() string { return fmt.Sprint(n) } func (n *InterfaceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *InterfaceType) rawCopy() Node { c := *n; return &c } +func (n *InterfaceType) copy() Node { + c := *n + c.Methods = copyFields(c.Methods) + return &c +} + func (n *InterfaceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Methods = nil @@ -202,7 +212,15 @@ func NewFuncType(pos src.XPos, rcvr *Field, args, results []*Field) *FuncType { func (n *FuncType) String() string { return fmt.Sprint(n) } func (n *FuncType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *FuncType) rawCopy() Node { c := *n; return &c } +func (n *FuncType) copy() Node { + c := *n + if c.Recv != nil { + c.Recv = c.Recv.copy() + } + c.Params = copyFields(c.Params) + c.Results = copyFields(c.Results) + return &c +} func (n *FuncType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) @@ -252,6 +270,20 @@ func (f *Field) String() string { return typ } +func (f *Field) copy() *Field { + c := *f + return &c +} + +func copyFields(list []*Field) []*Field { + out := make([]*Field, len(list)) + copy(out, list) + for i, f := range out { + out[i] = f.copy() + } + return out +} + func (f *Field) deepCopy(pos src.XPos) *Field { if f == nil { return nil @@ -289,7 +321,7 @@ func NewSliceType(pos src.XPos, elem Node) *SliceType { func (n *SliceType) String() string { return fmt.Sprint(n) } func (n *SliceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SliceType) rawCopy() Node { c := *n; return &c } +func (n *SliceType) copy() Node { c := *n; return &c } func (n *SliceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -320,7 +352,7 @@ func NewArrayType(pos src.XPos, size Node, elem Node) *ArrayType { func (n *ArrayType) String() string { return fmt.Sprint(n) } func (n *ArrayType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ArrayType) rawCopy() Node { c := *n; return &c } +func (n *ArrayType) copy() Node { c := *n; return &c } func (n *ArrayType) DeepCopy(pos src.XPos) Node { if n.op == OTYPE { @@ -351,7 +383,7 @@ func newTypeNode(pos src.XPos, typ *types.Type) *typeNode { func (n *typeNode) String() string { return fmt.Sprint(n) } func (n *typeNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *typeNode) rawCopy() Node { c := *n; return &c } +func (n *typeNode) copy() Node { c := *n; return &c } func (n *typeNode) Type() *types.Type { return n.typ } func (n *typeNode) Sym() *types.Sym { return n.typ.Sym() } func (n *typeNode) CanBeNtype() {} From 4725c3ffd1b8baf87204936e59bf00c96e3bf4a0 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 21:02:19 -0500 Subject: [PATCH 138/212] [dev.regabi] cmd/compile: implement doChildren for nodes Put each node in charge of its DoChildren implementation. This removes a generic use of Left, Right, and so on in func DoChildren, heading toward removing those even from being used in package ir. Passes buildall w/ toolstash -cmp. Change-Id: Ibdf56f36801217cf24549e063da0078c1820a56b Reviewed-on: https://go-review.googlesource.com/c/go/+/275375 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/copy.go | 6 +- src/cmd/compile/internal/ir/expr.go | 171 ++++++++++++++++++++++++++- src/cmd/compile/internal/ir/func.go | 22 ++-- src/cmd/compile/internal/ir/name.go | 44 +++---- src/cmd/compile/internal/ir/node.go | 2 + src/cmd/compile/internal/ir/stmt.go | 137 ++++++++++++++++++++- src/cmd/compile/internal/ir/type.go | 74 +++++++++++- src/cmd/compile/internal/ir/visit.go | 30 +---- 8 files changed, 419 insertions(+), 67 deletions(-) diff --git a/src/cmd/compile/internal/ir/copy.go b/src/cmd/compile/internal/ir/copy.go index 8d174d6e53..86e78cfc33 100644 --- a/src/cmd/compile/internal/ir/copy.go +++ b/src/cmd/compile/internal/ir/copy.go @@ -65,9 +65,9 @@ func Copy(n Node) Node { } func copyList(x Nodes) Nodes { - out := make([]Node, x.Len()) - copy(out, x.Slice()) - return AsNodes(out) + c := make([]Node, x.Len()) + copy(c, x.Slice()) + return AsNodes(c) } // A Node can implement DeepCopyNode to provide a custom implementation diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 7431a56d94..9e5dfaf0f2 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -12,6 +12,20 @@ import ( "go/constant" ) +func maybeDo(x Node, err error, do func(Node) error) error { + if x != nil && err == nil { + err = do(x) + } + return err +} + +func maybeDoList(x Nodes, err error, do func(Node) error) error { + if err == nil { + err = DoList(x, do) + } + return err +} + // A miniStmt is a miniNode with extra fields common to expressions. // TODO(rsc): Once we are sure about the contents, compact the bools // into a bit field and leave extra bits available for implementations @@ -82,6 +96,12 @@ func (n *AddStringExpr) copy() Node { c.list = c.list.Copy() return &c } +func (n *AddStringExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.list, err, do) + return err +} func (n *AddStringExpr) List() Nodes { return n.list } func (n *AddStringExpr) PtrList() *Nodes { return &n.list } @@ -109,6 +129,12 @@ func (n *AddrExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *AddrExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} func (n *AddrExpr) Left() Node { return n.X } func (n *AddrExpr) SetLeft(x Node) { n.X = x } @@ -146,6 +172,13 @@ func (n *BinaryExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *BinaryExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Y, err, do) + return err +} func (n *BinaryExpr) Left() Node { return n.X } func (n *BinaryExpr) SetLeft(x Node) { n.X = x } @@ -207,6 +240,15 @@ func (n *CallExpr) copy() Node { c.body = c.body.Copy() return &c } +func (n *CallExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDoList(n.Args, err, do) + err = maybeDoList(n.Rargs, err, do) + err = maybeDoList(n.body, err, do) + return err +} func (n *CallExpr) Orig() Node { return n.orig } func (n *CallExpr) SetOrig(x Node) { n.orig = x } @@ -260,6 +302,12 @@ func (n *CallPartExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *CallPartExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} func (n *CallPartExpr) Func() *Func { return n.fn } func (n *CallPartExpr) Left() Node { return n.X } @@ -286,6 +334,11 @@ func (n *ClosureExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *ClosureExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} func (n *ClosureExpr) Func() *Func { return n.fn } @@ -312,6 +365,11 @@ func (n *ClosureRead) copy() Node { func (n *ClosureRead) Type() *types.Type { return n.typ } func (n *ClosureRead) Offset() int64 { return n.offset } +func (n *ClosureRead) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} // A CompLitExpr is a composite literal Type{Vals}. // Before type-checking, the type is Ntype. @@ -339,6 +397,13 @@ func (n *CompLitExpr) copy() Node { c.list = c.list.Copy() return &c } +func (n *CompLitExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Ntype, err, do) + err = maybeDoList(n.list, err, do) + return err +} func (n *CompLitExpr) Orig() Node { return n.orig } func (n *CompLitExpr) SetOrig(x Node) { n.orig = x } @@ -373,9 +438,10 @@ func NewConstExpr(val constant.Value, orig Node) Node { return n } -func (n *ConstExpr) String() string { return fmt.Sprint(n) } -func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ConstExpr) copy() Node { c := *n; return &c } +func (n *ConstExpr) String() string { return fmt.Sprint(n) } +func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ConstExpr) copy() Node { c := *n; return &c } +func (n *ConstExpr) doChildren(do func(Node) error) error { return nil } func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() } func (n *ConstExpr) Orig() Node { return n.orig } @@ -406,6 +472,12 @@ func (n *ConvExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *ConvExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} func (n *ConvExpr) rawCopy() Node { c := *n; return &c } func (n *ConvExpr) Left() Node { return n.X } @@ -442,6 +514,13 @@ func (n *IndexExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *IndexExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Index, err, do) + return err +} func (n *IndexExpr) Left() Node { return n.X } func (n *IndexExpr) SetLeft(x Node) { n.X = x } @@ -484,6 +563,13 @@ func (n *KeyExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *KeyExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Key, err, do) + err = maybeDo(n.Value, err, do) + return err +} func (n *KeyExpr) Left() Node { return n.Key } func (n *KeyExpr) SetLeft(x Node) { n.Key = x } @@ -528,6 +614,13 @@ func (n *InlinedCallExpr) copy() Node { c.ReturnVars = c.ReturnVars.Copy() return &c } +func (n *InlinedCallExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.body, err, do) + err = maybeDoList(n.ReturnVars, err, do) + return err +} func (n *InlinedCallExpr) Body() Nodes { return n.body } func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.body } @@ -559,6 +652,13 @@ func (n *MakeExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *MakeExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Len, err, do) + err = maybeDo(n.Cap, err, do) + return err +} func (n *MakeExpr) Left() Node { return n.Len } func (n *MakeExpr) SetLeft(x Node) { n.Len = x } @@ -574,7 +674,7 @@ func (n *MakeExpr) SetOp(op Op) { } } -// A MethodExpr is a method expression X.M (where X is an expression, not a type). +// A MethodExpr is a method value X.M (where X is an expression, not a type). type MethodExpr struct { miniExpr X Node @@ -600,6 +700,13 @@ func (n *MethodExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *MethodExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.M, err, do) + return err +} func (n *MethodExpr) Left() Node { return n.X } func (n *MethodExpr) SetLeft(x Node) { n.X = x } @@ -633,6 +740,11 @@ func (n *NilExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *NilExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} func (n *NilExpr) Sym() *types.Sym { return n.sym } func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x } @@ -658,6 +770,12 @@ func (n *ParenExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *ParenExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} func (n *ParenExpr) Left() Node { return n.X } func (n *ParenExpr) SetLeft(x Node) { n.X = x } @@ -693,6 +811,11 @@ func (n *ResultExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *ResultExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} func (n *ResultExpr) Offset() int64 { return n.offset } func (n *ResultExpr) SetOffset(x int64) { n.offset = x } @@ -730,6 +853,12 @@ func (n *SelectorExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *SelectorExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} func (n *SelectorExpr) Left() Node { return n.X } func (n *SelectorExpr) SetLeft(x Node) { n.X = x } @@ -764,6 +893,13 @@ func (n *SliceExpr) copy() Node { c.list = c.list.Copy() return &c } +func (n *SliceExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDoList(n.list, err, do) + return err +} func (n *SliceExpr) Left() Node { return n.X } func (n *SliceExpr) SetLeft(x Node) { n.X = x } @@ -871,6 +1007,13 @@ func (n *SliceHeaderExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *SliceHeaderExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Ptr, err, do) + err = maybeDoList(n.lenCap, err, do) + return err +} func (n *SliceHeaderExpr) Left() Node { return n.Ptr } func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x } @@ -899,6 +1042,12 @@ func (n *StarExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *StarExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} func (n *StarExpr) Left() Node { return n.X } func (n *StarExpr) SetLeft(x Node) { n.X = x } @@ -949,6 +1098,14 @@ func (n *TypeAssertExpr) copy() Node { c.Itab = c.Itab.Copy() return &c } +func (n *TypeAssertExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Ntype, err, do) + err = maybeDoList(n.Itab, err, do) + return err +} func (n *TypeAssertExpr) Left() Node { return n.X } func (n *TypeAssertExpr) SetLeft(x Node) { n.X = x } @@ -988,6 +1145,12 @@ func (n *UnaryExpr) copy() Node { c.init = c.init.Copy() return &c } +func (n *UnaryExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} func (n *UnaryExpr) Left() Node { return n.X } func (n *UnaryExpr) SetLeft(x Node) { n.X = x } diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index ae803cd6a5..342b7a91e7 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -118,14 +118,20 @@ func NewFunc(pos src.XPos) *Func { func (f *Func) String() string { return fmt.Sprint(f) } func (f *Func) Format(s fmt.State, verb rune) { FmtNode(f, s, verb) } func (f *Func) copy() Node { panic(f.no("copy")) } -func (f *Func) Func() *Func { return f } -func (f *Func) Body() Nodes { return f.body } -func (f *Func) PtrBody() *Nodes { return &f.body } -func (f *Func) SetBody(x Nodes) { f.body = x } -func (f *Func) Type() *types.Type { return f.typ } -func (f *Func) SetType(x *types.Type) { f.typ = x } -func (f *Func) Iota() int64 { return f.iota } -func (f *Func) SetIota(x int64) { f.iota = x } +func (f *Func) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(f.body, err, do) + return err +} + +func (f *Func) Func() *Func { return f } +func (f *Func) Body() Nodes { return f.body } +func (f *Func) PtrBody() *Nodes { return &f.body } +func (f *Func) SetBody(x Nodes) { f.body = x } +func (f *Func) Type() *types.Type { return f.typ } +func (f *Func) SetType(x *types.Type) { f.typ = x } +func (f *Func) Iota() int64 { return f.iota } +func (f *Func) SetIota(x int64) { f.iota = x } func (f *Func) Sym() *types.Sym { if f.Nname != nil { diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index dc8c58e4f4..2ff1fbc683 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -149,22 +149,24 @@ func newNameAt(pos src.XPos, op Op, sym *types.Sym) *Name { return n } -func (n *Name) String() string { return fmt.Sprint(n) } -func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *Name) copy() Node { c := *n; return &c } -func (n *Name) Name() *Name { return n } -func (n *Name) Sym() *types.Sym { return n.sym } -func (n *Name) SetSym(x *types.Sym) { n.sym = x } -func (n *Name) SubOp() Op { return n.subOp } -func (n *Name) SetSubOp(x Op) { n.subOp = x } -func (n *Name) Class() Class { return n.class } -func (n *Name) SetClass(x Class) { n.class = x } -func (n *Name) Func() *Func { return n.fn } -func (n *Name) SetFunc(x *Func) { n.fn = x } -func (n *Name) Offset() int64 { return n.offset } -func (n *Name) SetOffset(x int64) { n.offset = x } -func (n *Name) Iota() int64 { return n.offset } -func (n *Name) SetIota(x int64) { n.offset = x } +func (n *Name) String() string { return fmt.Sprint(n) } +func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *Name) copy() Node { c := *n; return &c } +func (n *Name) doChildren(do func(Node) error) error { return nil } + +func (n *Name) Name() *Name { return n } +func (n *Name) Sym() *types.Sym { return n.sym } +func (n *Name) SetSym(x *types.Sym) { n.sym = x } +func (n *Name) SubOp() Op { return n.subOp } +func (n *Name) SetSubOp(x Op) { n.subOp = x } +func (n *Name) Class() Class { return n.class } +func (n *Name) SetClass(x Class) { n.class = x } +func (n *Name) Func() *Func { return n.fn } +func (n *Name) SetFunc(x *Func) { n.fn = x } +func (n *Name) Offset() int64 { return n.offset } +func (n *Name) SetOffset(x int64) { n.offset = x } +func (n *Name) Iota() int64 { return n.offset } +func (n *Name) SetIota(x int64) { n.offset = x } func (*Name) CanBeNtype() {} @@ -321,10 +323,12 @@ type PkgName struct { Used bool } -func (p *PkgName) String() string { return fmt.Sprint(p) } -func (p *PkgName) Format(s fmt.State, verb rune) { FmtNode(p, s, verb) } -func (p *PkgName) copy() Node { c := *p; return &c } -func (p *PkgName) Sym() *types.Sym { return p.sym } +func (p *PkgName) String() string { return fmt.Sprint(p) } +func (p *PkgName) Format(s fmt.State, verb rune) { FmtNode(p, s, verb) } +func (p *PkgName) copy() Node { c := *p; return &c } +func (p *PkgName) doChildren(do func(Node) error) error { return nil } + +func (p *PkgName) Sym() *types.Sym { return p.sym } func (*PkgName) CanBeNtype() {} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 705eb9e47e..02ab87846f 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -30,6 +30,8 @@ type Node interface { // For making copies. For Copy and SepCopy. copy() Node + doChildren(func(Node) error) error + // Abstract graph structure, for generic traversals. Op() Op SetOp(x Op) diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 5af6a62cf2..b940c5f59d 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -11,7 +11,6 @@ import ( ) // A Decl is a declaration of a const, type, or var. (A declared func is a Func.) -// (This is not technically a statement but it's not worth its own file.) type Decl struct { miniNode X Node // the thing being declared @@ -32,8 +31,14 @@ func NewDecl(pos src.XPos, op Op, x Node) *Decl { func (n *Decl) String() string { return fmt.Sprint(n) } func (n *Decl) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *Decl) copy() Node { c := *n; return &c } -func (n *Decl) Left() Node { return n.X } -func (n *Decl) SetLeft(x Node) { n.X = x } +func (n *Decl) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.X, err, do) + return err +} + +func (n *Decl) Left() Node { return n.X } +func (n *Decl) SetLeft(x Node) { n.X = x } // A miniStmt is a miniNode with extra fields common to statements. type miniStmt struct { @@ -77,6 +82,13 @@ func (n *AssignListStmt) copy() Node { c.Rhs = c.Rhs.Copy() return &c } +func (n *AssignListStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Lhs, err, do) + err = maybeDoList(n.Rhs, err, do) + return err +} func (n *AssignListStmt) List() Nodes { return n.Lhs } func (n *AssignListStmt) PtrList() *Nodes { return &n.Lhs } @@ -123,6 +135,13 @@ func (n *AssignStmt) copy() Node { c.init = c.init.Copy() return &c } +func (n *AssignStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Y, err, do) + return err +} func (n *AssignStmt) Left() Node { return n.X } func (n *AssignStmt) SetLeft(x Node) { n.X = x } @@ -166,6 +185,13 @@ func (n *AssignOpStmt) copy() Node { c.init = c.init.Copy() return &c } +func (n *AssignOpStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Y, err, do) + return err +} func (n *AssignOpStmt) Left() Node { return n.X } func (n *AssignOpStmt) SetLeft(x Node) { n.X = x } @@ -200,6 +226,12 @@ func (n *BlockStmt) copy() Node { c.list = c.list.Copy() return &c } +func (n *BlockStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.list, err, do) + return err +} func (n *BlockStmt) List() Nodes { return n.list } func (n *BlockStmt) PtrList() *Nodes { return &n.list } @@ -234,6 +266,11 @@ func (n *BranchStmt) copy() Node { c.init = c.init.Copy() return &c } +func (n *BranchStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} func (n *BranchStmt) Sym() *types.Sym { return n.Label } func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym } @@ -266,6 +303,15 @@ func (n *CaseStmt) copy() Node { c.body = c.body.Copy() return &c } +func (n *CaseStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Vars, err, do) + err = maybeDoList(n.list, err, do) + err = maybeDo(n.Comm, err, do) + err = maybeDoList(n.body, err, do) + return err +} func (n *CaseStmt) List() Nodes { return n.list } func (n *CaseStmt) PtrList() *Nodes { return &n.list } @@ -299,6 +345,12 @@ func (n *DeferStmt) copy() Node { c.init = c.init.Copy() return &c } +func (n *DeferStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Call, err, do) + return err +} func (n *DeferStmt) Left() Node { return n.Call } func (n *DeferStmt) SetLeft(x Node) { n.Call = x } @@ -309,8 +361,8 @@ type ForStmt struct { miniStmt Label *types.Sym Cond Node - Post Node Late Nodes + Post Node body Nodes hasBreak bool } @@ -333,6 +385,15 @@ func (n *ForStmt) copy() Node { c.body = c.body.Copy() return &c } +func (n *ForStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Cond, err, do) + err = maybeDoList(n.Late, err, do) + err = maybeDo(n.Post, err, do) + err = maybeDoList(n.body, err, do) + return err +} func (n *ForStmt) Sym() *types.Sym { return n.Label } func (n *ForStmt) SetSym(x *types.Sym) { n.Label = x } @@ -376,6 +437,12 @@ func (n *GoStmt) copy() Node { c.init = c.init.Copy() return &c } +func (n *GoStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Call, err, do) + return err +} func (n *GoStmt) Left() Node { return n.Call } func (n *GoStmt) SetLeft(x Node) { n.Call = x } @@ -407,6 +474,14 @@ func (n *IfStmt) copy() Node { c.Else = c.Else.Copy() return &c } +func (n *IfStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Cond, err, do) + err = maybeDoList(n.body, err, do) + err = maybeDoList(n.Else, err, do) + return err +} func (n *IfStmt) Left() Node { return n.Cond } func (n *IfStmt) SetLeft(x Node) { n.Cond = x } @@ -439,6 +514,11 @@ func (n *InlineMarkStmt) copy() Node { c.init = c.init.Copy() return &c } +func (n *InlineMarkStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} func (n *InlineMarkStmt) Offset() int64 { return n.Index } func (n *InlineMarkStmt) SetOffset(x int64) { n.Index = x } @@ -463,6 +543,11 @@ func (n *LabelStmt) copy() Node { c.init = c.init.Copy() return &c } +func (n *LabelStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} func (n *LabelStmt) Sym() *types.Sym { return n.Label } func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x } @@ -498,6 +583,14 @@ func (n *RangeStmt) copy() Node { c.body = c.body.Copy() return &c } +func (n *RangeStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Vars, err, do) + err = maybeDo(n.X, err, do) + err = maybeDoList(n.body, err, do) + return err +} func (n *RangeStmt) Sym() *types.Sym { return n.Label } func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x } @@ -540,6 +633,12 @@ func (n *ReturnStmt) copy() Node { c.Results = c.Results.Copy() return &c } +func (n *ReturnStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Results, err, do) + return err +} func (n *ReturnStmt) Orig() Node { return n.orig } func (n *ReturnStmt) SetOrig(x Node) { n.orig = x } @@ -576,6 +675,13 @@ func (n *SelectStmt) copy() Node { c.Compiled = c.Compiled.Copy() return &c } +func (n *SelectStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Cases, err, do) + err = maybeDoList(n.Compiled, err, do) + return err +} func (n *SelectStmt) List() Nodes { return n.Cases } func (n *SelectStmt) PtrList() *Nodes { return &n.Cases } @@ -609,6 +715,13 @@ func (n *SendStmt) copy() Node { c.init = c.init.Copy() return &c } +func (n *SendStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Chan, err, do) + err = maybeDo(n.Value, err, do) + return err +} func (n *SendStmt) Left() Node { return n.Chan } func (n *SendStmt) SetLeft(x Node) { n.Chan = x } @@ -644,6 +757,14 @@ func (n *SwitchStmt) copy() Node { c.Compiled = c.Compiled.Copy() return &c } +func (n *SwitchStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Tag, err, do) + err = maybeDoList(n.Cases, err, do) + err = maybeDoList(n.Compiled, err, do) + return err +} func (n *SwitchStmt) Left() Node { return n.Tag } func (n *SwitchStmt) SetLeft(x Node) { n.Tag = x } @@ -678,6 +799,14 @@ func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard { func (n *TypeSwitchGuard) String() string { return fmt.Sprint(n) } func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *TypeSwitchGuard) copy() Node { c := *n; return &c } +func (n *TypeSwitchGuard) doChildren(do func(Node) error) error { + var err error + if n.name != nil { + err = maybeDo(n.name, err, do) + } + err = maybeDo(n.X, err, do) + return err +} func (n *TypeSwitchGuard) Left() Node { if n.name == nil { diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index a8af99034d..2723c00044 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -75,6 +75,11 @@ func NewChanType(pos src.XPos, elem Node, dir types.ChanDir) *ChanType { func (n *ChanType) String() string { return fmt.Sprint(n) } func (n *ChanType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ChanType) copy() Node { c := *n; return &c } +func (n *ChanType) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.Elem, err, do) + return err +} func (n *ChanType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -105,6 +110,12 @@ func NewMapType(pos src.XPos, key, elem Node) *MapType { func (n *MapType) String() string { return fmt.Sprint(n) } func (n *MapType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *MapType) copy() Node { c := *n; return &c } +func (n *MapType) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.Key, err, do) + err = maybeDo(n.Elem, err, do) + return err +} func (n *MapType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Key = nil @@ -139,6 +150,11 @@ func (n *StructType) copy() Node { c.Fields = copyFields(c.Fields) return &c } +func (n *StructType) doChildren(do func(Node) error) error { + var err error + err = maybeDoFields(n.Fields, err, do) + return err +} func (n *StructType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) @@ -181,6 +197,11 @@ func (n *InterfaceType) copy() Node { c.Methods = copyFields(c.Methods) return &c } +func (n *InterfaceType) doChildren(do func(Node) error) error { + var err error + err = maybeDoFields(n.Methods, err, do) + return err +} func (n *InterfaceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) @@ -221,6 +242,13 @@ func (n *FuncType) copy() Node { c.Results = copyFields(c.Results) return &c } +func (n *FuncType) doChildren(do func(Node) error) error { + var err error + err = maybeDoField(n.Recv, err, do) + err = maybeDoFields(n.Params, err, do) + err = maybeDoFields(n.Results, err, do) + return err +} func (n *FuncType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) @@ -284,6 +312,31 @@ func copyFields(list []*Field) []*Field { return out } +func maybeDoField(f *Field, err error, do func(Node) error) error { + if f != nil { + if err == nil && f.Decl != nil { + err = do(f.Decl) + } + if err == nil && f.Ntype != nil { + err = do(f.Ntype) + } + } + return err +} + +func maybeDoFields(list []*Field, err error, do func(Node) error) error { + if err != nil { + return err + } + for _, f := range list { + err = maybeDoField(f, err, do) + if err != nil { + return err + } + } + return err +} + func (f *Field) deepCopy(pos src.XPos) *Field { if f == nil { return nil @@ -322,6 +375,11 @@ func NewSliceType(pos src.XPos, elem Node) *SliceType { func (n *SliceType) String() string { return fmt.Sprint(n) } func (n *SliceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SliceType) copy() Node { c := *n; return &c } +func (n *SliceType) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.Elem, err, do) + return err +} func (n *SliceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -353,6 +411,12 @@ func NewArrayType(pos src.XPos, size Node, elem Node) *ArrayType { func (n *ArrayType) String() string { return fmt.Sprint(n) } func (n *ArrayType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ArrayType) copy() Node { c := *n; return &c } +func (n *ArrayType) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.Len, err, do) + err = maybeDo(n.Elem, err, do) + return err +} func (n *ArrayType) DeepCopy(pos src.XPos) Node { if n.op == OTYPE { @@ -384,9 +448,13 @@ func newTypeNode(pos src.XPos, typ *types.Type) *typeNode { func (n *typeNode) String() string { return fmt.Sprint(n) } func (n *typeNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *typeNode) copy() Node { c := *n; return &c } -func (n *typeNode) Type() *types.Type { return n.typ } -func (n *typeNode) Sym() *types.Sym { return n.typ.Sym() } -func (n *typeNode) CanBeNtype() {} +func (n *typeNode) doChildren(do func(Node) error) error { + return nil +} + +func (n *typeNode) Type() *types.Type { return n.typ } +func (n *typeNode) Sym() *types.Sym { return n.typ.Sym() } +func (n *typeNode) CanBeNtype() {} // TypeNode returns the Node representing the type t. func TypeNode(t *types.Type) Ntype { diff --git a/src/cmd/compile/internal/ir/visit.go b/src/cmd/compile/internal/ir/visit.go index a239fd1532..042257c32a 100644 --- a/src/cmd/compile/internal/ir/visit.go +++ b/src/cmd/compile/internal/ir/visit.go @@ -14,7 +14,9 @@ package ir -import "errors" +import ( + "errors" +) // DoChildren calls do(x) on each of n's non-nil child nodes x. // If any call returns a non-nil error, DoChildren stops and returns that error. @@ -86,7 +88,7 @@ import "errors" // found = v // return stop // } -// return DoChildren(x, do) +// return ir.DoChildren(x, do) // } // do(n) // return found @@ -100,29 +102,7 @@ func DoChildren(n Node, do func(Node) error) error { if n == nil { return nil } - if err := DoList(n.Init(), do); err != nil { - return err - } - if l := n.Left(); l != nil { - if err := do(l); err != nil { - return err - } - } - if r := n.Right(); r != nil { - if err := do(r); err != nil { - return err - } - } - if err := DoList(n.List(), do); err != nil { - return err - } - if err := DoList(n.Body(), do); err != nil { - return err - } - if err := DoList(n.Rlist(), do); err != nil { - return err - } - return nil + return n.doChildren(do) } // DoList calls f on each non-nil node x in the list, in list order. From bb5aa2b664331087d3230732cb0d11c8e87b9e98 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 21:29:23 -0500 Subject: [PATCH 139/212] [dev.regabi] cmd/compile: implement editChildren for nodes Put each node in charge of its EditChildren implementation. This removes the final generic use of Left, SetLeft, Right, SetRight, and so on in package ir. Passes buildall w/ toolstash -cmp. Change-Id: I9821cc20f5b91cc9b44eb1f386cc82f20cd6770c Reviewed-on: https://go-review.googlesource.com/c/go/+/275376 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/expr.go | 110 +++++++++++++++++++++++++++ src/cmd/compile/internal/ir/func.go | 3 + src/cmd/compile/internal/ir/name.go | 2 + src/cmd/compile/internal/ir/node.go | 1 + src/cmd/compile/internal/ir/stmt.go | 91 ++++++++++++++++++++++ src/cmd/compile/internal/ir/type.go | 44 +++++++++++ src/cmd/compile/internal/ir/visit.go | 11 +-- 7 files changed, 252 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 9e5dfaf0f2..312faa8436 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -26,6 +26,13 @@ func maybeDoList(x Nodes, err error, do func(Node) error) error { return err } +func maybeEdit(x Node, edit func(Node) Node) Node { + if x == nil { + return x + } + return edit(x) +} + // A miniStmt is a miniNode with extra fields common to expressions. // TODO(rsc): Once we are sure about the contents, compact the bools // into a bit field and leave extra bits available for implementations @@ -102,6 +109,10 @@ func (n *AddStringExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.list, err, do) return err } +func (n *AddStringExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.list, edit) +} func (n *AddStringExpr) List() Nodes { return n.list } func (n *AddStringExpr) PtrList() *Nodes { return &n.list } @@ -135,6 +146,10 @@ func (n *AddrExpr) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) return err } +func (n *AddrExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} func (n *AddrExpr) Left() Node { return n.X } func (n *AddrExpr) SetLeft(x Node) { n.X = x } @@ -179,6 +194,11 @@ func (n *BinaryExpr) doChildren(do func(Node) error) error { err = maybeDo(n.Y, err, do) return err } +func (n *BinaryExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Y = maybeEdit(n.Y, edit) +} func (n *BinaryExpr) Left() Node { return n.X } func (n *BinaryExpr) SetLeft(x Node) { n.X = x } @@ -249,6 +269,13 @@ func (n *CallExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.body, err, do) return err } +func (n *CallExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + editList(n.Args, edit) + editList(n.Rargs, edit) + editList(n.body, edit) +} func (n *CallExpr) Orig() Node { return n.orig } func (n *CallExpr) SetOrig(x Node) { n.orig = x } @@ -308,6 +335,10 @@ func (n *CallPartExpr) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) return err } +func (n *CallPartExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} func (n *CallPartExpr) Func() *Func { return n.fn } func (n *CallPartExpr) Left() Node { return n.X } @@ -339,6 +370,9 @@ func (n *ClosureExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.init, err, do) return err } +func (n *ClosureExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} func (n *ClosureExpr) Func() *Func { return n.fn } @@ -370,6 +404,9 @@ func (n *ClosureRead) doChildren(do func(Node) error) error { err = maybeDoList(n.init, err, do) return err } +func (n *ClosureRead) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} // A CompLitExpr is a composite literal Type{Vals}. // Before type-checking, the type is Ntype. @@ -404,6 +441,11 @@ func (n *CompLitExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.list, err, do) return err } +func (n *CompLitExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Ntype = toNtype(maybeEdit(n.Ntype, edit)) + editList(n.list, edit) +} func (n *CompLitExpr) Orig() Node { return n.orig } func (n *CompLitExpr) SetOrig(x Node) { n.orig = x } @@ -442,6 +484,7 @@ func (n *ConstExpr) String() string { return fmt.Sprint(n) func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ConstExpr) copy() Node { c := *n; return &c } func (n *ConstExpr) doChildren(do func(Node) error) error { return nil } +func (n *ConstExpr) editChildren(edit func(Node) Node) {} func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() } func (n *ConstExpr) Orig() Node { return n.orig } @@ -478,6 +521,10 @@ func (n *ConvExpr) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) return err } +func (n *ConvExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} func (n *ConvExpr) rawCopy() Node { c := *n; return &c } func (n *ConvExpr) Left() Node { return n.X } @@ -521,6 +568,11 @@ func (n *IndexExpr) doChildren(do func(Node) error) error { err = maybeDo(n.Index, err, do) return err } +func (n *IndexExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Index = maybeEdit(n.Index, edit) +} func (n *IndexExpr) Left() Node { return n.X } func (n *IndexExpr) SetLeft(x Node) { n.X = x } @@ -570,6 +622,11 @@ func (n *KeyExpr) doChildren(do func(Node) error) error { err = maybeDo(n.Value, err, do) return err } +func (n *KeyExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Key = maybeEdit(n.Key, edit) + n.Value = maybeEdit(n.Value, edit) +} func (n *KeyExpr) Left() Node { return n.Key } func (n *KeyExpr) SetLeft(x Node) { n.Key = x } @@ -621,6 +678,11 @@ func (n *InlinedCallExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.ReturnVars, err, do) return err } +func (n *InlinedCallExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.body, edit) + editList(n.ReturnVars, edit) +} func (n *InlinedCallExpr) Body() Nodes { return n.body } func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.body } @@ -659,6 +721,11 @@ func (n *MakeExpr) doChildren(do func(Node) error) error { err = maybeDo(n.Cap, err, do) return err } +func (n *MakeExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Len = maybeEdit(n.Len, edit) + n.Cap = maybeEdit(n.Cap, edit) +} func (n *MakeExpr) Left() Node { return n.Len } func (n *MakeExpr) SetLeft(x Node) { n.Len = x } @@ -707,6 +774,11 @@ func (n *MethodExpr) doChildren(do func(Node) error) error { err = maybeDo(n.M, err, do) return err } +func (n *MethodExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.M = maybeEdit(n.M, edit) +} func (n *MethodExpr) Left() Node { return n.X } func (n *MethodExpr) SetLeft(x Node) { n.X = x } @@ -745,6 +817,9 @@ func (n *NilExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.init, err, do) return err } +func (n *NilExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} func (n *NilExpr) Sym() *types.Sym { return n.sym } func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x } @@ -776,6 +851,10 @@ func (n *ParenExpr) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) return err } +func (n *ParenExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} func (n *ParenExpr) Left() Node { return n.X } func (n *ParenExpr) SetLeft(x Node) { n.X = x } @@ -816,6 +895,9 @@ func (n *ResultExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.init, err, do) return err } +func (n *ResultExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} func (n *ResultExpr) Offset() int64 { return n.offset } func (n *ResultExpr) SetOffset(x int64) { n.offset = x } @@ -859,6 +941,10 @@ func (n *SelectorExpr) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) return err } +func (n *SelectorExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} func (n *SelectorExpr) Left() Node { return n.X } func (n *SelectorExpr) SetLeft(x Node) { n.X = x } @@ -900,6 +986,11 @@ func (n *SliceExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.list, err, do) return err } +func (n *SliceExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + editList(n.list, edit) +} func (n *SliceExpr) Left() Node { return n.X } func (n *SliceExpr) SetLeft(x Node) { n.X = x } @@ -1014,6 +1105,11 @@ func (n *SliceHeaderExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.lenCap, err, do) return err } +func (n *SliceHeaderExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Ptr = maybeEdit(n.Ptr, edit) + editList(n.lenCap, edit) +} func (n *SliceHeaderExpr) Left() Node { return n.Ptr } func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x } @@ -1048,6 +1144,10 @@ func (n *StarExpr) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) return err } +func (n *StarExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} func (n *StarExpr) Left() Node { return n.X } func (n *StarExpr) SetLeft(x Node) { n.X = x } @@ -1106,6 +1206,12 @@ func (n *TypeAssertExpr) doChildren(do func(Node) error) error { err = maybeDoList(n.Itab, err, do) return err } +func (n *TypeAssertExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Ntype = maybeEdit(n.Ntype, edit) + editList(n.Itab, edit) +} func (n *TypeAssertExpr) Left() Node { return n.X } func (n *TypeAssertExpr) SetLeft(x Node) { n.X = x } @@ -1151,6 +1257,10 @@ func (n *UnaryExpr) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) return err } +func (n *UnaryExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} func (n *UnaryExpr) Left() Node { return n.X } func (n *UnaryExpr) SetLeft(x Node) { n.X = x } diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 342b7a91e7..78e98c4d31 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -123,6 +123,9 @@ func (f *Func) doChildren(do func(Node) error) error { err = maybeDoList(f.body, err, do) return err } +func (f *Func) editChildren(edit func(Node) Node) { + editList(f.body, edit) +} func (f *Func) Func() *Func { return f } func (f *Func) Body() Nodes { return f.body } diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 2ff1fbc683..d2c33eab2b 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -153,6 +153,7 @@ func (n *Name) String() string { return fmt.Sprint(n) } func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *Name) copy() Node { c := *n; return &c } func (n *Name) doChildren(do func(Node) error) error { return nil } +func (n *Name) editChildren(edit func(Node) Node) {} func (n *Name) Name() *Name { return n } func (n *Name) Sym() *types.Sym { return n.sym } @@ -327,6 +328,7 @@ func (p *PkgName) String() string { return fmt.Sprint(p) } func (p *PkgName) Format(s fmt.State, verb rune) { FmtNode(p, s, verb) } func (p *PkgName) copy() Node { c := *p; return &c } func (p *PkgName) doChildren(do func(Node) error) error { return nil } +func (p *PkgName) editChildren(edit func(Node) Node) {} func (p *PkgName) Sym() *types.Sym { return p.sym } diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 02ab87846f..f44d22313c 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -31,6 +31,7 @@ type Node interface { copy() Node doChildren(func(Node) error) error + editChildren(func(Node) Node) // Abstract graph structure, for generic traversals. Op() Op diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index b940c5f59d..c859fae55b 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -36,6 +36,9 @@ func (n *Decl) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) return err } +func (n *Decl) editChildren(edit func(Node) Node) { + n.X = maybeEdit(n.X, edit) +} func (n *Decl) Left() Node { return n.X } func (n *Decl) SetLeft(x Node) { n.X = x } @@ -89,6 +92,11 @@ func (n *AssignListStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.Rhs, err, do) return err } +func (n *AssignListStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Lhs, edit) + editList(n.Rhs, edit) +} func (n *AssignListStmt) List() Nodes { return n.Lhs } func (n *AssignListStmt) PtrList() *Nodes { return &n.Lhs } @@ -142,6 +150,11 @@ func (n *AssignStmt) doChildren(do func(Node) error) error { err = maybeDo(n.Y, err, do) return err } +func (n *AssignStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Y = maybeEdit(n.Y, edit) +} func (n *AssignStmt) Left() Node { return n.X } func (n *AssignStmt) SetLeft(x Node) { n.X = x } @@ -192,6 +205,11 @@ func (n *AssignOpStmt) doChildren(do func(Node) error) error { err = maybeDo(n.Y, err, do) return err } +func (n *AssignOpStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Y = maybeEdit(n.Y, edit) +} func (n *AssignOpStmt) Left() Node { return n.X } func (n *AssignOpStmt) SetLeft(x Node) { n.X = x } @@ -232,6 +250,10 @@ func (n *BlockStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.list, err, do) return err } +func (n *BlockStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.list, edit) +} func (n *BlockStmt) List() Nodes { return n.list } func (n *BlockStmt) PtrList() *Nodes { return &n.list } @@ -271,6 +293,9 @@ func (n *BranchStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.init, err, do) return err } +func (n *BranchStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} func (n *BranchStmt) Sym() *types.Sym { return n.Label } func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym } @@ -312,6 +337,13 @@ func (n *CaseStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.body, err, do) return err } +func (n *CaseStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Vars, edit) + editList(n.list, edit) + n.Comm = maybeEdit(n.Comm, edit) + editList(n.body, edit) +} func (n *CaseStmt) List() Nodes { return n.list } func (n *CaseStmt) PtrList() *Nodes { return &n.list } @@ -351,6 +383,10 @@ func (n *DeferStmt) doChildren(do func(Node) error) error { err = maybeDo(n.Call, err, do) return err } +func (n *DeferStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Call = maybeEdit(n.Call, edit) +} func (n *DeferStmt) Left() Node { return n.Call } func (n *DeferStmt) SetLeft(x Node) { n.Call = x } @@ -394,6 +430,13 @@ func (n *ForStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.body, err, do) return err } +func (n *ForStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Cond = maybeEdit(n.Cond, edit) + editList(n.Late, edit) + n.Post = maybeEdit(n.Post, edit) + editList(n.body, edit) +} func (n *ForStmt) Sym() *types.Sym { return n.Label } func (n *ForStmt) SetSym(x *types.Sym) { n.Label = x } @@ -443,6 +486,10 @@ func (n *GoStmt) doChildren(do func(Node) error) error { err = maybeDo(n.Call, err, do) return err } +func (n *GoStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Call = maybeEdit(n.Call, edit) +} func (n *GoStmt) Left() Node { return n.Call } func (n *GoStmt) SetLeft(x Node) { n.Call = x } @@ -482,6 +529,12 @@ func (n *IfStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.Else, err, do) return err } +func (n *IfStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Cond = maybeEdit(n.Cond, edit) + editList(n.body, edit) + editList(n.Else, edit) +} func (n *IfStmt) Left() Node { return n.Cond } func (n *IfStmt) SetLeft(x Node) { n.Cond = x } @@ -519,6 +572,9 @@ func (n *InlineMarkStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.init, err, do) return err } +func (n *InlineMarkStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} func (n *InlineMarkStmt) Offset() int64 { return n.Index } func (n *InlineMarkStmt) SetOffset(x int64) { n.Index = x } @@ -548,6 +604,9 @@ func (n *LabelStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.init, err, do) return err } +func (n *LabelStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} func (n *LabelStmt) Sym() *types.Sym { return n.Label } func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x } @@ -591,6 +650,12 @@ func (n *RangeStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.body, err, do) return err } +func (n *RangeStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Vars, edit) + n.X = maybeEdit(n.X, edit) + editList(n.body, edit) +} func (n *RangeStmt) Sym() *types.Sym { return n.Label } func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x } @@ -639,6 +704,10 @@ func (n *ReturnStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.Results, err, do) return err } +func (n *ReturnStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Results, edit) +} func (n *ReturnStmt) Orig() Node { return n.orig } func (n *ReturnStmt) SetOrig(x Node) { n.orig = x } @@ -682,6 +751,11 @@ func (n *SelectStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.Compiled, err, do) return err } +func (n *SelectStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Cases, edit) + editList(n.Compiled, edit) +} func (n *SelectStmt) List() Nodes { return n.Cases } func (n *SelectStmt) PtrList() *Nodes { return &n.Cases } @@ -722,6 +796,11 @@ func (n *SendStmt) doChildren(do func(Node) error) error { err = maybeDo(n.Value, err, do) return err } +func (n *SendStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Chan = maybeEdit(n.Chan, edit) + n.Value = maybeEdit(n.Value, edit) +} func (n *SendStmt) Left() Node { return n.Chan } func (n *SendStmt) SetLeft(x Node) { n.Chan = x } @@ -765,6 +844,12 @@ func (n *SwitchStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.Compiled, err, do) return err } +func (n *SwitchStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Tag = maybeEdit(n.Tag, edit) + editList(n.Cases, edit) + editList(n.Compiled, edit) +} func (n *SwitchStmt) Left() Node { return n.Tag } func (n *SwitchStmt) SetLeft(x Node) { n.Tag = x } @@ -807,6 +892,12 @@ func (n *TypeSwitchGuard) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) return err } +func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) { + if n.name != nil { + n.name = edit(n.name).(*Name) + } + n.X = maybeEdit(n.X, edit) +} func (n *TypeSwitchGuard) Left() Node { if n.name == nil { diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index 2723c00044..d69dc3fd2a 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -80,6 +80,9 @@ func (n *ChanType) doChildren(do func(Node) error) error { err = maybeDo(n.Elem, err, do) return err } +func (n *ChanType) editChildren(edit func(Node) Node) { + n.Elem = maybeEdit(n.Elem, edit) +} func (n *ChanType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -116,6 +119,10 @@ func (n *MapType) doChildren(do func(Node) error) error { err = maybeDo(n.Elem, err, do) return err } +func (n *MapType) editChildren(edit func(Node) Node) { + n.Key = maybeEdit(n.Key, edit) + n.Elem = maybeEdit(n.Elem, edit) +} func (n *MapType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Key = nil @@ -155,6 +162,9 @@ func (n *StructType) doChildren(do func(Node) error) error { err = maybeDoFields(n.Fields, err, do) return err } +func (n *StructType) editChildren(edit func(Node) Node) { + editFields(n.Fields, edit) +} func (n *StructType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) @@ -202,6 +212,9 @@ func (n *InterfaceType) doChildren(do func(Node) error) error { err = maybeDoFields(n.Methods, err, do) return err } +func (n *InterfaceType) editChildren(edit func(Node) Node) { + editFields(n.Methods, edit) +} func (n *InterfaceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) @@ -249,6 +262,11 @@ func (n *FuncType) doChildren(do func(Node) error) error { err = maybeDoFields(n.Results, err, do) return err } +func (n *FuncType) editChildren(edit func(Node) Node) { + editField(n.Recv, edit) + editFields(n.Params, edit) + editFields(n.Results, edit) +} func (n *FuncType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) @@ -337,6 +355,24 @@ func maybeDoFields(list []*Field, err error, do func(Node) error) error { return err } +func editField(f *Field, edit func(Node) Node) { + if f == nil { + return + } + if f.Decl != nil { + f.Decl = edit(f.Decl).(*Name) + } + if f.Ntype != nil { + f.Ntype = toNtype(edit(f.Ntype)) + } +} + +func editFields(list []*Field, edit func(Node) Node) { + for _, f := range list { + editField(f, edit) + } +} + func (f *Field) deepCopy(pos src.XPos) *Field { if f == nil { return nil @@ -380,6 +416,9 @@ func (n *SliceType) doChildren(do func(Node) error) error { err = maybeDo(n.Elem, err, do) return err } +func (n *SliceType) editChildren(edit func(Node) Node) { + n.Elem = maybeEdit(n.Elem, edit) +} func (n *SliceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -417,6 +456,10 @@ func (n *ArrayType) doChildren(do func(Node) error) error { err = maybeDo(n.Elem, err, do) return err } +func (n *ArrayType) editChildren(edit func(Node) Node) { + n.Len = maybeEdit(n.Len, edit) + n.Elem = maybeEdit(n.Elem, edit) +} func (n *ArrayType) DeepCopy(pos src.XPos) Node { if n.op == OTYPE { @@ -451,6 +494,7 @@ func (n *typeNode) copy() Node { c := *n; return &c } func (n *typeNode) doChildren(do func(Node) error) error { return nil } +func (n *typeNode) editChildren(edit func(Node) Node) {} func (n *typeNode) Type() *types.Type { return n.typ } func (n *typeNode) Sym() *types.Sym { return n.typ.Sym() } diff --git a/src/cmd/compile/internal/ir/visit.go b/src/cmd/compile/internal/ir/visit.go index 042257c32a..4f3575614d 100644 --- a/src/cmd/compile/internal/ir/visit.go +++ b/src/cmd/compile/internal/ir/visit.go @@ -226,16 +226,7 @@ func EditChildren(n Node, edit func(Node) Node) { if n == nil { return } - editList(n.Init(), edit) - if l := n.Left(); l != nil { - n.SetLeft(edit(l)) - } - if r := n.Right(); r != nil { - n.SetRight(edit(r)) - } - editList(n.List(), edit) - editList(n.Body(), edit) - editList(n.Rlist(), edit) + n.editChildren(edit) } // editList calls edit on each non-nil node x in the list, From 9ab3d854ad95d06f5dd0874050ee57dd63c5a746 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 3 Dec 2020 23:56:16 -0500 Subject: [PATCH 140/212] [dev.regabi] cmd/compile: avoid general traversal in deadcode deadcode is trying to walk the statements it can find, but it can sweep in other nodes too. Stop doing that: only walk known statements containing statements. Otherwise, if we put panics in expression accessors that shouldn't be used anymore, deadcode can trip them. deadcode would be a good candidate to rewrite using EditChildren, but that would certainly cause toolstash changes, since deadcode is so ad-hoc about exactly which parts of the function it looks at. For now just remove the general traversal and leave as is. Passes buildall w/ toolstash -cmp. Change-Id: I06481eb87350905597600203c4fa724d55645b46 Reviewed-on: https://go-review.googlesource.com/c/go/+/275377 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/typecheck.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 65c5f2abce..2070297bc0 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3860,9 +3860,24 @@ func deadcodeslice(nn *ir.Nodes) { } deadcodeslice(n.PtrInit()) - deadcodeslice(n.PtrBody()) - deadcodeslice(n.PtrList()) - deadcodeslice(n.PtrRlist()) + switch n.Op() { + case ir.OBLOCK: + deadcodeslice(n.PtrList()) + case ir.OCASE: + deadcodeslice(n.PtrBody()) + case ir.OFOR: + deadcodeslice(n.PtrBody()) + case ir.OIF: + deadcodeslice(n.PtrBody()) + deadcodeslice(n.PtrRlist()) + case ir.ORANGE: + deadcodeslice(n.PtrBody()) + case ir.OSELECT: + deadcodeslice(n.PtrList()) + case ir.OSWITCH: + deadcodeslice(n.PtrList()) + } + if cut { nn.Set(nn.Slice()[:i+1]) break From 5dbd2e8e44d823bfbc3df883c544e23f4a872de1 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 4 Dec 2020 00:30:53 -0500 Subject: [PATCH 141/212] [dev.regabi] cmd/compile: remove DeepCopyNode interface The only reason for the DeepCopyNode interface was to allow the type syntaxes to avoid being constrained by Left, Right etc. methods. Now those are gone, so the general traversal methods they implement (doChildren, editChildren) do the right thing for DeepCopy. Passes buildall w/ toolstash -cmp. Change-Id: I54672c011114a95efabff32dbcf02e6071f91b9e Reviewed-on: https://go-review.googlesource.com/c/go/+/275379 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/copy.go | 21 ---------- src/cmd/compile/internal/ir/expr.go | 11 ------ src/cmd/compile/internal/ir/type.go | 59 ----------------------------- 3 files changed, 91 deletions(-) diff --git a/src/cmd/compile/internal/ir/copy.go b/src/cmd/compile/internal/ir/copy.go index 86e78cfc33..7f5d313513 100644 --- a/src/cmd/compile/internal/ir/copy.go +++ b/src/cmd/compile/internal/ir/copy.go @@ -70,33 +70,12 @@ func copyList(x Nodes) Nodes { return AsNodes(c) } -// A Node can implement DeepCopyNode to provide a custom implementation -// of DeepCopy. If the compiler only needs access to a Node's structure during -// DeepCopy, then a Node can implement DeepCopyNode instead of providing -// fine-grained mutable access with Left, SetLeft, Right, SetRight, and so on. -type DeepCopyNode interface { - Node - DeepCopy(pos src.XPos) Node -} - // DeepCopy returns a “deep” copy of n, with its entire structure copied // (except for shared nodes like ONAME, ONONAME, OLITERAL, and OTYPE). // If pos.IsKnown(), it sets the source position of newly allocated Nodes to pos. -// -// The default implementation is to traverse the Node graph, making -// a shallow copy of each node and then updating each field to point -// at shallow copies of children, recursively, using Left, SetLeft, and so on. -// -// If a Node wishes to provide an alternate implementation, it can -// implement a DeepCopy method: see the DeepCopyNode interface. -// -// TODO(rsc): Once Nodes implement EditChildren, remove the DeepCopyNode interface. func DeepCopy(pos src.XPos, n Node) Node { var edit func(Node) Node edit = func(x Node) Node { - if x, ok := x.(DeepCopyNode); ok { - return x.DeepCopy(pos) - } switch x.Op() { case OPACK, ONAME, ONONAME, OLITERAL, ONIL, OTYPE: return x diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 312faa8436..cfdb86f221 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -1163,17 +1163,6 @@ func (n *StarExpr) SetOTYPE(t *types.Type) { t.SetNod(n) } -func (n *StarExpr) DeepCopy(pos src.XPos) Node { - if n.op == OTYPE { - // Can't change types and no node references left. - return n - } - c := SepCopy(n).(*StarExpr) - c.pos = n.posOr(pos) - c.X = DeepCopy(pos, n.X) - return c -} - // A TypeAssertionExpr is a selector expression X.(Type). // Before type-checking, the type is Ntype. type TypeAssertExpr struct { diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index d69dc3fd2a..9f82c9faa2 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -88,14 +88,6 @@ func (n *ChanType) SetOTYPE(t *types.Type) { n.Elem = nil } -func (n *ChanType) DeepCopy(pos src.XPos) Node { - if n.op == OTYPE { - // Can't change types and no node references left. - return n - } - return NewChanType(n.posOr(pos), DeepCopy(pos, n.Elem), n.Dir) -} - // A MapType represents a map[Key]Value type syntax. type MapType struct { miniType @@ -129,14 +121,6 @@ func (n *MapType) SetOTYPE(t *types.Type) { n.Elem = nil } -func (n *MapType) DeepCopy(pos src.XPos) Node { - if n.op == OTYPE { - // Can't change types and no node references left. - return n - } - return NewMapType(n.posOr(pos), DeepCopy(pos, n.Key), DeepCopy(pos, n.Elem)) -} - // A StructType represents a struct { ... } type syntax. type StructType struct { miniType @@ -171,14 +155,6 @@ func (n *StructType) SetOTYPE(t *types.Type) { n.Fields = nil } -func (n *StructType) DeepCopy(pos src.XPos) Node { - if n.op == OTYPE { - // Can't change types and no node references left. - return n - } - return NewStructType(n.posOr(pos), deepCopyFields(pos, n.Fields)) -} - func deepCopyFields(pos src.XPos, fields []*Field) []*Field { var out []*Field for _, f := range fields { @@ -221,14 +197,6 @@ func (n *InterfaceType) SetOTYPE(t *types.Type) { n.Methods = nil } -func (n *InterfaceType) DeepCopy(pos src.XPos) Node { - if n.op == OTYPE { - // Can't change types and no node references left. - return n - } - return NewInterfaceType(n.posOr(pos), deepCopyFields(pos, n.Methods)) -} - // A FuncType represents a func(Args) Results type syntax. type FuncType struct { miniType @@ -275,17 +243,6 @@ func (n *FuncType) SetOTYPE(t *types.Type) { n.Results = nil } -func (n *FuncType) DeepCopy(pos src.XPos) Node { - if n.op == OTYPE { - // Can't change types and no node references left. - return n - } - return NewFuncType(n.posOr(pos), - n.Recv.deepCopy(pos), - deepCopyFields(pos, n.Params), - deepCopyFields(pos, n.Results)) -} - // A Field is a declared struct field, interface method, or function argument. // It is not a Node. type Field struct { @@ -424,14 +381,6 @@ func (n *SliceType) SetOTYPE(t *types.Type) { n.Elem = nil } -func (n *SliceType) DeepCopy(pos src.XPos) Node { - if n.op == OTYPE { - // Can't change types and no node references left. - return n - } - return NewSliceType(n.posOr(pos), DeepCopy(pos, n.Elem)) -} - // An ArrayType represents a [Len]Elem type syntax. // If Len is nil, the type is a [...]Elem in an array literal. type ArrayType struct { @@ -461,14 +410,6 @@ func (n *ArrayType) editChildren(edit func(Node) Node) { n.Elem = maybeEdit(n.Elem, edit) } -func (n *ArrayType) DeepCopy(pos src.XPos) Node { - if n.op == OTYPE { - // Can't change types and no node references left. - return n - } - return NewArrayType(n.posOr(pos), DeepCopy(pos, n.Len), DeepCopy(pos, n.Elem)) -} - func (n *ArrayType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Len = nil From edf60be15175ff2eb20fb66344d7487875546778 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 3 Dec 2020 17:07:52 +0000 Subject: [PATCH 142/212] doc/go1.16: document no language changes There are no language changes in Go 1.16, so document that. For #40700. Fixes #42976. Change-Id: I80b0d2ce6cf550c00c0f026ee59ac9fbce6310be Reviewed-on: https://go-review.googlesource.com/c/go/+/275117 Trust: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor --- doc/go1.16.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 62d9b97db8..ce93ab349e 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -26,7 +26,7 @@ Do not send CLs removing the interior tags from such phrases.

Changes to the language

- TODO + There are no changes to the language.

Ports

From d9cb84c84bb0edc1afb782f99de4cc424ac0d23f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 3 Dec 2020 16:52:45 -0800 Subject: [PATCH 143/212] [dev.regabi] cmd/compile: add SameSource, Uses, and DeclaredBy helpers Currently, because we use the same *Name to represent both declaration and uses of an object, it's ambiguous what "n1 == n2" means when comparing two Node values. It can mean any of: Are these the same syntactic element? Is n1 a use of declared variable n2? Are n1 and n2 both uses of the same declared variable? We'd like to introduce a new IdentExpr node to replace use of Name within the AST, but that means those three cases need to be handled differently. The first case needs to stay "n1 == n2", but the other cases need to become "n1.Name() == n2" and "n1.Name() == n2.Name()", respectively. ("n1.Name() == n2.Name()" also currently works for the second case, but eventually we'll want to get rid of the Name.Name method.) This CL introduces helper functions SameSource and Uses to handle these cases. It also introduces DeclaredBy, which is another somewhat common case that the next CL introduces uses of. Passes buildall w/ toolstash -cmp. Updates #42990. Change-Id: Ia816c124446e9067645d5820a8163f295968794f Reviewed-on: https://go-review.googlesource.com/c/go/+/275305 Reviewed-by: Russ Cox Trust: Matthew Dempsky --- src/cmd/compile/internal/ir/name.go | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index d2c33eab2b..030fb82a7d 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -297,6 +297,43 @@ func (n *Name) SetVal(v constant.Value) { n.val = v } +// SameSource reports whether two nodes refer to the same source +// element. +// +// It exists to help incrementally migrate the compiler towards +// allowing the introduction of IdentExpr (#42990). Once we have +// IdentExpr, it will no longer be safe to directly compare Node +// values to tell if they refer to the same Name. Instead, code will +// need to explicitly get references to the underlying Name object(s), +// and compare those instead. +// +// It will still be safe to compare Nodes directly for checking if two +// nodes are syntactically the same. The SameSource function exists to +// indicate code that intentionally compares Nodes for syntactic +// equality as opposed to code that has yet to be updated in +// preparation for IdentExpr. +func SameSource(n1, n2 Node) bool { + return n1 == n2 +} + +// Uses reports whether expression x is a (direct) use of the given +// variable. +func Uses(x Node, v *Name) bool { + if v == nil || v.Op() != ONAME { + base.Fatalf("RefersTo bad Name: %v", v) + } + return x.Op() == ONAME && x.Name() == v +} + +// DeclaredBy reports whether expression x refers (directly) to a +// variable that was declared by the given statement. +func DeclaredBy(x, stmt Node) bool { + if stmt == nil { + base.Fatalf("DeclaredBy nil") + } + return x.Op() == ONAME && SameSource(x.Name().Defn, stmt) +} + // The Class of a variable/function describes the "storage class" // of a variable or function. During parsing, storage classes are // called declaration contexts. From 133b03e1c386dc69e46fa36f9053ff6993125ace Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 3 Dec 2020 16:57:56 -0800 Subject: [PATCH 144/212] [dev.regabi] cmd/compile: rewrite code to use DeclaredBy Passes buildall w/ toolstash -cmp. Updates #42990. [git-generate] cd src/cmd/compile/internal/gc rf ' ex { import "cmd/compile/internal/ir" var x, stmt ir.Node x.Name() != nil && x.Name().Defn == stmt -> ir.DeclaredBy(x, stmt) x.Name() == nil || x.Name().Defn != stmt -> !ir.DeclaredBy(x, stmt) } ' Change-Id: I222a757296dbcb5d0889d617d221a9d7319f2d74 Reviewed-on: https://go-review.googlesource.com/c/go/+/275306 Reviewed-by: Russ Cox Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/range.go | 8 ++++---- src/cmd/compile/internal/gc/typecheck.go | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go index e48642a854..8025119c5e 100644 --- a/src/cmd/compile/internal/gc/range.go +++ b/src/cmd/compile/internal/gc/range.go @@ -49,7 +49,7 @@ func typecheckrangeExpr(n ir.Node) { // delicate little dance. see typecheckas2 ls := n.List().Slice() for i1, n1 := range ls { - if n1.Name() == nil || n1.Name().Defn != n { + if !ir.DeclaredBy(n1, n) { ls[i1] = typecheck(ls[i1], ctxExpr|ctxAssign) } } @@ -115,7 +115,7 @@ func typecheckrangeExpr(n ir.Node) { } if v1 != nil { - if v1.Name() != nil && v1.Name().Defn == n { + if ir.DeclaredBy(v1, n) { v1.SetType(t1) } else if v1.Type() != nil { if op, why := assignop(t1, v1.Type()); op == ir.OXXX { @@ -126,7 +126,7 @@ func typecheckrangeExpr(n ir.Node) { } if v2 != nil { - if v2.Name() != nil && v2.Name().Defn == n { + if ir.DeclaredBy(v2, n) { v2.SetType(t2) } else if v2.Type() != nil { if op, why := assignop(t2, v2.Type()); op == ir.OXXX { @@ -477,7 +477,7 @@ func isMapClear(n ir.Node) bool { } // Require k to be a new variable name. - if k.Name() == nil || k.Name().Defn != n { + if !ir.DeclaredBy(k, n) { return false } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 2070297bc0..c22786f148 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3083,7 +3083,7 @@ func checklvalue(n ir.Node, verb string) { func checkassign(stmt ir.Node, n ir.Node) { // Variables declared in ORANGE are assigned on every iteration. - if n.Name() == nil || n.Name().Defn != stmt || stmt.Op() == ir.ORANGE { + if !ir.DeclaredBy(n, stmt) || stmt.Op() == ir.ORANGE { r := outervalue(n) if r.Op() == ir.ONAME { r.Name().SetAssigned(true) @@ -3192,7 +3192,7 @@ func typecheckas(n ir.Node) { // so that the conversion below happens). n.SetLeft(resolve(n.Left())) - if n.Left().Name() == nil || n.Left().Name().Defn != n || n.Left().Name().Ntype != nil { + if !ir.DeclaredBy(n.Left(), n) || n.Left().Name().Ntype != nil { n.SetLeft(typecheck(n.Left(), ctxExpr|ctxAssign)) } @@ -3211,7 +3211,7 @@ func typecheckas(n ir.Node) { } } - if n.Left().Name() != nil && n.Left().Name().Defn == n && n.Left().Name().Ntype == nil { + if ir.DeclaredBy(n.Left(), n) && n.Left().Name().Ntype == nil { n.SetRight(defaultlit(n.Right(), nil)) n.Left().SetType(n.Right().Type()) } @@ -3247,7 +3247,7 @@ func typecheckas2(n ir.Node) { n1 = resolve(n1) ls[i1] = n1 - if n1.Name() == nil || n1.Name().Defn != n || n1.Name().Ntype != nil { + if !ir.DeclaredBy(n1, n) || n1.Name().Ntype != nil { ls[i1] = typecheck(ls[i1], ctxExpr|ctxAssign) } } @@ -3272,7 +3272,7 @@ func typecheckas2(n ir.Node) { if nl.Type() != nil && nr.Type() != nil { rs[il] = assignconv(nr, nl.Type(), "assignment") } - if nl.Name() != nil && nl.Name().Defn == n && nl.Name().Ntype == nil { + if ir.DeclaredBy(nl, n) && nl.Name().Ntype == nil { rs[il] = defaultlit(rs[il], nil) nl.SetType(rs[il].Type()) } @@ -3305,7 +3305,7 @@ func typecheckas2(n ir.Node) { if f.Type != nil && l.Type() != nil { checkassignto(f.Type, l) } - if l.Name() != nil && l.Name().Defn == n && l.Name().Ntype == nil { + if ir.DeclaredBy(l, n) && l.Name().Ntype == nil { l.SetType(f.Type) } } @@ -3332,14 +3332,14 @@ func typecheckas2(n ir.Node) { if l.Type() != nil { checkassignto(r.Type(), l) } - if l.Name() != nil && l.Name().Defn == n { + if ir.DeclaredBy(l, n) { l.SetType(r.Type()) } l := n.List().Second() if l.Type() != nil && !l.Type().IsBoolean() { checkassignto(types.Types[types.TBOOL], l) } - if l.Name() != nil && l.Name().Defn == n && l.Name().Ntype == nil { + if ir.DeclaredBy(l, n) && l.Name().Ntype == nil { l.SetType(types.Types[types.TBOOL]) } goto out From b75f51c6451a00f223ad43ed7069e4136466fdac Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 4 Dec 2020 11:07:25 +0700 Subject: [PATCH 145/212] [dev.regabi] cmd/compile: replace ir.Node with *ir.Name in Liveness Passes buildall w/ toolstash -cmp. Updates #42982 Change-Id: Iad8df321adfd576da070c13ed16a9651d4e59ad8 Reviewed-on: https://go-review.googlesource.com/c/go/+/275352 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/plive.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index f2555cc941..06e423daa1 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -103,8 +103,8 @@ type BlockEffects struct { type Liveness struct { fn *ir.Func f *ssa.Func - vars []ir.Node - idx map[ir.Node]int32 + vars []*ir.Name + idx map[*ir.Name]int32 stkptrsize int64 be []BlockEffects @@ -212,14 +212,14 @@ func livenessShouldTrack(n ir.Node) bool { // getvariables returns the list of on-stack variables that we need to track // and a map for looking up indices by *Node. -func getvariables(fn *ir.Func) ([]ir.Node, map[ir.Node]int32) { - var vars []ir.Node +func getvariables(fn *ir.Func) ([]*ir.Name, map[*ir.Name]int32) { + var vars []*ir.Name for _, n := range fn.Dcl { if livenessShouldTrack(n) { vars = append(vars, n) } } - idx := make(map[ir.Node]int32, len(vars)) + idx := make(map[*ir.Name]int32, len(vars)) for i, n := range vars { idx[n] = int32(i) } @@ -276,13 +276,14 @@ func (lv *Liveness) valueEffects(v *ssa.Value) (int32, liveEffect) { return -1, 0 } + nn := n.(*ir.Name) // AllocFrame has dropped unused variables from // lv.fn.Func.Dcl, but they might still be referenced by // OpVarFoo pseudo-ops. Ignore them to prevent "lost track of // variable" ICEs (issue 19632). switch v.Op { case ssa.OpVarDef, ssa.OpVarKill, ssa.OpVarLive, ssa.OpKeepAlive: - if !n.Name().Used() { + if !nn.Name().Used() { return -1, 0 } } @@ -305,7 +306,7 @@ func (lv *Liveness) valueEffects(v *ssa.Value) (int32, liveEffect) { return -1, 0 } - if pos, ok := lv.idx[n]; ok { + if pos, ok := lv.idx[nn]; ok { return pos, effect } return -1, 0 @@ -356,7 +357,7 @@ type livenessFuncCache struct { // Constructs a new liveness structure used to hold the global state of the // liveness computation. The cfg argument is a slice of *BasicBlocks and the // vars argument is a slice of *Nodes. -func newliveness(fn *ir.Func, f *ssa.Func, vars []ir.Node, idx map[ir.Node]int32, stkptrsize int64) *Liveness { +func newliveness(fn *ir.Func, f *ssa.Func, vars []*ir.Name, idx map[*ir.Name]int32, stkptrsize int64) *Liveness { lv := &Liveness{ fn: fn, f: f, @@ -482,7 +483,7 @@ func onebitwalktype1(t *types.Type, off int64, bv bvec) { // Generates live pointer value maps for arguments and local variables. The // this argument and the in arguments are always assumed live. The vars // argument is a slice of *Nodes. -func (lv *Liveness) pointerMap(liveout bvec, vars []ir.Node, args, locals bvec) { +func (lv *Liveness) pointerMap(liveout bvec, vars []*ir.Name, args, locals bvec) { for i := int32(0); ; i++ { i = liveout.Next(i) if i < 0 { From 46b6e70e3b9380b5dff6319673e385950b9fb201 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 4 Dec 2020 11:38:47 +0700 Subject: [PATCH 146/212] [dev.regabi] cmd/compile: replace ir.Node with *ir.Name in Order Passes buildall w/ toolstash -cmp. Updates #42982 Change-Id: I7121c37f72ccbc141a7dd17fba1753f2c6289908 Reviewed-on: https://go-review.googlesource.com/c/go/+/275353 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/order.go | 14 +++++++------- src/cmd/compile/internal/gc/sinit.go | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 1680d9d920..39b78c9819 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -44,9 +44,9 @@ import ( // Order holds state during the ordering process. type Order struct { - out []ir.Node // list of generated statements - temp []ir.Node // stack of temporary variables - free map[string][]ir.Node // free list of unused temporaries, by type.LongString(). + out []ir.Node // list of generated statements + temp []*ir.Name // stack of temporary variables + free map[string][]*ir.Name // free list of unused temporaries, by type.LongString(). } // Order rewrites fn.Nbody to apply the ordering constraints @@ -57,14 +57,14 @@ func order(fn *ir.Func) { ir.DumpList(s, fn.Body()) } - orderBlock(fn.PtrBody(), map[string][]ir.Node{}) + orderBlock(fn.PtrBody(), map[string][]*ir.Name{}) } // newTemp allocates a new temporary with the given type, // pushes it onto the temp stack, and returns it. // If clear is true, newTemp emits code to zero the temporary. func (o *Order) newTemp(t *types.Type, clear bool) ir.Node { - var v ir.Node + var v *ir.Name // Note: LongString is close to the type equality we want, // but not exactly. We still need to double-check with types.Identical. key := t.LongString() @@ -415,7 +415,7 @@ func (o *Order) edge() { // orderBlock orders the block of statements in n into a new slice, // and then replaces the old slice in n with the new slice. // free is a map that can be used to obtain temporary variables by type. -func orderBlock(n *ir.Nodes, free map[string][]ir.Node) { +func orderBlock(n *ir.Nodes, free map[string][]*ir.Name) { var order Order order.free = free mark := order.markTemp() @@ -446,7 +446,7 @@ func (o *Order) exprInPlace(n ir.Node) ir.Node { // The result of orderStmtInPlace MUST be assigned back to n, e.g. // n.Left = orderStmtInPlace(n.Left) // free is a map that can be used to obtain temporary variables by type. -func orderStmtInPlace(n ir.Node, free map[string][]ir.Node) ir.Node { +func orderStmtInPlace(n ir.Node, free map[string][]*ir.Name) ir.Node { var order Order order.free = free mark := order.markTemp() diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index 20abbfef8c..c446c9d083 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -579,7 +579,7 @@ func fixedlit(ctxt initContext, kind initKind, n ir.Node, var_ ir.Node, init *ir case initKindStatic: genAsStatic(a) case initKindDynamic, initKindLocalCode: - a = orderStmtInPlace(a, map[string][]ir.Node{}) + a = orderStmtInPlace(a, map[string][]*ir.Name{}) a = walkstmt(a) init.Append(a) default: @@ -747,7 +747,7 @@ func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) { a = ir.Nod(ir.OAS, a, value) a = typecheck(a, ctxStmt) - a = orderStmtInPlace(a, map[string][]ir.Node{}) + a = orderStmtInPlace(a, map[string][]*ir.Name{}) a = walkstmt(a) init.Append(a) } @@ -756,7 +756,7 @@ func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) { a = ir.Nod(ir.OAS, var_, ir.Nod(ir.OSLICE, vauto, nil)) a = typecheck(a, ctxStmt) - a = orderStmtInPlace(a, map[string][]ir.Node{}) + a = orderStmtInPlace(a, map[string][]*ir.Name{}) a = walkstmt(a) init.Append(a) } From 0b99ea3b16ae2e00851e087771d30e649c2faa4c Mon Sep 17 00:00:00 2001 From: zikaeroh Date: Fri, 4 Dec 2020 12:20:17 -0800 Subject: [PATCH 147/212] cmd/vendor: sync pprof@v0.0.0-20201203190320-1bf35d6f28c2 Pulls in a fix to make versioned import paths more readable in pprof's graph view. Updated via the instructions in README.vendor. Updates #36905 Change-Id: I6a91de0f4ca1be3fc69d8e1a39ccf4f5bd0387ef Reviewed-on: https://go-review.googlesource.com/c/go/+/275513 Run-TryBot: Dmitri Shuralyov Reviewed-by: Hyang-Ah Hana Kim Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- src/cmd/go.mod | 3 +- src/cmd/go.sum | 9 +- .../google/pprof/internal/graph/dotgraph.go | 24 +- .../google/pprof/internal/graph/graph.go | 17 +- .../github.com/ianlancetaylor/demangle/ast.go | 378 ++++++++++++- .../ianlancetaylor/demangle/demangle.go | 503 ++++++++++++++---- src/cmd/vendor/modules.txt | 5 +- 7 files changed, 793 insertions(+), 146 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index bfee2c7f06..46ec54b5a2 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -3,8 +3,7 @@ module cmd go 1.16 require ( - github.com/google/pprof v0.0.0-20201007051231-1066cbb265c7 - github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 // indirect + github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2 golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/mod v0.4.0 diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 7a743d9f73..b3e4598bd1 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -1,11 +1,10 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/google/pprof v0.0.0-20201007051231-1066cbb265c7 h1:qYWTuM6SUNWgtvkhV8oH6GFHCpU+rKQOxPcepM3xKi0= -github.com/google/pprof v0.0.0-20201007051231-1066cbb265c7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 h1:S1+yTUaFPXuDZnPDbO+TrDFIjPzQraYH8/CwSlu9Fac= -github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2 h1:HyOHhUtuB/Ruw/L5s5pG2D0kckkN2/IzBs9OClGHnHI= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff h1:XmKBi9R6duxOB3lfc72wyrwiOY7X2Jl1wuI+RFOyMDE= golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= diff --git a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go index cde648f20b..8cb87da9af 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go @@ -127,7 +127,7 @@ func (b *builder) addLegend() { } title := labels[0] fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, title) - fmt.Fprintf(b, ` label="%s\l"`, strings.Join(escapeForDot(labels), `\l`)) + fmt.Fprintf(b, ` label="%s\l"`, strings.Join(escapeAllForDot(labels), `\l`)) if b.config.LegendURL != "" { fmt.Fprintf(b, ` URL="%s" target="_blank"`, b.config.LegendURL) } @@ -187,7 +187,7 @@ func (b *builder) addNode(node *Node, nodeID int, maxFlat float64) { // Create DOT attribute for node. attr := fmt.Sprintf(`label="%s" id="node%d" fontsize=%d shape=%s tooltip="%s (%s)" color="%s" fillcolor="%s"`, - label, nodeID, fontSize, shape, node.Info.PrintableName(), cumValue, + label, nodeID, fontSize, shape, escapeForDot(node.Info.PrintableName()), cumValue, dotColor(float64(node.CumValue())/float64(abs64(b.config.Total)), false), dotColor(float64(node.CumValue())/float64(abs64(b.config.Total)), true)) @@ -305,7 +305,8 @@ func (b *builder) addEdge(edge *Edge, from, to int, hasNodelets bool) { arrow = "..." } tooltip := fmt.Sprintf(`"%s %s %s (%s)"`, - edge.Src.Info.PrintableName(), arrow, edge.Dest.Info.PrintableName(), w) + escapeForDot(edge.Src.Info.PrintableName()), arrow, + escapeForDot(edge.Dest.Info.PrintableName()), w) attr = fmt.Sprintf(`%s tooltip=%s labeltooltip=%s`, attr, tooltip, tooltip) if edge.Residual { @@ -382,7 +383,7 @@ func dotColor(score float64, isBackground bool) string { func multilinePrintableName(info *NodeInfo) string { infoCopy := *info - infoCopy.Name = ShortenFunctionName(infoCopy.Name) + infoCopy.Name = escapeForDot(ShortenFunctionName(infoCopy.Name)) infoCopy.Name = strings.Replace(infoCopy.Name, "::", `\n`, -1) infoCopy.Name = strings.Replace(infoCopy.Name, ".", `\n`, -1) if infoCopy.File != "" { @@ -473,13 +474,18 @@ func min64(a, b int64) int64 { return b } -// escapeForDot escapes double quotes and backslashes, and replaces Graphviz's -// "center" character (\n) with a left-justified character. -// See https://graphviz.org/doc/info/attrs.html#k:escString for more info. -func escapeForDot(in []string) []string { +// escapeAllForDot applies escapeForDot to all strings in the given slice. +func escapeAllForDot(in []string) []string { var out = make([]string, len(in)) for i := range in { - out[i] = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(in[i], `\`, `\\`), `"`, `\"`), "\n", `\l`) + out[i] = escapeForDot(in[i]) } return out } + +// escapeForDot escapes double quotes and backslashes, and replaces Graphviz's +// "center" character (\n) with a left-justified character. +// See https://graphviz.org/doc/info/attrs.html#k:escString for more info. +func escapeForDot(str string) string { + return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(str, `\`, `\\`), `"`, `\"`), "\n", `\l`) +} diff --git a/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go b/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go index d2397a93d8..74b904c402 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go @@ -28,12 +28,14 @@ import ( ) var ( - // Removes package name and method arugments for Java method names. + // Removes package name and method arguments for Java method names. // See tests for examples. javaRegExp = regexp.MustCompile(`^(?:[a-z]\w*\.)*([A-Z][\w\$]*\.(?:|[a-z][\w\$]*(?:\$\d+)?))(?:(?:\()|$)`) - // Removes package name and method arugments for Go function names. + // Removes package name and method arguments for Go function names. // See tests for examples. goRegExp = regexp.MustCompile(`^(?:[\w\-\.]+\/)+(.+)`) + // Removes potential module versions in a package path. + goVerRegExp = regexp.MustCompile(`^(.*?)/v(?:[2-9]|[1-9][0-9]+)([./].*)$`) // Strips C++ namespace prefix from a C++ function / method name. // NOTE: Make sure to keep the template parameters in the name. Normally, // template parameters are stripped from the C++ names but when @@ -317,6 +319,8 @@ func New(prof *profile.Profile, o *Options) *Graph { // nodes. func newGraph(prof *profile.Profile, o *Options) (*Graph, map[uint64]Nodes) { nodes, locationMap := CreateNodes(prof, o) + seenNode := make(map[*Node]bool) + seenEdge := make(map[nodePair]bool) for _, sample := range prof.Sample { var w, dw int64 w = o.SampleValue(sample.Value) @@ -326,8 +330,12 @@ func newGraph(prof *profile.Profile, o *Options) (*Graph, map[uint64]Nodes) { if dw == 0 && w == 0 { continue } - seenNode := make(map[*Node]bool, len(sample.Location)) - seenEdge := make(map[nodePair]bool, len(sample.Location)) + for k := range seenNode { + delete(seenNode, k) + } + for k := range seenEdge { + delete(seenEdge, k) + } var parent *Node // A residual edge goes over one or more nodes that were not kept. residual := false @@ -440,6 +448,7 @@ func newTree(prof *profile.Profile, o *Options) (g *Graph) { // ShortenFunctionName returns a shortened version of a function's name. func ShortenFunctionName(f string) string { f = cppAnonymousPrefixRegExp.ReplaceAllString(f, "") + f = goVerRegExp.ReplaceAllString(f, `${1}${2}`) for _, re := range []*regexp.Regexp{goRegExp, javaRegExp, cppRegExp} { if matches := re.FindStringSubmatch(f); len(matches) >= 2 { return strings.Join(matches[1:], "") diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go index 0ad5354f58..ccbe5b3559 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go @@ -5,7 +5,6 @@ package demangle import ( - "bytes" "fmt" "strings" ) @@ -23,7 +22,10 @@ type AST interface { // Copy an AST with possible transformations. // If the skip function returns true, no copy is required. // If the copy function returns nil, no copy is required. - // Otherwise the AST returned by copy is used in a copy of the full AST. + // The Copy method will do the right thing if copy returns nil + // for some components of an AST but not others, so a good + // copy function will only return non-nil for AST values that + // need to change. // Copy itself returns either a copy or nil. Copy(copy func(AST) AST, skip func(AST) bool) AST @@ -51,7 +53,7 @@ func ASTToString(a AST, options ...Option) string { type printState struct { tparams bool // whether to print template parameters - buf bytes.Buffer + buf strings.Builder last byte // Last byte written to buffer. // The inner field is a list of items to print for a type @@ -398,13 +400,172 @@ func (tp *TemplateParam) goString(indent int, field string) string { return fmt.Sprintf("%*s%sTemplateParam: Template: %p; Index %d", indent, "", field, tp.Template, tp.Index) } +// LambdaAuto is a lambda auto parameter. +type LambdaAuto struct { + Index int +} + +func (la *LambdaAuto) print(ps *printState) { + // We print the index plus 1 because that is what the standard + // demangler does. + fmt.Fprintf(&ps.buf, "auto:%d", la.Index+1) +} + +func (la *LambdaAuto) Traverse(fn func(AST) bool) { + fn(la) +} + +func (la *LambdaAuto) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(la) { + return nil + } + return fn(la) +} + +func (la *LambdaAuto) GoString() string { + return la.goString(0, "") +} + +func (la *LambdaAuto) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sLambdaAuto: Index %d", indent, "", field, la.Index) +} + // Qualifiers is an ordered list of type qualifiers. -type Qualifiers []string +type Qualifiers struct { + Qualifiers []AST +} + +func (qs *Qualifiers) print(ps *printState) { + first := true + for _, q := range qs.Qualifiers { + if !first { + ps.writeByte(' ') + } + q.print(ps) + first = false + } +} + +func (qs *Qualifiers) Traverse(fn func(AST) bool) { + if fn(qs) { + for _, q := range qs.Qualifiers { + q.Traverse(fn) + } + } +} + +func (qs *Qualifiers) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(qs) { + return nil + } + changed := false + qualifiers := make([]AST, len(qs.Qualifiers)) + for i, q := range qs.Qualifiers { + qc := q.Copy(fn, skip) + if qc == nil { + qualifiers[i] = q + } else { + qualifiers[i] = qc + changed = true + } + } + if !changed { + return fn(qs) + } + qs = &Qualifiers{Qualifiers: qualifiers} + if r := fn(qs); r != nil { + return r + } + return qs +} + +func (qs *Qualifiers) GoString() string { + return qs.goString(0, "") +} + +func (qs *Qualifiers) goString(indent int, field string) string { + quals := fmt.Sprintf("%*s%s", indent, "", field) + for _, q := range qs.Qualifiers { + quals += "\n" + quals += q.goString(indent+2, "") + } + return quals +} + +// Qualifier is a single type qualifier. +type Qualifier struct { + Name string // qualifier name: const, volatile, etc. + Exprs []AST // can be non-nil for noexcept and throw +} + +func (q *Qualifier) print(ps *printState) { + ps.writeString(q.Name) + if len(q.Exprs) > 0 { + ps.writeByte('(') + first := true + for _, e := range q.Exprs { + if !first { + ps.writeString(", ") + } + ps.print(e) + first = false + } + ps.writeByte(')') + } +} + +func (q *Qualifier) Traverse(fn func(AST) bool) { + if fn(q) { + for _, e := range q.Exprs { + e.Traverse(fn) + } + } +} + +func (q *Qualifier) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(q) { + return nil + } + exprs := make([]AST, len(q.Exprs)) + changed := false + for i, e := range q.Exprs { + ec := e.Copy(fn, skip) + if ec == nil { + exprs[i] = e + } else { + exprs[i] = ec + changed = true + } + } + if !changed { + return fn(q) + } + q = &Qualifier{Name: q.Name, Exprs: exprs} + if r := fn(q); r != nil { + return r + } + return q +} + +func (q *Qualifier) GoString() string { + return q.goString(0, "Qualifier: ") +} + +func (q *Qualifier) goString(indent int, field string) string { + qs := fmt.Sprintf("%*s%s%s", indent, "", field, q.Name) + if len(q.Exprs) > 0 { + for i, e := range q.Exprs { + qs += "\n" + qs += e.goString(indent+2, fmt.Sprintf("%d: ", i)) + } + } + return qs +} // TypeWithQualifiers is a type with standard qualifiers. type TypeWithQualifiers struct { Base AST - Qualifiers Qualifiers + Qualifiers AST } func (twq *TypeWithQualifiers) print(ps *printState) { @@ -414,7 +575,7 @@ func (twq *TypeWithQualifiers) print(ps *printState) { if len(ps.inner) > 0 { // The qualifier wasn't printed by Base. ps.writeByte(' ') - ps.writeString(strings.Join(twq.Qualifiers, " ")) + ps.print(twq.Qualifiers) ps.inner = ps.inner[:len(ps.inner)-1] } } @@ -422,7 +583,7 @@ func (twq *TypeWithQualifiers) print(ps *printState) { // Print qualifiers as an inner type by just printing the qualifiers. func (twq *TypeWithQualifiers) printInner(ps *printState) { ps.writeByte(' ') - ps.writeString(strings.Join(twq.Qualifiers, " ")) + ps.print(twq.Qualifiers) } func (twq *TypeWithQualifiers) Traverse(fn func(AST) bool) { @@ -436,10 +597,17 @@ func (twq *TypeWithQualifiers) Copy(fn func(AST) AST, skip func(AST) bool) AST { return nil } base := twq.Base.Copy(fn, skip) - if base == nil { + quals := twq.Qualifiers.Copy(fn, skip) + if base == nil && quals == nil { return fn(twq) } - twq = &TypeWithQualifiers{Base: base, Qualifiers: twq.Qualifiers} + if base == nil { + base = twq.Base + } + if quals == nil { + quals = twq.Qualifiers + } + twq = &TypeWithQualifiers{Base: base, Qualifiers: quals} if r := fn(twq); r != nil { return r } @@ -451,14 +619,15 @@ func (twq *TypeWithQualifiers) GoString() string { } func (twq *TypeWithQualifiers) goString(indent int, field string) string { - return fmt.Sprintf("%*s%sTypeWithQualifiers: Qualifiers: %s\n%s", indent, "", field, - twq.Qualifiers, twq.Base.goString(indent+2, "Base: ")) + return fmt.Sprintf("%*s%sTypeWithQualifiers:\n%s\n%s", indent, "", field, + twq.Qualifiers.goString(indent+2, "Qualifiers: "), + twq.Base.goString(indent+2, "Base: ")) } // MethodWithQualifiers is a method with qualifiers. type MethodWithQualifiers struct { Method AST - Qualifiers Qualifiers + Qualifiers AST RefQualifier string // "" or "&" or "&&" } @@ -467,9 +636,9 @@ func (mwq *MethodWithQualifiers) print(ps *printState) { ps.inner = append(ps.inner, mwq) ps.print(mwq.Method) if len(ps.inner) > 0 { - if len(mwq.Qualifiers) > 0 { + if mwq.Qualifiers != nil { ps.writeByte(' ') - ps.writeString(strings.Join(mwq.Qualifiers, " ")) + ps.print(mwq.Qualifiers) } if mwq.RefQualifier != "" { ps.writeByte(' ') @@ -480,9 +649,9 @@ func (mwq *MethodWithQualifiers) print(ps *printState) { } func (mwq *MethodWithQualifiers) printInner(ps *printState) { - if len(mwq.Qualifiers) > 0 { + if mwq.Qualifiers != nil { ps.writeByte(' ') - ps.writeString(strings.Join(mwq.Qualifiers, " ")) + ps.print(mwq.Qualifiers) } if mwq.RefQualifier != "" { ps.writeByte(' ') @@ -501,10 +670,20 @@ func (mwq *MethodWithQualifiers) Copy(fn func(AST) AST, skip func(AST) bool) AST return nil } method := mwq.Method.Copy(fn, skip) - if method == nil { + var quals AST + if mwq.Qualifiers != nil { + quals = mwq.Qualifiers.Copy(fn, skip) + } + if method == nil && quals == nil { return fn(mwq) } - mwq = &MethodWithQualifiers{Method: method, Qualifiers: mwq.Qualifiers, RefQualifier: mwq.RefQualifier} + if method == nil { + method = mwq.Method + } + if quals == nil { + quals = mwq.Qualifiers + } + mwq = &MethodWithQualifiers{Method: method, Qualifiers: quals, RefQualifier: mwq.RefQualifier} if r := fn(mwq); r != nil { return r } @@ -517,14 +696,14 @@ func (mwq *MethodWithQualifiers) GoString() string { func (mwq *MethodWithQualifiers) goString(indent int, field string) string { var q string - if len(mwq.Qualifiers) > 0 { - q += fmt.Sprintf(" Qualifiers: %v", mwq.Qualifiers) + if mwq.Qualifiers != nil { + q += "\n" + mwq.Qualifiers.goString(indent+2, "Qualifiers: ") } if mwq.RefQualifier != "" { if q != "" { - q += ";" + q += "\n" } - q += " RefQualifier: " + mwq.RefQualifier + q += fmt.Sprintf("%*s%s%s", indent+2, "", "RefQualifier: ", mwq.RefQualifier) } return fmt.Sprintf("%*s%sMethodWithQualifiers:%s\n%s", indent, "", field, q, mwq.Method.goString(indent+2, "Method: ")) @@ -1955,6 +2134,22 @@ func (u *Unary) goString(indent int, field string) string { u.Expr.goString(indent+2, "Expr: ")) } +// isDesignatedInitializer reports whether x is a designated +// initializer. +func isDesignatedInitializer(x AST) bool { + switch x := x.(type) { + case *Binary: + if op, ok := x.Op.(*Operator); ok { + return op.Name == "=" || op.Name == "]=" + } + case *Trinary: + if op, ok := x.Op.(*Operator); ok { + return op.Name == "[...]=" + } + } + return false +} + // Binary is a binary operation in an expression. type Binary struct { Op AST @@ -1975,6 +2170,27 @@ func (b *Binary) print(ps *printState) { return } + if isDesignatedInitializer(b) { + if op.Name == "=" { + ps.writeByte('.') + } else { + ps.writeByte('[') + } + ps.print(b.Left) + if op.Name == "]=" { + ps.writeByte(']') + } + if isDesignatedInitializer(b.Right) { + // Don't add anything between designated + // initializer chains. + ps.print(b.Right) + } else { + ps.writeByte('=') + parenthesize(ps, b.Right) + } + return + } + // Use an extra set of parentheses around an expression that // uses the greater-than operator, so that it does not get // confused with the '>' that ends template parameters. @@ -1984,15 +2200,28 @@ func (b *Binary) print(ps *printState) { left := b.Left - // A function call in an expression should not print the types - // of the arguments. + // For a function call in an expression, don't print the types + // of the arguments unless there is a return type. + skipParens := false if op != nil && op.Name == "()" { if ty, ok := b.Left.(*Typed); ok { - left = ty.Name + if ft, ok := ty.Type.(*FunctionType); ok { + if ft.Return == nil { + left = ty.Name + } else { + skipParens = true + } + } else { + left = ty.Name + } } } - parenthesize(ps, left) + if skipParens { + ps.print(left) + } else { + parenthesize(ps, left) + } if op != nil && op.Name == "[]" { ps.writeByte('[') @@ -2070,6 +2299,23 @@ type Trinary struct { } func (t *Trinary) print(ps *printState) { + if isDesignatedInitializer(t) { + ps.writeByte('[') + ps.print(t.First) + ps.writeString(" ... ") + ps.print(t.Second) + ps.writeByte(']') + if isDesignatedInitializer(t.Third) { + // Don't add anything between designated + // initializer chains. + ps.print(t.Third) + } else { + ps.writeByte('=') + parenthesize(ps, t.Third) + } + return + } + parenthesize(ps, t.First) ps.writeByte('?') parenthesize(ps, t.Second) @@ -2362,6 +2608,9 @@ func (l *Literal) print(ps *printState) { ps.writeString("true") return } + } else if b.Name == "decltype(nullptr)" && l.Val == "" { + ps.print(l.Type) + return } else { isFloat = builtinTypeFloat[b.Name] } @@ -2821,6 +3070,83 @@ func (s *Special2) goString(indent int, field string) string { indent+2, "", s.Middle, s.Val2.goString(indent+2, "Val2: ")) } +// EnableIf is used by clang for an enable_if attribute. +type EnableIf struct { + Type AST + Args []AST +} + +func (ei *EnableIf) print(ps *printState) { + ps.print(ei.Type) + ps.writeString(" [enable_if:") + first := true + for _, a := range ei.Args { + if !first { + ps.writeString(", ") + } + ps.print(a) + first = false + } + ps.writeString("]") +} + +func (ei *EnableIf) Traverse(fn func(AST) bool) { + if fn(ei) { + ei.Type.Traverse(fn) + for _, a := range ei.Args { + a.Traverse(fn) + } + } +} + +func (ei *EnableIf) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(ei) { + return nil + } + typ := ei.Type.Copy(fn, skip) + argsChanged := false + args := make([]AST, len(ei.Args)) + for i, a := range ei.Args { + ac := a.Copy(fn, skip) + if ac == nil { + args[i] = a + } else { + args[i] = ac + argsChanged = true + } + } + if typ == nil && !argsChanged { + return fn(ei) + } + if typ == nil { + typ = ei.Type + } + ei = &EnableIf{Type: typ, Args: args} + if r := fn(ei); r != nil { + return r + } + return ei +} + +func (ei *EnableIf) GoString() string { + return ei.goString(0, "") +} + +func (ei *EnableIf) goString(indent int, field string) string { + var args string + if len(ei.Args) == 0 { + args = fmt.Sprintf("%*sArgs: nil", indent+2, "") + } else { + args = fmt.Sprintf("%*sArgs:", indent+2, "") + for i, a := range ei.Args { + args += "\n" + args += a.goString(indent+4, fmt.Sprintf("%d: ", i)) + } + } + return fmt.Sprintf("%*s%sEnableIf:\n%s\n%s", indent, "", field, + ei.Type.goString(indent+2, "Type: "), args) +} + // Print the inner types. func (ps *printState) printInner(prefixOnly bool) []AST { var save []AST diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go index 7541b736ba..c2667446df 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go @@ -5,6 +5,8 @@ // Package demangle defines functions that demangle GCC/LLVM C++ symbol names. // This package recognizes names that were mangled according to the C++ ABI // defined at http://codesourcery.com/cxx-abi/. +// +// Most programs will want to call Filter or ToString. package demangle import ( @@ -45,7 +47,7 @@ func Filter(name string, options ...Option) string { return ret } -// ToString demangles a C++ symbol name, returning human-readable C++ +// ToString demangles a C++ symbol name, returning a human-readable C++ // name or an error. // If the name does not appear to be a C++ symbol name at all, the // error will be ErrNotMangledName. @@ -183,6 +185,7 @@ type state struct { off int // offset of str within original string subs substitutions // substitutions templates []*Template // templates being processed + inLambda int // number of lambdas being parsed } // copy returns a copy of the current state. @@ -310,15 +313,42 @@ func (st *state) encoding(params bool, local forLocalNameType) AST { if mwq != nil { check = mwq.Method } - template, _ := check.(*Template) + + var template *Template + switch check := check.(type) { + case *Template: + template = check + case *Qualified: + if check.LocalName { + n := check.Name + if nmwq, ok := n.(*MethodWithQualifiers); ok { + n = nmwq.Method + } + template, _ = n.(*Template) + } + } + var oldInLambda int if template != nil { st.templates = append(st.templates, template) + oldInLambda = st.inLambda + st.inLambda = 0 + } + + // Checking for the enable_if attribute here is what the LLVM + // demangler does. This is not very general but perhaps it is + // sufficent. + const enableIfPrefix = "Ua9enable_ifI" + var enableIfArgs []AST + if strings.HasPrefix(st.str, enableIfPrefix) { + st.advance(len(enableIfPrefix) - 1) + enableIfArgs = st.templateArgs() } ft := st.bareFunctionType(hasReturnType(a)) if template != nil { st.templates = st.templates[:len(st.templates)-1] + st.inLambda = oldInLambda } ft = simplify(ft) @@ -349,13 +379,24 @@ func (st *state) encoding(params bool, local forLocalNameType) AST { } } - return &Typed{Name: a, Type: ft} + r := AST(&Typed{Name: a, Type: ft}) + + if len(enableIfArgs) > 0 { + r = &EnableIf{Type: r, Args: enableIfArgs} + } + + return r } // hasReturnType returns whether the mangled form of a will have a // return type. func hasReturnType(a AST) bool { switch a := a.(type) { + case *Qualified: + if a.LocalName { + return hasReturnType(a.Name) + } + return false case *Template: return !isCDtorConversion(a.Name) case *TypeWithQualifiers: @@ -481,7 +522,7 @@ func (st *state) nestedName() AST { q := st.cvQualifiers() r := st.refQualifier() a := st.prefix() - if len(q) > 0 || r != "" { + if q != nil || r != "" { a = &MethodWithQualifiers{Method: a, Qualifiers: q, RefQualifier: r} } if len(st.str) == 0 || st.str[0] != 'E' { @@ -608,6 +649,29 @@ func (st *state) prefix() AST { // gives appropriate output. st.advance(1) continue + case 'J': + // It appears that in some cases clang + // can emit a J for a template arg + // without the expected I. I don't + // know when this happens, but I've + // seen it in some large C++ programs. + if a == nil { + st.fail("unexpected template arguments") + } + var args []AST + for len(st.str) == 0 || st.str[0] != 'E' { + arg := st.templateArg() + args = append(args, arg) + } + st.advance(1) + tmpl := &Template{Name: a, Args: args} + if isCast { + st.setTemplate(a, tmpl) + st.clearTemplateArgs(args) + isCast = false + } + a = nil + next = tmpl default: st.fail("unrecognized letter in prefix") } @@ -754,19 +818,26 @@ var operators = map[string]operator{ "ad": {"&", 1}, "an": {"&", 2}, "at": {"alignof ", 1}, + "aw": {"co_await ", 1}, "az": {"alignof ", 1}, "cc": {"const_cast", 2}, "cl": {"()", 2}, + // cp is not in the ABI but is used by clang "when the call + // would use ADL except for being parenthesized." + "cp": {"()", 2}, "cm": {",", 2}, "co": {"~", 1}, "dV": {"/=", 2}, + "dX": {"[...]=", 3}, "da": {"delete[] ", 1}, "dc": {"dynamic_cast", 2}, "de": {"*", 1}, + "di": {"=", 2}, "dl": {"delete ", 1}, "ds": {".*", 2}, "dt": {".", 2}, "dv": {"/", 2}, + "dx": {"]=", 2}, "eO": {"^=", 2}, "eo": {"^", 2}, "eq": {"==", 2}, @@ -808,7 +879,10 @@ var operators = map[string]operator{ "rc": {"reinterpret_cast", 2}, "rm": {"%", 2}, "rs": {">>", 2}, + "sP": {"sizeof...", 1}, + "sZ": {"sizeof...", 1}, "sc": {"static_cast", 2}, + "ss": {"<=>", 2}, "st": {"sizeof ", 1}, "sz": {"sizeof ", 1}, "tr": {"throw", 0}, @@ -928,6 +1002,7 @@ func (st *state) javaResource() AST { // ::= TT // ::= TI // ::= TS +// ::= TA // ::= GV <(object) name> // ::= T <(base) encoding> // ::= Tc <(base) encoding> @@ -961,6 +1036,9 @@ func (st *state) specialName() AST { case 'S': t := st.demangleType(false) return &Special{Prefix: "typeinfo name for ", Val: t} + case 'A': + t := st.templateArg() + return &Special{Prefix: "template parameter object for ", Val: t} case 'h': st.callOffset('h') v := st.encoding(true, notForLocalName) @@ -1138,7 +1216,7 @@ func (st *state) demangleType(isCast bool) AST { addSubst := true q := st.cvQualifiers() - if len(q) > 0 { + if q != nil { if len(st.str) == 0 { st.fail("expected type") } @@ -1159,7 +1237,7 @@ func (st *state) demangleType(isCast bool) AST { if btype, ok := builtinTypes[st.str[0]]; ok { ret = &BuiltinType{Name: btype} st.advance(1) - if len(q) > 0 { + if q != nil { ret = &TypeWithQualifiers{Base: ret, Qualifiers: q} st.subs.add(ret) } @@ -1286,6 +1364,8 @@ func (st *state) demangleType(isCast bool) AST { case 'a': ret = &Name{Name: "auto"} + case 'c': + ret = &Name{Name: "decltype(auto)"} case 'f': ret = &BuiltinType{Name: "decimal32"} @@ -1295,6 +1375,8 @@ func (st *state) demangleType(isCast bool) AST { ret = &BuiltinType{Name: "decimal128"} case 'h': ret = &BuiltinType{Name: "half"} + case 'u': + ret = &BuiltinType{Name: "char8_t"} case 's': ret = &BuiltinType{Name: "char16_t"} case 'i': @@ -1343,7 +1425,7 @@ func (st *state) demangleType(isCast bool) AST { } } - if len(q) > 0 { + if q != nil { if _, ok := ret.(*FunctionType); ok { ret = &MethodWithQualifiers{Method: ret, Qualifiers: q, RefQualifier: ""} } else if mwq, ok := ret.(*MethodWithQualifiers); ok { @@ -1433,17 +1515,32 @@ func (st *state) demangleCastTemplateArgs(tp AST, addSubst bool) AST { } // mergeQualifiers merges two qualifer lists into one. -func mergeQualifiers(q1, q2 Qualifiers) Qualifiers { - m := make(map[string]bool) - for _, qual := range q1 { - m[qual] = true +func mergeQualifiers(q1AST, q2AST AST) AST { + if q1AST == nil { + return q2AST } - for _, qual := range q2 { - if !m[qual] { - q1 = append(q1, qual) - m[qual] = true + if q2AST == nil { + return q1AST + } + q1 := q1AST.(*Qualifiers) + m := make(map[string]bool) + for _, qualAST := range q1.Qualifiers { + qual := qualAST.(*Qualifier) + if len(qual.Exprs) == 0 { + m[qual.Name] = true } } + rq := q1.Qualifiers + for _, qualAST := range q2AST.(*Qualifiers).Qualifiers { + qual := qualAST.(*Qualifier) + if len(qual.Exprs) > 0 { + rq = append(rq, qualAST) + } else if !m[qual.Name] { + rq = append(rq, qualAST) + m[qual.Name] = true + } + } + q1.Qualifiers = rq return q1 } @@ -1456,20 +1553,51 @@ var qualifiers = map[byte]string{ } // ::= [r] [V] [K] -func (st *state) cvQualifiers() Qualifiers { - var q Qualifiers +func (st *state) cvQualifiers() AST { + var q []AST +qualLoop: for len(st.str) > 0 { if qv, ok := qualifiers[st.str[0]]; ok { - q = append([]string{qv}, q...) + qual := &Qualifier{Name: qv} + q = append([]AST{qual}, q...) st.advance(1) - } else if len(st.str) > 1 && st.str[:2] == "Dx" { - q = append([]string{"transaction_safe"}, q...) - st.advance(2) + } else if len(st.str) > 1 && st.str[0] == 'D' { + var qual AST + switch st.str[1] { + case 'x': + qual = &Qualifier{Name: "transaction_safe"} + st.advance(2) + case 'o': + qual = &Qualifier{Name: "noexcept"} + st.advance(2) + case 'O': + st.advance(2) + expr := st.expression() + if len(st.str) == 0 || st.str[0] != 'E' { + st.fail("expected E after computed noexcept expression") + } + st.advance(1) + qual = &Qualifier{Name: "noexcept", Exprs: []AST{expr}} + case 'w': + st.advance(2) + parmlist := st.parmlist() + if len(st.str) == 0 || st.str[0] != 'E' { + st.fail("expected E after throw parameter list") + } + st.advance(1) + qual = &Qualifier{Name: "throw", Exprs: parmlist} + default: + break qualLoop + } + q = append([]AST{qual}, q...) } else { break } } - return q + if len(q) == 0 { + return nil + } + return &Qualifiers{Qualifiers: q} } // ::= R @@ -1677,7 +1805,7 @@ func (st *state) compactNumber() int { // whatever the template parameter would be expanded to here. We sort // this out in substitution and simplify. func (st *state) templateParam() AST { - if len(st.templates) == 0 { + if len(st.templates) == 0 && st.inLambda == 0 { st.fail("template parameter not in scope of template") } off := st.off @@ -1685,6 +1813,13 @@ func (st *state) templateParam() AST { st.checkChar('T') n := st.compactNumber() + if st.inLambda > 0 { + // g++ mangles lambda auto params as template params. + // Apparently we can't encounter a template within a lambda. + // See https://gcc.gnu.org/PR78252. + return &LambdaAuto{Index: n} + } + template := st.templates[len(st.templates)-1] if template == nil { @@ -1723,6 +1858,10 @@ func (st *state) setTemplate(a AST, tmpl *Template) { } a.Template = tmpl return false + case *Closure: + // There are no template params in closure types. + // https://gcc.gnu.org/PR78252. + return false default: for _, v := range seen { if v == a { @@ -1812,12 +1951,60 @@ func (st *state) exprList(stop byte) AST { // ::= <(unary) operator-name> // ::= <(binary) operator-name> // ::= <(trinary) operator-name> +// ::= pp_ +// ::= mm_ // ::= cl + E +// ::= cl + E +// ::= cv +// ::= cv _ * E +// ::= tl * E +// ::= il * E +// ::= [gs] nw * _ E +// ::= [gs] nw * _ +// ::= [gs] na * _ E +// ::= [gs] na * _ +// ::= [gs] dl +// ::= [gs] da +// ::= dc +// ::= sc +// ::= cc +// ::= rc +// ::= ti +// ::= te // ::= st +// ::= sz +// ::= at +// ::= az +// ::= nx // ::= -// ::= sr -// ::= sr +// ::= +// ::= dt +// ::= pt +// ::= ds +// ::= sZ +// ::= sZ +// ::= sP * E +// ::= sp +// ::= fl +// ::= fr +// ::= fL +// ::= fR +// ::= tw +// ::= tr +// ::= // ::= +// +// ::= fp _ +// ::= fp +// ::= fL p _ +// ::= fL p +// ::= fpT +// +// ::= +// ::= di +// ::= dx +// ::= dX +// func (st *state) expression() AST { if len(st.str) == 0 { st.fail("expected expression") @@ -1827,61 +2014,7 @@ func (st *state) expression() AST { } else if st.str[0] == 'T' { return st.templateParam() } else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'r' { - st.advance(2) - if len(st.str) == 0 { - st.fail("expected unresolved type") - } - switch st.str[0] { - case 'T', 'D', 'S': - t := st.demangleType(false) - n := st.baseUnresolvedName() - n = &Qualified{Scope: t, Name: n, LocalName: false} - if len(st.str) > 0 && st.str[0] == 'I' { - args := st.templateArgs() - n = &Template{Name: n, Args: args} - } - return n - default: - var s AST - if st.str[0] == 'N' { - st.advance(1) - s = st.demangleType(false) - } - for len(st.str) == 0 || st.str[0] != 'E' { - // GCC does not seem to follow the ABI here. - // It can emit type/name without an 'E'. - if s != nil && len(st.str) > 0 && !isDigit(st.str[0]) { - if q, ok := s.(*Qualified); ok { - a := q.Scope - if t, ok := a.(*Template); ok { - st.subs.add(t.Name) - st.subs.add(t) - } else { - st.subs.add(a) - } - return s - } - } - n := st.sourceName() - if len(st.str) > 0 && st.str[0] == 'I' { - st.subs.add(n) - args := st.templateArgs() - n = &Template{Name: n, Args: args} - } - if s == nil { - s = n - } else { - s = &Qualified{Scope: s, Name: n, LocalName: false} - } - st.subs.add(s) - } - if s == nil { - st.fail("missing scope in unresolved name") - } - st.advance(1) - n := st.baseUnresolvedName() - return &Qualified{Scope: s, Name: n, LocalName: false} - } + return st.unresolvedName() } else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'p' { st.advance(2) e := st.expression() @@ -1911,9 +2044,25 @@ func (st *state) expression() AST { st.advance(1) return &FunctionParam{Index: 0} } else { + // We can see qualifiers here, but we don't + // include them in the demangled string. + st.cvQualifiers() index := st.compactNumber() return &FunctionParam{Index: index + 1} } + } else if st.str[0] == 'f' && len(st.str) > 2 && st.str[1] == 'L' && isDigit(st.str[2]) { + st.advance(2) + // We don't include the scope count in the demangled string. + st.number() + if len(st.str) == 0 || st.str[0] != 'p' { + st.fail("expected p after function parameter scope count") + } + st.advance(1) + // We can see qualifiers here, but we don't include them + // in the demangled string. + st.cvQualifiers() + index := st.compactNumber() + return &FunctionParam{Index: index + 1} } else if isDigit(st.str[0]) || (st.str[0] == 'o' && len(st.str) > 1 && st.str[1] == 'n') { if st.str[0] == 'o' { // Skip operator function ID. @@ -1975,13 +2124,15 @@ func (st *state) expression() AST { left, _ = st.operatorName(true) right = st.expression() return &Fold{Left: code[1] == 'l', Op: left, Arg1: right, Arg2: nil} + } else if code == "di" { + left, _ = st.unqualifiedName() } else { left = st.expression() } - if code == "cl" { + if code == "cl" || code == "cp" { right = st.exprList('E') } else if code == "dt" || code == "pt" { - right, _ = st.unqualifiedName() + right = st.unresolvedName() if len(st.str) > 0 && st.str[0] == 'I' { args := st.templateArgs() right = &Template{Name: right, Args: args} @@ -2034,6 +2185,82 @@ func (st *state) expression() AST { } } +// ::= [gs] +// ::= sr +// ::= srN + E +// ::= [gs] sr + E +func (st *state) unresolvedName() AST { + if len(st.str) >= 2 && st.str[:2] == "gs" { + st.advance(2) + n := st.unresolvedName() + return &Unary{ + Op: &Operator{Name: "::"}, + Expr: n, + Suffix: false, + SizeofType: false, + } + } else if len(st.str) >= 2 && st.str[:2] == "sr" { + st.advance(2) + if len(st.str) == 0 { + st.fail("expected unresolved type") + } + switch st.str[0] { + case 'T', 'D', 'S': + t := st.demangleType(false) + n := st.baseUnresolvedName() + n = &Qualified{Scope: t, Name: n, LocalName: false} + if len(st.str) > 0 && st.str[0] == 'I' { + args := st.templateArgs() + n = &Template{Name: n, Args: args} + st.subs.add(n) + } + return n + default: + var s AST + if st.str[0] == 'N' { + st.advance(1) + s = st.demangleType(false) + } + for len(st.str) == 0 || st.str[0] != 'E' { + // GCC does not seem to follow the ABI here. + // It can emit type/name without an 'E'. + if s != nil && len(st.str) > 0 && !isDigit(st.str[0]) { + if q, ok := s.(*Qualified); ok { + a := q.Scope + if t, ok := a.(*Template); ok { + st.subs.add(t.Name) + st.subs.add(t) + } else { + st.subs.add(a) + } + return s + } + } + n := st.sourceName() + if len(st.str) > 0 && st.str[0] == 'I' { + st.subs.add(n) + args := st.templateArgs() + n = &Template{Name: n, Args: args} + } + if s == nil { + s = n + } else { + s = &Qualified{Scope: s, Name: n, LocalName: false} + } + st.subs.add(s) + } + if s == nil { + st.fail("missing scope in unresolved name") + } + st.advance(1) + n := st.baseUnresolvedName() + return &Qualified{Scope: s, Name: n, LocalName: false} + } + } else { + return st.baseUnresolvedName() + } +} + // ::= // ::= on // ::= on @@ -2099,7 +2326,14 @@ func (st *state) exprPrimary() AST { st.advance(1) } if len(st.str) > 0 && st.str[0] == 'E' { - st.fail("missing literal value") + if bt, ok := t.(*BuiltinType); ok && bt.Name == "decltype(nullptr)" { + // A nullptr should not have a value. + // We accept one if present because GCC + // used to generate one. + // https://gcc.gnu.org/PR91979. + } else { + st.fail("missing literal value") + } } i := 0 for len(st.str) > i && st.str[i] != 'E' { @@ -2116,17 +2350,29 @@ func (st *state) exprPrimary() AST { return ret } -// ::= _ <(non-negative) number> +// ::= _ <(non-negative) number> (when number < 10) +// __ <(non-negative) number> _ (when number >= 10) func (st *state) discriminator(a AST) AST { if len(st.str) == 0 || st.str[0] != '_' { return a } off := st.off st.advance(1) + trailingUnderscore := false + if len(st.str) > 0 && st.str[0] == '_' { + st.advance(1) + trailingUnderscore = true + } d := st.number() if d < 0 { st.failEarlier("invalid negative discriminator", st.off-off) } + if trailingUnderscore && d >= 10 { + if len(st.str) == 0 || st.str[0] != '_' { + st.fail("expected _ after discriminator >= 10") + } + st.advance(1) + } // We don't currently print out the discriminator, so we don't // save it. return a @@ -2136,15 +2382,15 @@ func (st *state) discriminator(a AST) AST { func (st *state) closureTypeName() AST { st.checkChar('U') st.checkChar('l') + st.inLambda++ types := st.parmlist() + st.inLambda-- if len(st.str) == 0 || st.str[0] != 'E' { st.fail("expected E after closure type name") } st.advance(1) num := st.compactNumber() - ret := &Closure{Types: types, Num: num} - st.subs.add(ret) - return ret + return &Closure{Types: types, Num: num} } // ::= Ut [ ] _ @@ -2295,31 +2541,92 @@ func (st *state) substitution(forPrefix bool) AST { // We need to update any references to template // parameters to refer to the currently active // template. + + // When copying a Typed we may need to adjust + // the templates. + copyTemplates := st.templates + var oldInLambda []int + + // pushTemplate is called from skip, popTemplate from copy. + pushTemplate := func(template *Template) { + copyTemplates = append(copyTemplates, template) + oldInLambda = append(oldInLambda, st.inLambda) + st.inLambda = 0 + } + popTemplate := func() { + copyTemplates = copyTemplates[:len(copyTemplates)-1] + st.inLambda = oldInLambda[len(oldInLambda)-1] + oldInLambda = oldInLambda[:len(oldInLambda)-1] + } + copy := func(a AST) AST { - tp, ok := a.(*TemplateParam) - if !ok { + var index int + switch a := a.(type) { + case *Typed: + // Remove the template added in skip. + if _, ok := a.Name.(*Template); ok { + popTemplate() + } + return nil + case *Closure: + // Undo the decrement in skip. + st.inLambda-- + return nil + case *TemplateParam: + index = a.Index + case *LambdaAuto: + // A lambda auto parameter is represented + // as a template parameter, so we may have + // to change back when substituting. + index = a.Index + default: return nil } - if len(st.templates) == 0 { + if st.inLambda > 0 { + if _, ok := a.(*LambdaAuto); ok { + return nil + } + return &LambdaAuto{Index: index} + } + var template *Template + if len(copyTemplates) > 0 { + template = copyTemplates[len(copyTemplates)-1] + } else if rt, ok := ret.(*Template); ok { + // At least with clang we can see a template + // to start, and sometimes we need to refer + // to it. There is probably something wrong + // here. + template = rt + } else { st.failEarlier("substituted template parameter not in scope of template", dec) } - template := st.templates[len(st.templates)-1] if template == nil { // This template parameter is within // the scope of a cast operator. - return &TemplateParam{Index: tp.Index, Template: nil} + return &TemplateParam{Index: index, Template: nil} } - if tp.Index >= len(template.Args) { - st.failEarlier(fmt.Sprintf("substituted template index out of range (%d >= %d)", tp.Index, len(template.Args)), dec) + if index >= len(template.Args) { + st.failEarlier(fmt.Sprintf("substituted template index out of range (%d >= %d)", index, len(template.Args)), dec) } - return &TemplateParam{Index: tp.Index, Template: template} + return &TemplateParam{Index: index, Template: template} } var seen []AST skip := func(a AST) bool { - if _, ok := a.(*Typed); ok { - return true + switch a := a.(type) { + case *Typed: + if template, ok := a.Name.(*Template); ok { + // This template is removed in copy. + pushTemplate(template) + } + return false + case *Closure: + // This is decremented in copy. + st.inLambda++ + return false + case *TemplateParam, *LambdaAuto: + return false } for _, v := range seen { if v == a { @@ -2329,6 +2636,7 @@ func (st *state) substitution(forPrefix bool) AST { seen = append(seen, a) return false } + if c := ret.Copy(copy, skip); c != nil { return c } @@ -2351,6 +2659,7 @@ func (st *state) substitution(forPrefix bool) AST { if len(st.str) > 0 && st.str[0] == 'B' { a = st.taggedName(a) + st.subs.add(a) } return a diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 21bd6bfe48..48aac279e9 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/google/pprof v0.0.0-20201007051231-1066cbb265c7 +# github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2 ## explicit github.com/google/pprof/driver github.com/google/pprof/internal/binutils @@ -15,8 +15,7 @@ github.com/google/pprof/profile github.com/google/pprof/third_party/d3 github.com/google/pprof/third_party/d3flamegraph github.com/google/pprof/third_party/svgpan -# github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 -## explicit +# github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 github.com/ianlancetaylor/demangle # golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff ## explicit From 4de4480dc34fbe4f7b0ed97eada26aef7a7e2337 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 4 Dec 2020 01:46:59 +0100 Subject: [PATCH 148/212] doc/go1.16: cleanup crypto release notes For #40700 Fixes #42897 Change-Id: Id3b87841a899818d6939dcc3edbaaa0bc183e913 Reviewed-on: https://go-review.googlesource.com/c/go/+/275313 Trust: Filippo Valsorda Trust: Roland Shoemaker Reviewed-by: Roland Shoemaker --- doc/go1.16.html | 108 ++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 55 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index ce93ab349e..fb7022b354 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -440,9 +440,10 @@ Do not send CLs removing the interior tags from such phrases.
crypto/hmac

- New will now panic if separate calls to - the hash generation function fail to return new values. Previously, the - behavior was undefined and invalid outputs were sometimes generated. + New will now panic if + separate calls to the hash generation function fail to return new values. + Previously, the behavior was undefined and invalid outputs were sometimes + generated.

@@ -450,56 +451,49 @@ Do not send CLs removing the interior tags from such phrases.
crypto/tls

- I/O operations on closing or closed TLS connections can now be detected using - the new ErrClosed error. A typical use - would be errors.Is(err, net.ErrClosed). In earlier releases - the only way to reliably detect this case was to match the string returned - by the Error method with "tls: use of closed connection". + I/O operations on closing or closed TLS connections can now be detected + using the new net.ErrClosed + error. A typical use would be errors.Is(err, net.ErrClosed).

- A default deadline is set in Close - before sending the close notify alert, in order to prevent blocking + A default write deadline is now set in + Conn.Close + before sending the "close notify" alert, in order to prevent blocking indefinitely.

- (*Conn).HandshakeContext was added to - allow the user to control cancellation of an in-progress TLS Handshake. - The context provided is propagated into the - ClientHelloInfo - and CertificateRequestInfo - structs and accessible through the new - (*ClientHelloInfo).Context - and - - (*CertificateRequestInfo).Context - methods respectively. Canceling the context after the handshake has finished - has no effect. + The new Conn.HandshakeContext + method allows cancellation of an in-progress handshake. The provided + context is accessible through the new + ClientHelloInfo.Context + and + CertificateRequestInfo.Context methods. Canceling the + context after the handshake has finished has no effect.

- Clients now ensure that the server selects + Clients now return a handshake error if the server selects - an ALPN protocol from + an ALPN protocol that was not in the list advertised by the client.

- TLS servers will now prefer other AEAD cipher suites (such as ChaCha20Poly1305) + Servers will now prefer other available AEAD cipher suites (such as ChaCha20Poly1305) over AES-GCM cipher suites if either the client or server doesn't have AES hardware - support, unless the application set both - Config.PreferServerCipherSuites + support, unless both + Config.PreferServerCipherSuites and Config.CipherSuites - or there are no other AEAD cipher suites supported. - The client is assumed not to have AES hardware support if it does not signal a - preference for AES-GCM cipher suites. + are set. The client is assumed not to have AES hardware support if it does + not signal a preference for AES-GCM cipher suites.

- Config.Clone now returns - a nil *Config if the source is nil, rather than panicking. + Config.Clone now + returns nil if the receiver is nil, rather than panicking.

@@ -514,25 +508,26 @@ Do not send CLs removing the interior tags from such phrases.

- ParseCertificate and - CreateCertificate both - now enforce string encoding restrictions for the fields DNSNames, - EmailAddresses, and URIs. These fields can only - contain strings with characters within the ASCII range. + ParseCertificate and + CreateCertificate + now enforce string encoding restrictions for the DNSNames, + EmailAddresses, and URIs fields. These fields + can only contain strings with characters within the ASCII range.

- CreateCertificate now - verifies the generated certificate's signature using the signer's - public key. If the signature is invalid, an error is returned, instead - of a malformed certificate. + CreateCertificate + now verifies the generated certificate's signature using the signer's + public key. If the signature is invalid, an error is returned, instead of + a malformed certificate.

A number of additional fields have been added to the - CertificateRequest type. - These fields are now parsed in ParseCertificateRequest - and marshalled in CreateCertificateRequest. + CertificateRequest type. + These fields are now parsed in + ParseCertificateRequest and marshalled in + CreateCertificateRequest.

@@ -548,7 +543,9 @@ Do not send CLs removing the interior tags from such phrases.

- TODO: https://golang.org/cl/262343: add Unwrap to SystemRootsError + The new SystemRootsError.Unwrap + method allows accessing the Err + field through the errors package functions.

@@ -556,11 +553,11 @@ Do not send CLs removing the interior tags from such phrases.
encoding/asn1

- Unmarshal and - UnmarshalWithParams - now return an error instead of panic when the argument is not + Unmarshal and + UnmarshalWithParams + now return an error instead of panicking when the argument is not a pointer or is nil. This change matches the behavior of other - encoding packages such as encoding/json. + encoding packages such as encoding/json.

@@ -693,15 +690,16 @@ Do not send CLs removing the interior tags from such phrases.

- Cookies set with SameSiteDefaultMode now behave according to the current - spec (no attribute is set) instead of generating a SameSite key without a value. + Cookies set with SameSiteDefaultMode + now behave according to the current spec (no attribute is set) instead of + generating a SameSite key without a value.

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

From be9379f8a8e2bfd924966020d177552d01833fdb Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 29 Nov 2020 13:33:37 +0100 Subject: [PATCH 149/212] syscall: correct CertOpenStore to expect a 0 return value on failure According to [1], this function returns NULL when it errors, rather than INVALID_HANDLE_VALUE, which other Win32 functions return. This was pointed out in CL 273446 for the x/sys package, and this patch here cleans it up for the syscall package and updates the vendored x/sys package using the usual `go get/go mod vendor` dance. The function is currently in use by crypto/x509/root_windows.go, which calls CertOpenStore(CERT_STORE_PROV_MEMORY), which I assume can fail under OOM or other weird conditions. Quick reversing indicates that [1] is correct, as there's a `xor eax, eax` in the error paths of the function just before jumping to the epilogue. [1] https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certopenstore#return-value Change-Id: I77c0b0319c13313212f8710785252c494da56ed5 Reviewed-on: https://go-review.googlesource.com/c/go/+/273827 Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda Trust: Jason A. Donenfeld Trust: Alex Brainman --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../golang.org/x/sys/unix/asm_aix_ppc64.s | 2 +- .../golang.org/x/sys/unix/asm_darwin_386.s | 2 +- .../golang.org/x/sys/unix/asm_darwin_amd64.s | 2 +- .../golang.org/x/sys/unix/asm_darwin_arm.s | 2 +- .../golang.org/x/sys/unix/asm_darwin_arm64.s | 2 +- .../x/sys/unix/asm_dragonfly_amd64.s | 2 +- .../golang.org/x/sys/unix/asm_freebsd_386.s | 2 +- .../golang.org/x/sys/unix/asm_freebsd_amd64.s | 2 +- .../golang.org/x/sys/unix/asm_freebsd_arm.s | 2 +- .../golang.org/x/sys/unix/asm_freebsd_arm64.s | 2 +- .../golang.org/x/sys/unix/asm_linux_386.s | 2 +- .../golang.org/x/sys/unix/asm_linux_amd64.s | 2 +- .../golang.org/x/sys/unix/asm_linux_arm.s | 2 +- .../golang.org/x/sys/unix/asm_linux_arm64.s | 2 +- .../golang.org/x/sys/unix/asm_linux_mips64x.s | 2 +- .../golang.org/x/sys/unix/asm_linux_mipsx.s | 2 +- .../golang.org/x/sys/unix/asm_linux_ppc64x.s | 2 +- .../golang.org/x/sys/unix/asm_linux_riscv64.s | 2 +- .../golang.org/x/sys/unix/asm_linux_s390x.s | 2 +- .../golang.org/x/sys/unix/asm_netbsd_386.s | 2 +- .../golang.org/x/sys/unix/asm_netbsd_amd64.s | 2 +- .../golang.org/x/sys/unix/asm_netbsd_arm.s | 2 +- .../golang.org/x/sys/unix/asm_netbsd_arm64.s | 2 +- .../golang.org/x/sys/unix/asm_openbsd_386.s | 2 +- .../golang.org/x/sys/unix/asm_openbsd_amd64.s | 2 +- .../golang.org/x/sys/unix/asm_openbsd_arm.s | 2 +- .../golang.org/x/sys/unix/asm_openbsd_arm64.s | 2 +- .../x/sys/unix/asm_openbsd_mips64.s | 2 +- .../golang.org/x/sys/unix/asm_solaris_amd64.s | 2 +- .../golang.org/x/sys/unix/endian_big.go | 2 +- .../golang.org/x/sys/unix/endian_little.go | 2 +- .../vendor/golang.org/x/sys/unix/mkerrors.sh | 2 + .../x/sys/unix/syscall_darwin.1_13.go | 1 - .../x/sys/unix/syscall_dragonfly.go | 13 ++ .../golang.org/x/sys/unix/syscall_linux.go | 87 +++++++++-- .../x/sys/unix/syscall_linux_amd64_gc.go | 2 +- .../golang.org/x/sys/unix/syscall_linux_gc.go | 2 +- .../x/sys/unix/syscall_linux_gc_386.go | 2 +- .../x/sys/unix/syscall_linux_gc_arm.go | 2 +- .../golang.org/x/sys/unix/syscall_unix_gc.go | 2 +- .../x/sys/unix/syscall_unix_gc_ppc64x.go | 2 +- .../golang.org/x/sys/unix/zerrors_linux.go | 6 + .../x/sys/unix/zsyscall_aix_ppc64_gc.go | 2 +- .../x/sys/unix/zsyscall_darwin_386.1_13.go | 2 - .../x/sys/unix/zsyscall_darwin_386.go | 142 ------------------ .../x/sys/unix/zsyscall_darwin_amd64.1_13.go | 2 - .../x/sys/unix/zsyscall_darwin_amd64.go | 142 ------------------ .../x/sys/unix/zsyscall_darwin_arm.1_13.go | 2 - .../x/sys/unix/zsyscall_darwin_arm.go | 141 ----------------- .../x/sys/unix/zsyscall_darwin_arm64.1_13.go | 2 - .../x/sys/unix/zsyscall_darwin_arm64.go | 142 ------------------ .../x/sys/unix/zsyscall_dragonfly_amd64.go | 10 ++ .../x/sys/unix/ztypes_darwin_386.go | 1 + .../x/sys/unix/ztypes_darwin_amd64.go | 1 + .../x/sys/unix/ztypes_darwin_arm.go | 1 + .../x/sys/unix/ztypes_darwin_arm64.go | 1 + .../golang.org/x/sys/unix/ztypes_linux.go | 18 +++ .../golang.org/x/sys/windows/dll_windows.go | 3 +- .../x/sys/windows/security_windows.go | 14 +- .../golang.org/x/sys/windows/service.go | 6 + .../x/sys/windows/setupapierrors_windows.go | 100 ++++++++++++ .../x/sys/windows/syscall_windows.go | 8 +- .../golang.org/x/sys/windows/types_windows.go | 48 ++++++ .../x/sys/windows/zsyscall_windows.go | 103 ++++++++++++- src/cmd/vendor/modules.txt | 2 +- src/go.mod | 2 +- src/go.sum | 4 +- src/syscall/syscall_windows.go | 2 +- src/syscall/zsyscall_windows.go | 2 +- .../golang.org/x/sys/cpu/asm_aix_ppc64.s | 2 +- src/vendor/golang.org/x/sys/cpu/cpu_arm64.s | 2 +- .../golang.org/x/sys/cpu/cpu_gc_arm64.go | 2 +- .../golang.org/x/sys/cpu/cpu_gc_s390x.go | 2 +- src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 2 +- src/vendor/golang.org/x/sys/cpu/cpu_s390x.s | 2 +- src/vendor/golang.org/x/sys/cpu/cpu_x86.s | 2 +- .../x/sys/cpu/syscall_aix_ppc64_gc.go | 2 +- src/vendor/modules.txt | 2 +- 80 files changed, 455 insertions(+), 655 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 46ec54b5a2..98ef23d61b 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -7,6 +7,6 @@ require ( golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/mod v0.4.0 - golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 // indirect + golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect golang.org/x/tools v0.0.0-20201110201400-7099162a900a ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index b3e4598bd1..70f14f6640 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -25,8 +25,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 h1:Qo9oJ566/Sq7N4hrGftVXs8GI2CXBCuOd4S2wHE/e0M= -golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s index 06f84b8555..6b4027b33f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_386.s index 8a7278319e..8a06b87d71 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_386.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_386.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s index 6321421f27..f2397fde55 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm.s index 333242d506..c9e6b6fc8b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc // +build arm,darwin #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s index 97e0174371..89843f8f4b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc // +build arm64,darwin #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s index 603dd5728c..27674e1caf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_386.s index c9a0a26015..49f0ac2364 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_386.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_386.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s index 35172477c8..f2dfc57b83 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s index 9227c875bf..6d740db2c0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s index d9318cbf03..a8f5a29b35 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_386.s index 448bebbb59..0655ecbfbb 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_386.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_386.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_amd64.s index c6468a9588..bc3fb6ac3e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_amd64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm.s index cf0f3575c1..55b13c7ba4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm64.s index afe6fdf6b1..22a83d8e3f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_arm64.s @@ -4,7 +4,7 @@ // +build linux // +build arm64 -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s index ab9d63831a..dc222b90ce 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s @@ -4,7 +4,7 @@ // +build linux // +build mips64 mips64le -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s index 99e5399045..d333f13cff 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s @@ -4,7 +4,7 @@ // +build linux // +build mips mipsle -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s index 88f7125578..459a629c27 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s @@ -4,7 +4,7 @@ // +build linux // +build ppc64 ppc64le -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s index 3cfefed2ec..04d38497c6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build riscv64,!gccgo +// +build riscv64,gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_s390x.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_s390x.s index a5a863c6bd..cc303989e1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_s390x.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_s390x.s @@ -4,7 +4,7 @@ // +build s390x // +build linux -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_386.s index 48bdcd7632..ae7b498d50 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_386.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_386.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s index 2ede05c72f..e57367c17a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s index e8928571c4..d7da175e1a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s index 6f98ba5a37..e7cbe1904c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_386.s index 00576f3c83..2f00b0310f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_386.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_386.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s index 790ef77f86..07632c99ce 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s index 469bfa1003..73e997320f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s index 0cedea3d39..c47302aa46 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s index 567a4763c8..47c93fcb6c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s index ded8260f3e..1f2c755a72 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/endian_big.go b/src/cmd/vendor/golang.org/x/sys/unix/endian_big.go index 5e9269063f..86781eac22 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/endian_big.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/endian_big.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // -// +build ppc64 s390x mips mips64 +// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64 package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/endian_little.go b/src/cmd/vendor/golang.org/x/sys/unix/endian_little.go index bcdb5d30eb..8822d8541f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/endian_little.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/endian_little.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // -// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le riscv64 +// +build 386 amd64 amd64p32 alpha arm arm64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh index 0c9a5c44bb..c0f9f2d523 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -225,6 +225,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -561,6 +562,7 @@ ccflags="$@" $2 ~ /^CRYPTO_/ || $2 ~ /^TIPC_/ || $2 ~ /^DEVLINK_/ || + $2 ~ /^LWTUNNEL_IP/ || $2 !~ "WMESGLEN" && $2 ~ /^W[A-Z0-9]+$/ || $2 ~/^PPPIOC/ || diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go index dc0befee37..ee852f1abc 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go @@ -26,7 +26,6 @@ func fdopendir(fd int) (dir uintptr, err error) { func libc_fdopendir_trampoline() -//go:linkname libc_fdopendir libc_fdopendir //go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib" func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 842ab5acde..a4f2944a24 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -105,6 +105,19 @@ func Pipe(p []int) (err error) { return } +//sysnb pipe2(p *[2]_C_int, flags int) (err error) + +func Pipe2(p []int, flags int) error { + if len(p) != 2 { + return EINVAL + } + var pp [2]_C_int + err := pipe2(&pp, flags) + p[0] = int(pp[0]) + p[1] = int(pp[1]) + return err +} + //sys extpread(fd int, p []byte, flags int, offset int64) (n int, err error) func Pread(fd int, p []byte, offset int64) (n int, err error) { return extpread(fd, p, 0, offset) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go index 84a9e5277a..28be1306ec 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -641,6 +641,36 @@ func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) { return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil } +// SockaddrCANJ1939 implements the Sockaddr interface for AF_CAN using J1939 +// protocol (https://en.wikipedia.org/wiki/SAE_J1939). For more information +// on the purposes of the fields, check the official linux kernel documentation +// available here: https://www.kernel.org/doc/Documentation/networking/j1939.rst +type SockaddrCANJ1939 struct { + Ifindex int + Name uint64 + PGN uint32 + Addr uint8 + raw RawSockaddrCAN +} + +func (sa *SockaddrCANJ1939) sockaddr() (unsafe.Pointer, _Socklen, error) { + if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff { + return nil, 0, EINVAL + } + sa.raw.Family = AF_CAN + sa.raw.Ifindex = int32(sa.Ifindex) + n := (*[8]byte)(unsafe.Pointer(&sa.Name)) + for i := 0; i < 8; i++ { + sa.raw.Addr[i] = n[i] + } + p := (*[4]byte)(unsafe.Pointer(&sa.PGN)) + for i := 0; i < 4; i++ { + sa.raw.Addr[i+8] = p[i] + } + sa.raw.Addr[12] = sa.Addr + return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil +} + // SockaddrALG implements the Sockaddr interface for AF_ALG type sockets. // SockaddrALG enables userspace access to the Linux kernel's cryptography // subsystem. The Type and Name fields specify which type of hash or cipher @@ -952,6 +982,10 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) { return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil } +var socketProtocol = func(fd int) (int, error) { + return GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) +} + func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { switch rsa.Addr.Family { case AF_NETLINK: @@ -1002,7 +1036,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { return sa, nil case AF_INET: - proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) + proto, err := socketProtocol(fd) if err != nil { return nil, err } @@ -1028,7 +1062,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { } case AF_INET6: - proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) + proto, err := socketProtocol(fd) if err != nil { return nil, err } @@ -1063,7 +1097,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { } return sa, nil case AF_BLUETOOTH: - proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) + proto, err := socketProtocol(fd) if err != nil { return nil, err } @@ -1150,20 +1184,43 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { return sa, nil case AF_CAN: - pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa)) - sa := &SockaddrCAN{ - Ifindex: int(pp.Ifindex), + proto, err := socketProtocol(fd) + if err != nil { + return nil, err } - rx := (*[4]byte)(unsafe.Pointer(&sa.RxID)) - for i := 0; i < 4; i++ { - rx[i] = pp.Addr[i] - } - tx := (*[4]byte)(unsafe.Pointer(&sa.TxID)) - for i := 0; i < 4; i++ { - tx[i] = pp.Addr[i+4] - } - return sa, nil + pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa)) + + switch proto { + case CAN_J1939: + sa := &SockaddrCANJ1939{ + Ifindex: int(pp.Ifindex), + } + name := (*[8]byte)(unsafe.Pointer(&sa.Name)) + for i := 0; i < 8; i++ { + name[i] = pp.Addr[i] + } + pgn := (*[4]byte)(unsafe.Pointer(&sa.PGN)) + for i := 0; i < 4; i++ { + pgn[i] = pp.Addr[i+8] + } + addr := (*[1]byte)(unsafe.Pointer(&sa.Addr)) + addr[0] = pp.Addr[12] + return sa, nil + default: + sa := &SockaddrCAN{ + Ifindex: int(pp.Ifindex), + } + rx := (*[4]byte)(unsafe.Pointer(&sa.RxID)) + for i := 0; i < 4; i++ { + rx[i] = pp.Addr[i] + } + tx := (*[4]byte)(unsafe.Pointer(&sa.TxID)) + for i := 0; i < 4; i++ { + tx[i] = pp.Addr[i+4] + } + return sa, nil + } } return nil, EAFNOSUPPORT } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go index 21a4946ba5..baa771f8ad 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build amd64,linux -// +build !gccgo +// +build gc package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc.go index c26e6ec231..9edf3961b0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,!gccgo +// +build linux,gc package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go index 070bd38994..90e33d8cf7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,!gccgo,386 +// +build linux,gc,386 package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go index 8c514c95ed..1a97baae73 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm,!gccgo,linux +// +build arm,gc,linux package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc.go index 1c70d1b690..87bd161cef 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build darwin dragonfly freebsd linux netbsd openbsd solaris -// +build !gccgo,!ppc64le,!ppc64 +// +build gc,!ppc64le,!ppc64 package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go index 86dc765aba..d36216c3ca 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go @@ -4,7 +4,7 @@ // +build linux // +build ppc64le ppc64 -// +build !gccgo +// +build gc package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go index 2069fb861d..b46110354d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -1217,6 +1217,12 @@ const ( LOOP_SET_STATUS_SETTABLE_FLAGS = 0xc LO_KEY_SIZE = 0x20 LO_NAME_SIZE = 0x40 + LWTUNNEL_IP6_MAX = 0x8 + LWTUNNEL_IP_MAX = 0x8 + LWTUNNEL_IP_OPTS_MAX = 0x3 + LWTUNNEL_IP_OPT_ERSPAN_MAX = 0x4 + LWTUNNEL_IP_OPT_GENEVE_MAX = 0x3 + LWTUNNEL_IP_OPT_VXLAN_MAX = 0x1 MADV_COLD = 0x14 MADV_DODUMP = 0x11 MADV_DOFORK = 0xb diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go index 4b3a8ad7be..0550da06d1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go @@ -2,7 +2,7 @@ // Code generated by the command above; see README.md. DO NOT EDIT. // +build aix,ppc64 -// +build !gccgo +// +build gc package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go index e263fbdb8b..c8c142c59a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go @@ -24,7 +24,6 @@ func closedir(dir uintptr) (err error) { func libc_closedir_trampoline() -//go:linkname libc_closedir libc_closedir //go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -37,5 +36,4 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { func libc_readdir_r_trampoline() -//go:linkname libc_readdir_r libc_readdir_r //go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go index 6eb4579832..7f0f117d32 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go @@ -25,7 +25,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { func libc_getgroups_trampoline() -//go:linkname libc_getgroups libc_getgroups //go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -40,7 +39,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) { func libc_setgroups_trampoline() -//go:linkname libc_setgroups libc_setgroups //go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -56,7 +54,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err func libc_wait4_trampoline() -//go:linkname libc_wait4 libc_wait4 //go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -72,7 +69,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { func libc_accept_trampoline() -//go:linkname libc_accept libc_accept //go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -87,7 +83,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_bind_trampoline() -//go:linkname libc_bind libc_bind //go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -102,7 +97,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_connect_trampoline() -//go:linkname libc_connect libc_connect //go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -118,7 +112,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) { func libc_socket_trampoline() -//go:linkname libc_socket libc_socket //go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -133,7 +126,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen func libc_getsockopt_trampoline() -//go:linkname libc_getsockopt libc_getsockopt //go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -148,7 +140,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) func libc_setsockopt_trampoline() -//go:linkname libc_setsockopt libc_setsockopt //go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -163,7 +154,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getpeername_trampoline() -//go:linkname libc_getpeername libc_getpeername //go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -178,7 +168,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getsockname_trampoline() -//go:linkname libc_getsockname libc_getsockname //go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -193,7 +182,6 @@ func Shutdown(s int, how int) (err error) { func libc_shutdown_trampoline() -//go:linkname libc_shutdown libc_shutdown //go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -208,7 +196,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { func libc_socketpair_trampoline() -//go:linkname libc_socketpair libc_socketpair //go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -230,7 +217,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl func libc_recvfrom_trampoline() -//go:linkname libc_recvfrom libc_recvfrom //go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -251,7 +237,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( func libc_sendto_trampoline() -//go:linkname libc_sendto libc_sendto //go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -267,7 +252,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_recvmsg_trampoline() -//go:linkname libc_recvmsg libc_recvmsg //go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -283,7 +267,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_sendmsg_trampoline() -//go:linkname libc_sendmsg libc_sendmsg //go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -299,7 +282,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne func libc_kevent_trampoline() -//go:linkname libc_kevent libc_kevent //go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -319,7 +301,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) { func libc_utimes_trampoline() -//go:linkname libc_utimes libc_utimes //go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -334,7 +315,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) { func libc_futimes_trampoline() -//go:linkname libc_futimes libc_futimes //go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -350,7 +330,6 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { func libc_poll_trampoline() -//go:linkname libc_poll libc_poll //go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -371,7 +350,6 @@ func Madvise(b []byte, behav int) (err error) { func libc_madvise_trampoline() -//go:linkname libc_madvise libc_madvise //go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -392,7 +370,6 @@ func Mlock(b []byte) (err error) { func libc_mlock_trampoline() -//go:linkname libc_mlock libc_mlock //go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -407,7 +384,6 @@ func Mlockall(flags int) (err error) { func libc_mlockall_trampoline() -//go:linkname libc_mlockall libc_mlockall //go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -428,7 +404,6 @@ func Mprotect(b []byte, prot int) (err error) { func libc_mprotect_trampoline() -//go:linkname libc_mprotect libc_mprotect //go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -449,7 +424,6 @@ func Msync(b []byte, flags int) (err error) { func libc_msync_trampoline() -//go:linkname libc_msync libc_msync //go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -470,7 +444,6 @@ func Munlock(b []byte) (err error) { func libc_munlock_trampoline() -//go:linkname libc_munlock libc_munlock //go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -485,7 +458,6 @@ func Munlockall() (err error) { func libc_munlockall_trampoline() -//go:linkname libc_munlockall libc_munlockall //go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -502,7 +474,6 @@ func pipe() (r int, w int, err error) { func libc_pipe_trampoline() -//go:linkname libc_pipe libc_pipe //go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -528,7 +499,6 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o func libc_getxattr_trampoline() -//go:linkname libc_getxattr libc_getxattr //go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -549,7 +519,6 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio func libc_fgetxattr_trampoline() -//go:linkname libc_fgetxattr libc_fgetxattr //go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -574,7 +543,6 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o func libc_setxattr_trampoline() -//go:linkname libc_setxattr libc_setxattr //go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -594,7 +562,6 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio func libc_fsetxattr_trampoline() -//go:linkname libc_fsetxattr libc_fsetxattr //go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -619,7 +586,6 @@ func removexattr(path string, attr string, options int) (err error) { func libc_removexattr_trampoline() -//go:linkname libc_removexattr libc_removexattr //go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -639,7 +605,6 @@ func fremovexattr(fd int, attr string, options int) (err error) { func libc_fremovexattr_trampoline() -//go:linkname libc_fremovexattr libc_fremovexattr //go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -660,7 +625,6 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro func libc_listxattr_trampoline() -//go:linkname libc_listxattr libc_listxattr //go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -676,7 +640,6 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { func libc_flistxattr_trampoline() -//go:linkname libc_flistxattr libc_flistxattr //go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -691,7 +654,6 @@ func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp func libc_setattrlist_trampoline() -//go:linkname libc_setattrlist libc_setattrlist //go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -707,7 +669,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { func libc_fcntl_trampoline() -//go:linkname libc_fcntl libc_fcntl //go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -722,7 +683,6 @@ func kill(pid int, signum int, posix int) (err error) { func libc_kill_trampoline() -//go:linkname libc_kill libc_kill //go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -737,7 +697,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { func libc_ioctl_trampoline() -//go:linkname libc_ioctl libc_ioctl //go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -758,7 +717,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) func libc_sysctl_trampoline() -//go:linkname libc_sysctl libc_sysctl //go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -773,7 +731,6 @@ func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer func libc_sendfile_trampoline() -//go:linkname libc_sendfile libc_sendfile //go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -793,7 +750,6 @@ func Access(path string, mode uint32) (err error) { func libc_access_trampoline() -//go:linkname libc_access libc_access //go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -808,7 +764,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { func libc_adjtime_trampoline() -//go:linkname libc_adjtime libc_adjtime //go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -828,7 +783,6 @@ func Chdir(path string) (err error) { func libc_chdir_trampoline() -//go:linkname libc_chdir libc_chdir //go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -848,7 +802,6 @@ func Chflags(path string, flags int) (err error) { func libc_chflags_trampoline() -//go:linkname libc_chflags libc_chflags //go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -868,7 +821,6 @@ func Chmod(path string, mode uint32) (err error) { func libc_chmod_trampoline() -//go:linkname libc_chmod libc_chmod //go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -888,7 +840,6 @@ func Chown(path string, uid int, gid int) (err error) { func libc_chown_trampoline() -//go:linkname libc_chown libc_chown //go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -908,7 +859,6 @@ func Chroot(path string) (err error) { func libc_chroot_trampoline() -//go:linkname libc_chroot libc_chroot //go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -923,7 +873,6 @@ func ClockGettime(clockid int32, time *Timespec) (err error) { func libc_clock_gettime_trampoline() -//go:linkname libc_clock_gettime libc_clock_gettime //go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -938,7 +887,6 @@ func Close(fd int) (err error) { func libc_close_trampoline() -//go:linkname libc_close libc_close //go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -963,7 +911,6 @@ func Clonefile(src string, dst string, flags int) (err error) { func libc_clonefile_trampoline() -//go:linkname libc_clonefile libc_clonefile //go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -988,7 +935,6 @@ func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) func libc_clonefileat_trampoline() -//go:linkname libc_clonefileat libc_clonefileat //go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1004,7 +950,6 @@ func Dup(fd int) (nfd int, err error) { func libc_dup_trampoline() -//go:linkname libc_dup libc_dup //go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1019,7 +964,6 @@ func Dup2(from int, to int) (err error) { func libc_dup2_trampoline() -//go:linkname libc_dup2 libc_dup2 //go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1044,7 +988,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) { func libc_exchangedata_trampoline() -//go:linkname libc_exchangedata libc_exchangedata //go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1056,7 +999,6 @@ func Exit(code int) { func libc_exit_trampoline() -//go:linkname libc_exit libc_exit //go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1076,7 +1018,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { func libc_faccessat_trampoline() -//go:linkname libc_faccessat libc_faccessat //go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1091,7 +1032,6 @@ func Fchdir(fd int) (err error) { func libc_fchdir_trampoline() -//go:linkname libc_fchdir libc_fchdir //go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1106,7 +1046,6 @@ func Fchflags(fd int, flags int) (err error) { func libc_fchflags_trampoline() -//go:linkname libc_fchflags libc_fchflags //go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1121,7 +1060,6 @@ func Fchmod(fd int, mode uint32) (err error) { func libc_fchmod_trampoline() -//go:linkname libc_fchmod libc_fchmod //go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1141,7 +1079,6 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { func libc_fchmodat_trampoline() -//go:linkname libc_fchmodat libc_fchmodat //go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1156,7 +1093,6 @@ func Fchown(fd int, uid int, gid int) (err error) { func libc_fchown_trampoline() -//go:linkname libc_fchown libc_fchown //go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1176,7 +1112,6 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { func libc_fchownat_trampoline() -//go:linkname libc_fchownat libc_fchownat //go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1196,7 +1131,6 @@ func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) func libc_fclonefileat_trampoline() -//go:linkname libc_fclonefileat libc_fclonefileat //go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1211,7 +1145,6 @@ func Flock(fd int, how int) (err error) { func libc_flock_trampoline() -//go:linkname libc_flock libc_flock //go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1227,7 +1160,6 @@ func Fpathconf(fd int, name int) (val int, err error) { func libc_fpathconf_trampoline() -//go:linkname libc_fpathconf libc_fpathconf //go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1242,7 +1174,6 @@ func Fsync(fd int) (err error) { func libc_fsync_trampoline() -//go:linkname libc_fsync libc_fsync //go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1257,7 +1188,6 @@ func Ftruncate(fd int, length int64) (err error) { func libc_ftruncate_trampoline() -//go:linkname libc_ftruncate libc_ftruncate //go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1279,7 +1209,6 @@ func Getcwd(buf []byte) (n int, err error) { func libc_getcwd_trampoline() -//go:linkname libc_getcwd libc_getcwd //go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1292,7 +1221,6 @@ func Getdtablesize() (size int) { func libc_getdtablesize_trampoline() -//go:linkname libc_getdtablesize libc_getdtablesize //go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1305,7 +1233,6 @@ func Getegid() (egid int) { func libc_getegid_trampoline() -//go:linkname libc_getegid libc_getegid //go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1318,7 +1245,6 @@ func Geteuid() (uid int) { func libc_geteuid_trampoline() -//go:linkname libc_geteuid libc_geteuid //go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1331,7 +1257,6 @@ func Getgid() (gid int) { func libc_getgid_trampoline() -//go:linkname libc_getgid libc_getgid //go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1347,7 +1272,6 @@ func Getpgid(pid int) (pgid int, err error) { func libc_getpgid_trampoline() -//go:linkname libc_getpgid libc_getpgid //go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1360,7 +1284,6 @@ func Getpgrp() (pgrp int) { func libc_getpgrp_trampoline() -//go:linkname libc_getpgrp libc_getpgrp //go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1373,7 +1296,6 @@ func Getpid() (pid int) { func libc_getpid_trampoline() -//go:linkname libc_getpid libc_getpid //go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1386,7 +1308,6 @@ func Getppid() (ppid int) { func libc_getppid_trampoline() -//go:linkname libc_getppid libc_getppid //go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1402,7 +1323,6 @@ func Getpriority(which int, who int) (prio int, err error) { func libc_getpriority_trampoline() -//go:linkname libc_getpriority libc_getpriority //go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1417,7 +1337,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) { func libc_getrlimit_trampoline() -//go:linkname libc_getrlimit libc_getrlimit //go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1432,7 +1351,6 @@ func Getrusage(who int, rusage *Rusage) (err error) { func libc_getrusage_trampoline() -//go:linkname libc_getrusage libc_getrusage //go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1448,7 +1366,6 @@ func Getsid(pid int) (sid int, err error) { func libc_getsid_trampoline() -//go:linkname libc_getsid libc_getsid //go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1463,7 +1380,6 @@ func Gettimeofday(tp *Timeval) (err error) { func libc_gettimeofday_trampoline() -//go:linkname libc_gettimeofday libc_gettimeofday //go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1476,7 +1392,6 @@ func Getuid() (uid int) { func libc_getuid_trampoline() -//go:linkname libc_getuid libc_getuid //go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1489,7 +1404,6 @@ func Issetugid() (tainted bool) { func libc_issetugid_trampoline() -//go:linkname libc_issetugid libc_issetugid //go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1505,7 +1419,6 @@ func Kqueue() (fd int, err error) { func libc_kqueue_trampoline() -//go:linkname libc_kqueue libc_kqueue //go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1525,7 +1438,6 @@ func Lchown(path string, uid int, gid int) (err error) { func libc_lchown_trampoline() -//go:linkname libc_lchown libc_lchown //go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1550,7 +1462,6 @@ func Link(path string, link string) (err error) { func libc_link_trampoline() -//go:linkname libc_link libc_link //go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1575,7 +1486,6 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er func libc_linkat_trampoline() -//go:linkname libc_linkat libc_linkat //go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1590,7 +1500,6 @@ func Listen(s int, backlog int) (err error) { func libc_listen_trampoline() -//go:linkname libc_listen libc_listen //go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1610,7 +1519,6 @@ func Mkdir(path string, mode uint32) (err error) { func libc_mkdir_trampoline() -//go:linkname libc_mkdir libc_mkdir //go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1630,7 +1538,6 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { func libc_mkdirat_trampoline() -//go:linkname libc_mkdirat libc_mkdirat //go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1650,7 +1557,6 @@ func Mkfifo(path string, mode uint32) (err error) { func libc_mkfifo_trampoline() -//go:linkname libc_mkfifo libc_mkfifo //go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1670,7 +1576,6 @@ func Mknod(path string, mode uint32, dev int) (err error) { func libc_mknod_trampoline() -//go:linkname libc_mknod libc_mknod //go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1691,7 +1596,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { func libc_open_trampoline() -//go:linkname libc_open libc_open //go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1712,7 +1616,6 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { func libc_openat_trampoline() -//go:linkname libc_openat libc_openat //go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1733,7 +1636,6 @@ func Pathconf(path string, name int) (val int, err error) { func libc_pathconf_trampoline() -//go:linkname libc_pathconf libc_pathconf //go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1755,7 +1657,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { func libc_pread_trampoline() -//go:linkname libc_pread libc_pread //go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1777,7 +1678,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { func libc_pwrite_trampoline() -//go:linkname libc_pwrite libc_pwrite //go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1799,7 +1699,6 @@ func read(fd int, p []byte) (n int, err error) { func libc_read_trampoline() -//go:linkname libc_read libc_read //go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1826,7 +1725,6 @@ func Readlink(path string, buf []byte) (n int, err error) { func libc_readlink_trampoline() -//go:linkname libc_readlink libc_readlink //go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1853,7 +1751,6 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { func libc_readlinkat_trampoline() -//go:linkname libc_readlinkat libc_readlinkat //go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1878,7 +1775,6 @@ func Rename(from string, to string) (err error) { func libc_rename_trampoline() -//go:linkname libc_rename libc_rename //go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1903,7 +1799,6 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { func libc_renameat_trampoline() -//go:linkname libc_renameat libc_renameat //go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1923,7 +1818,6 @@ func Revoke(path string) (err error) { func libc_revoke_trampoline() -//go:linkname libc_revoke libc_revoke //go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1943,7 +1837,6 @@ func Rmdir(path string) (err error) { func libc_rmdir_trampoline() -//go:linkname libc_rmdir libc_rmdir //go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1959,7 +1852,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func libc_lseek_trampoline() -//go:linkname libc_lseek libc_lseek //go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1975,7 +1867,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err func libc_select_trampoline() -//go:linkname libc_select libc_select //go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1990,7 +1881,6 @@ func Setegid(egid int) (err error) { func libc_setegid_trampoline() -//go:linkname libc_setegid libc_setegid //go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2005,7 +1895,6 @@ func Seteuid(euid int) (err error) { func libc_seteuid_trampoline() -//go:linkname libc_seteuid libc_seteuid //go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2020,7 +1909,6 @@ func Setgid(gid int) (err error) { func libc_setgid_trampoline() -//go:linkname libc_setgid libc_setgid //go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2040,7 +1928,6 @@ func Setlogin(name string) (err error) { func libc_setlogin_trampoline() -//go:linkname libc_setlogin libc_setlogin //go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2055,7 +1942,6 @@ func Setpgid(pid int, pgid int) (err error) { func libc_setpgid_trampoline() -//go:linkname libc_setpgid libc_setpgid //go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2070,7 +1956,6 @@ func Setpriority(which int, who int, prio int) (err error) { func libc_setpriority_trampoline() -//go:linkname libc_setpriority libc_setpriority //go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2085,7 +1970,6 @@ func Setprivexec(flag int) (err error) { func libc_setprivexec_trampoline() -//go:linkname libc_setprivexec libc_setprivexec //go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2100,7 +1984,6 @@ func Setregid(rgid int, egid int) (err error) { func libc_setregid_trampoline() -//go:linkname libc_setregid libc_setregid //go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2115,7 +1998,6 @@ func Setreuid(ruid int, euid int) (err error) { func libc_setreuid_trampoline() -//go:linkname libc_setreuid libc_setreuid //go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2130,7 +2012,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) { func libc_setrlimit_trampoline() -//go:linkname libc_setrlimit libc_setrlimit //go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2146,7 +2027,6 @@ func Setsid() (pid int, err error) { func libc_setsid_trampoline() -//go:linkname libc_setsid libc_setsid //go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2161,7 +2041,6 @@ func Settimeofday(tp *Timeval) (err error) { func libc_settimeofday_trampoline() -//go:linkname libc_settimeofday libc_settimeofday //go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2176,7 +2055,6 @@ func Setuid(uid int) (err error) { func libc_setuid_trampoline() -//go:linkname libc_setuid libc_setuid //go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2201,7 +2079,6 @@ func Symlink(path string, link string) (err error) { func libc_symlink_trampoline() -//go:linkname libc_symlink libc_symlink //go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2226,7 +2103,6 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { func libc_symlinkat_trampoline() -//go:linkname libc_symlinkat libc_symlinkat //go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2241,7 +2117,6 @@ func Sync() (err error) { func libc_sync_trampoline() -//go:linkname libc_sync libc_sync //go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2261,7 +2136,6 @@ func Truncate(path string, length int64) (err error) { func libc_truncate_trampoline() -//go:linkname libc_truncate libc_truncate //go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2274,7 +2148,6 @@ func Umask(newmask int) (oldmask int) { func libc_umask_trampoline() -//go:linkname libc_umask libc_umask //go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2294,7 +2167,6 @@ func Undelete(path string) (err error) { func libc_undelete_trampoline() -//go:linkname libc_undelete libc_undelete //go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2314,7 +2186,6 @@ func Unlink(path string) (err error) { func libc_unlink_trampoline() -//go:linkname libc_unlink libc_unlink //go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2334,7 +2205,6 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { func libc_unlinkat_trampoline() -//go:linkname libc_unlinkat libc_unlinkat //go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2354,7 +2224,6 @@ func Unmount(path string, flags int) (err error) { func libc_unmount_trampoline() -//go:linkname libc_unmount libc_unmount //go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2376,7 +2245,6 @@ func write(fd int, p []byte) (n int, err error) { func libc_write_trampoline() -//go:linkname libc_write libc_write //go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2392,7 +2260,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( func libc_mmap_trampoline() -//go:linkname libc_mmap libc_mmap //go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2407,7 +2274,6 @@ func munmap(addr uintptr, length uintptr) (err error) { func libc_munmap_trampoline() -//go:linkname libc_munmap libc_munmap //go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2444,7 +2310,6 @@ func Fstat(fd int, stat *Stat_t) (err error) { func libc_fstat64_trampoline() -//go:linkname libc_fstat64 libc_fstat64 //go:cgo_import_dynamic libc_fstat64 fstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2464,7 +2329,6 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { func libc_fstatat64_trampoline() -//go:linkname libc_fstatat64 libc_fstatat64 //go:cgo_import_dynamic libc_fstatat64 fstatat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2479,7 +2343,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { func libc_fstatfs64_trampoline() -//go:linkname libc_fstatfs64 libc_fstatfs64 //go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2495,7 +2358,6 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { func libc_getfsstat64_trampoline() -//go:linkname libc_getfsstat64 libc_getfsstat64 //go:cgo_import_dynamic libc_getfsstat64 getfsstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2515,7 +2377,6 @@ func Lstat(path string, stat *Stat_t) (err error) { func libc_lstat64_trampoline() -//go:linkname libc_lstat64 libc_lstat64 //go:cgo_import_dynamic libc_lstat64 lstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2530,7 +2391,6 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func libc_ptrace_trampoline() -//go:linkname libc_ptrace libc_ptrace //go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2550,7 +2410,6 @@ func Stat(path string, stat *Stat_t) (err error) { func libc_stat64_trampoline() -//go:linkname libc_stat64 libc_stat64 //go:cgo_import_dynamic libc_stat64 stat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2570,5 +2429,4 @@ func Statfs(path string, stat *Statfs_t) (err error) { func libc_statfs64_trampoline() -//go:linkname libc_statfs64 libc_statfs64 //go:cgo_import_dynamic libc_statfs64 statfs64 "/usr/lib/libSystem.B.dylib" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go index 314042a9d4..8882623613 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go @@ -24,7 +24,6 @@ func closedir(dir uintptr) (err error) { func libc_closedir_trampoline() -//go:linkname libc_closedir libc_closedir //go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -37,5 +36,4 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { func libc_readdir_r_trampoline() -//go:linkname libc_readdir_r libc_readdir_r //go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index 889c14059e..2daf0bd628 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -25,7 +25,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { func libc_getgroups_trampoline() -//go:linkname libc_getgroups libc_getgroups //go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -40,7 +39,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) { func libc_setgroups_trampoline() -//go:linkname libc_setgroups libc_setgroups //go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -56,7 +54,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err func libc_wait4_trampoline() -//go:linkname libc_wait4 libc_wait4 //go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -72,7 +69,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { func libc_accept_trampoline() -//go:linkname libc_accept libc_accept //go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -87,7 +83,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_bind_trampoline() -//go:linkname libc_bind libc_bind //go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -102,7 +97,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_connect_trampoline() -//go:linkname libc_connect libc_connect //go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -118,7 +112,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) { func libc_socket_trampoline() -//go:linkname libc_socket libc_socket //go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -133,7 +126,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen func libc_getsockopt_trampoline() -//go:linkname libc_getsockopt libc_getsockopt //go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -148,7 +140,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) func libc_setsockopt_trampoline() -//go:linkname libc_setsockopt libc_setsockopt //go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -163,7 +154,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getpeername_trampoline() -//go:linkname libc_getpeername libc_getpeername //go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -178,7 +168,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getsockname_trampoline() -//go:linkname libc_getsockname libc_getsockname //go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -193,7 +182,6 @@ func Shutdown(s int, how int) (err error) { func libc_shutdown_trampoline() -//go:linkname libc_shutdown libc_shutdown //go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -208,7 +196,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { func libc_socketpair_trampoline() -//go:linkname libc_socketpair libc_socketpair //go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -230,7 +217,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl func libc_recvfrom_trampoline() -//go:linkname libc_recvfrom libc_recvfrom //go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -251,7 +237,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( func libc_sendto_trampoline() -//go:linkname libc_sendto libc_sendto //go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -267,7 +252,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_recvmsg_trampoline() -//go:linkname libc_recvmsg libc_recvmsg //go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -283,7 +267,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_sendmsg_trampoline() -//go:linkname libc_sendmsg libc_sendmsg //go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -299,7 +282,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne func libc_kevent_trampoline() -//go:linkname libc_kevent libc_kevent //go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -319,7 +301,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) { func libc_utimes_trampoline() -//go:linkname libc_utimes libc_utimes //go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -334,7 +315,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) { func libc_futimes_trampoline() -//go:linkname libc_futimes libc_futimes //go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -350,7 +330,6 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { func libc_poll_trampoline() -//go:linkname libc_poll libc_poll //go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -371,7 +350,6 @@ func Madvise(b []byte, behav int) (err error) { func libc_madvise_trampoline() -//go:linkname libc_madvise libc_madvise //go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -392,7 +370,6 @@ func Mlock(b []byte) (err error) { func libc_mlock_trampoline() -//go:linkname libc_mlock libc_mlock //go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -407,7 +384,6 @@ func Mlockall(flags int) (err error) { func libc_mlockall_trampoline() -//go:linkname libc_mlockall libc_mlockall //go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -428,7 +404,6 @@ func Mprotect(b []byte, prot int) (err error) { func libc_mprotect_trampoline() -//go:linkname libc_mprotect libc_mprotect //go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -449,7 +424,6 @@ func Msync(b []byte, flags int) (err error) { func libc_msync_trampoline() -//go:linkname libc_msync libc_msync //go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -470,7 +444,6 @@ func Munlock(b []byte) (err error) { func libc_munlock_trampoline() -//go:linkname libc_munlock libc_munlock //go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -485,7 +458,6 @@ func Munlockall() (err error) { func libc_munlockall_trampoline() -//go:linkname libc_munlockall libc_munlockall //go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -502,7 +474,6 @@ func pipe() (r int, w int, err error) { func libc_pipe_trampoline() -//go:linkname libc_pipe libc_pipe //go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -528,7 +499,6 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o func libc_getxattr_trampoline() -//go:linkname libc_getxattr libc_getxattr //go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -549,7 +519,6 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio func libc_fgetxattr_trampoline() -//go:linkname libc_fgetxattr libc_fgetxattr //go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -574,7 +543,6 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o func libc_setxattr_trampoline() -//go:linkname libc_setxattr libc_setxattr //go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -594,7 +562,6 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio func libc_fsetxattr_trampoline() -//go:linkname libc_fsetxattr libc_fsetxattr //go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -619,7 +586,6 @@ func removexattr(path string, attr string, options int) (err error) { func libc_removexattr_trampoline() -//go:linkname libc_removexattr libc_removexattr //go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -639,7 +605,6 @@ func fremovexattr(fd int, attr string, options int) (err error) { func libc_fremovexattr_trampoline() -//go:linkname libc_fremovexattr libc_fremovexattr //go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -660,7 +625,6 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro func libc_listxattr_trampoline() -//go:linkname libc_listxattr libc_listxattr //go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -676,7 +640,6 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { func libc_flistxattr_trampoline() -//go:linkname libc_flistxattr libc_flistxattr //go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -691,7 +654,6 @@ func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp func libc_setattrlist_trampoline() -//go:linkname libc_setattrlist libc_setattrlist //go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -707,7 +669,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { func libc_fcntl_trampoline() -//go:linkname libc_fcntl libc_fcntl //go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -722,7 +683,6 @@ func kill(pid int, signum int, posix int) (err error) { func libc_kill_trampoline() -//go:linkname libc_kill libc_kill //go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -737,7 +697,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { func libc_ioctl_trampoline() -//go:linkname libc_ioctl libc_ioctl //go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -758,7 +717,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) func libc_sysctl_trampoline() -//go:linkname libc_sysctl libc_sysctl //go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -773,7 +731,6 @@ func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer func libc_sendfile_trampoline() -//go:linkname libc_sendfile libc_sendfile //go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -793,7 +750,6 @@ func Access(path string, mode uint32) (err error) { func libc_access_trampoline() -//go:linkname libc_access libc_access //go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -808,7 +764,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { func libc_adjtime_trampoline() -//go:linkname libc_adjtime libc_adjtime //go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -828,7 +783,6 @@ func Chdir(path string) (err error) { func libc_chdir_trampoline() -//go:linkname libc_chdir libc_chdir //go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -848,7 +802,6 @@ func Chflags(path string, flags int) (err error) { func libc_chflags_trampoline() -//go:linkname libc_chflags libc_chflags //go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -868,7 +821,6 @@ func Chmod(path string, mode uint32) (err error) { func libc_chmod_trampoline() -//go:linkname libc_chmod libc_chmod //go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -888,7 +840,6 @@ func Chown(path string, uid int, gid int) (err error) { func libc_chown_trampoline() -//go:linkname libc_chown libc_chown //go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -908,7 +859,6 @@ func Chroot(path string) (err error) { func libc_chroot_trampoline() -//go:linkname libc_chroot libc_chroot //go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -923,7 +873,6 @@ func ClockGettime(clockid int32, time *Timespec) (err error) { func libc_clock_gettime_trampoline() -//go:linkname libc_clock_gettime libc_clock_gettime //go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -938,7 +887,6 @@ func Close(fd int) (err error) { func libc_close_trampoline() -//go:linkname libc_close libc_close //go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -963,7 +911,6 @@ func Clonefile(src string, dst string, flags int) (err error) { func libc_clonefile_trampoline() -//go:linkname libc_clonefile libc_clonefile //go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -988,7 +935,6 @@ func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) func libc_clonefileat_trampoline() -//go:linkname libc_clonefileat libc_clonefileat //go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1004,7 +950,6 @@ func Dup(fd int) (nfd int, err error) { func libc_dup_trampoline() -//go:linkname libc_dup libc_dup //go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1019,7 +964,6 @@ func Dup2(from int, to int) (err error) { func libc_dup2_trampoline() -//go:linkname libc_dup2 libc_dup2 //go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1044,7 +988,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) { func libc_exchangedata_trampoline() -//go:linkname libc_exchangedata libc_exchangedata //go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1056,7 +999,6 @@ func Exit(code int) { func libc_exit_trampoline() -//go:linkname libc_exit libc_exit //go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1076,7 +1018,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { func libc_faccessat_trampoline() -//go:linkname libc_faccessat libc_faccessat //go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1091,7 +1032,6 @@ func Fchdir(fd int) (err error) { func libc_fchdir_trampoline() -//go:linkname libc_fchdir libc_fchdir //go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1106,7 +1046,6 @@ func Fchflags(fd int, flags int) (err error) { func libc_fchflags_trampoline() -//go:linkname libc_fchflags libc_fchflags //go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1121,7 +1060,6 @@ func Fchmod(fd int, mode uint32) (err error) { func libc_fchmod_trampoline() -//go:linkname libc_fchmod libc_fchmod //go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1141,7 +1079,6 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { func libc_fchmodat_trampoline() -//go:linkname libc_fchmodat libc_fchmodat //go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1156,7 +1093,6 @@ func Fchown(fd int, uid int, gid int) (err error) { func libc_fchown_trampoline() -//go:linkname libc_fchown libc_fchown //go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1176,7 +1112,6 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { func libc_fchownat_trampoline() -//go:linkname libc_fchownat libc_fchownat //go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1196,7 +1131,6 @@ func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) func libc_fclonefileat_trampoline() -//go:linkname libc_fclonefileat libc_fclonefileat //go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1211,7 +1145,6 @@ func Flock(fd int, how int) (err error) { func libc_flock_trampoline() -//go:linkname libc_flock libc_flock //go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1227,7 +1160,6 @@ func Fpathconf(fd int, name int) (val int, err error) { func libc_fpathconf_trampoline() -//go:linkname libc_fpathconf libc_fpathconf //go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1242,7 +1174,6 @@ func Fsync(fd int) (err error) { func libc_fsync_trampoline() -//go:linkname libc_fsync libc_fsync //go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1257,7 +1188,6 @@ func Ftruncate(fd int, length int64) (err error) { func libc_ftruncate_trampoline() -//go:linkname libc_ftruncate libc_ftruncate //go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1279,7 +1209,6 @@ func Getcwd(buf []byte) (n int, err error) { func libc_getcwd_trampoline() -//go:linkname libc_getcwd libc_getcwd //go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1292,7 +1221,6 @@ func Getdtablesize() (size int) { func libc_getdtablesize_trampoline() -//go:linkname libc_getdtablesize libc_getdtablesize //go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1305,7 +1233,6 @@ func Getegid() (egid int) { func libc_getegid_trampoline() -//go:linkname libc_getegid libc_getegid //go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1318,7 +1245,6 @@ func Geteuid() (uid int) { func libc_geteuid_trampoline() -//go:linkname libc_geteuid libc_geteuid //go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1331,7 +1257,6 @@ func Getgid() (gid int) { func libc_getgid_trampoline() -//go:linkname libc_getgid libc_getgid //go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1347,7 +1272,6 @@ func Getpgid(pid int) (pgid int, err error) { func libc_getpgid_trampoline() -//go:linkname libc_getpgid libc_getpgid //go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1360,7 +1284,6 @@ func Getpgrp() (pgrp int) { func libc_getpgrp_trampoline() -//go:linkname libc_getpgrp libc_getpgrp //go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1373,7 +1296,6 @@ func Getpid() (pid int) { func libc_getpid_trampoline() -//go:linkname libc_getpid libc_getpid //go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1386,7 +1308,6 @@ func Getppid() (ppid int) { func libc_getppid_trampoline() -//go:linkname libc_getppid libc_getppid //go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1402,7 +1323,6 @@ func Getpriority(which int, who int) (prio int, err error) { func libc_getpriority_trampoline() -//go:linkname libc_getpriority libc_getpriority //go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1417,7 +1337,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) { func libc_getrlimit_trampoline() -//go:linkname libc_getrlimit libc_getrlimit //go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1432,7 +1351,6 @@ func Getrusage(who int, rusage *Rusage) (err error) { func libc_getrusage_trampoline() -//go:linkname libc_getrusage libc_getrusage //go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1448,7 +1366,6 @@ func Getsid(pid int) (sid int, err error) { func libc_getsid_trampoline() -//go:linkname libc_getsid libc_getsid //go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1463,7 +1380,6 @@ func Gettimeofday(tp *Timeval) (err error) { func libc_gettimeofday_trampoline() -//go:linkname libc_gettimeofday libc_gettimeofday //go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1476,7 +1392,6 @@ func Getuid() (uid int) { func libc_getuid_trampoline() -//go:linkname libc_getuid libc_getuid //go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1489,7 +1404,6 @@ func Issetugid() (tainted bool) { func libc_issetugid_trampoline() -//go:linkname libc_issetugid libc_issetugid //go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1505,7 +1419,6 @@ func Kqueue() (fd int, err error) { func libc_kqueue_trampoline() -//go:linkname libc_kqueue libc_kqueue //go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1525,7 +1438,6 @@ func Lchown(path string, uid int, gid int) (err error) { func libc_lchown_trampoline() -//go:linkname libc_lchown libc_lchown //go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1550,7 +1462,6 @@ func Link(path string, link string) (err error) { func libc_link_trampoline() -//go:linkname libc_link libc_link //go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1575,7 +1486,6 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er func libc_linkat_trampoline() -//go:linkname libc_linkat libc_linkat //go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1590,7 +1500,6 @@ func Listen(s int, backlog int) (err error) { func libc_listen_trampoline() -//go:linkname libc_listen libc_listen //go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1610,7 +1519,6 @@ func Mkdir(path string, mode uint32) (err error) { func libc_mkdir_trampoline() -//go:linkname libc_mkdir libc_mkdir //go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1630,7 +1538,6 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { func libc_mkdirat_trampoline() -//go:linkname libc_mkdirat libc_mkdirat //go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1650,7 +1557,6 @@ func Mkfifo(path string, mode uint32) (err error) { func libc_mkfifo_trampoline() -//go:linkname libc_mkfifo libc_mkfifo //go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1670,7 +1576,6 @@ func Mknod(path string, mode uint32, dev int) (err error) { func libc_mknod_trampoline() -//go:linkname libc_mknod libc_mknod //go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1691,7 +1596,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { func libc_open_trampoline() -//go:linkname libc_open libc_open //go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1712,7 +1616,6 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { func libc_openat_trampoline() -//go:linkname libc_openat libc_openat //go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1733,7 +1636,6 @@ func Pathconf(path string, name int) (val int, err error) { func libc_pathconf_trampoline() -//go:linkname libc_pathconf libc_pathconf //go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1755,7 +1657,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { func libc_pread_trampoline() -//go:linkname libc_pread libc_pread //go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1777,7 +1678,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { func libc_pwrite_trampoline() -//go:linkname libc_pwrite libc_pwrite //go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1799,7 +1699,6 @@ func read(fd int, p []byte) (n int, err error) { func libc_read_trampoline() -//go:linkname libc_read libc_read //go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1826,7 +1725,6 @@ func Readlink(path string, buf []byte) (n int, err error) { func libc_readlink_trampoline() -//go:linkname libc_readlink libc_readlink //go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1853,7 +1751,6 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { func libc_readlinkat_trampoline() -//go:linkname libc_readlinkat libc_readlinkat //go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1878,7 +1775,6 @@ func Rename(from string, to string) (err error) { func libc_rename_trampoline() -//go:linkname libc_rename libc_rename //go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1903,7 +1799,6 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { func libc_renameat_trampoline() -//go:linkname libc_renameat libc_renameat //go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1923,7 +1818,6 @@ func Revoke(path string) (err error) { func libc_revoke_trampoline() -//go:linkname libc_revoke libc_revoke //go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1943,7 +1837,6 @@ func Rmdir(path string) (err error) { func libc_rmdir_trampoline() -//go:linkname libc_rmdir libc_rmdir //go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1959,7 +1852,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func libc_lseek_trampoline() -//go:linkname libc_lseek libc_lseek //go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1975,7 +1867,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err func libc_select_trampoline() -//go:linkname libc_select libc_select //go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1990,7 +1881,6 @@ func Setegid(egid int) (err error) { func libc_setegid_trampoline() -//go:linkname libc_setegid libc_setegid //go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2005,7 +1895,6 @@ func Seteuid(euid int) (err error) { func libc_seteuid_trampoline() -//go:linkname libc_seteuid libc_seteuid //go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2020,7 +1909,6 @@ func Setgid(gid int) (err error) { func libc_setgid_trampoline() -//go:linkname libc_setgid libc_setgid //go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2040,7 +1928,6 @@ func Setlogin(name string) (err error) { func libc_setlogin_trampoline() -//go:linkname libc_setlogin libc_setlogin //go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2055,7 +1942,6 @@ func Setpgid(pid int, pgid int) (err error) { func libc_setpgid_trampoline() -//go:linkname libc_setpgid libc_setpgid //go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2070,7 +1956,6 @@ func Setpriority(which int, who int, prio int) (err error) { func libc_setpriority_trampoline() -//go:linkname libc_setpriority libc_setpriority //go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2085,7 +1970,6 @@ func Setprivexec(flag int) (err error) { func libc_setprivexec_trampoline() -//go:linkname libc_setprivexec libc_setprivexec //go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2100,7 +1984,6 @@ func Setregid(rgid int, egid int) (err error) { func libc_setregid_trampoline() -//go:linkname libc_setregid libc_setregid //go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2115,7 +1998,6 @@ func Setreuid(ruid int, euid int) (err error) { func libc_setreuid_trampoline() -//go:linkname libc_setreuid libc_setreuid //go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2130,7 +2012,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) { func libc_setrlimit_trampoline() -//go:linkname libc_setrlimit libc_setrlimit //go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2146,7 +2027,6 @@ func Setsid() (pid int, err error) { func libc_setsid_trampoline() -//go:linkname libc_setsid libc_setsid //go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2161,7 +2041,6 @@ func Settimeofday(tp *Timeval) (err error) { func libc_settimeofday_trampoline() -//go:linkname libc_settimeofday libc_settimeofday //go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2176,7 +2055,6 @@ func Setuid(uid int) (err error) { func libc_setuid_trampoline() -//go:linkname libc_setuid libc_setuid //go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2201,7 +2079,6 @@ func Symlink(path string, link string) (err error) { func libc_symlink_trampoline() -//go:linkname libc_symlink libc_symlink //go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2226,7 +2103,6 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { func libc_symlinkat_trampoline() -//go:linkname libc_symlinkat libc_symlinkat //go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2241,7 +2117,6 @@ func Sync() (err error) { func libc_sync_trampoline() -//go:linkname libc_sync libc_sync //go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2261,7 +2136,6 @@ func Truncate(path string, length int64) (err error) { func libc_truncate_trampoline() -//go:linkname libc_truncate libc_truncate //go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2274,7 +2148,6 @@ func Umask(newmask int) (oldmask int) { func libc_umask_trampoline() -//go:linkname libc_umask libc_umask //go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2294,7 +2167,6 @@ func Undelete(path string) (err error) { func libc_undelete_trampoline() -//go:linkname libc_undelete libc_undelete //go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2314,7 +2186,6 @@ func Unlink(path string) (err error) { func libc_unlink_trampoline() -//go:linkname libc_unlink libc_unlink //go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2334,7 +2205,6 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { func libc_unlinkat_trampoline() -//go:linkname libc_unlinkat libc_unlinkat //go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2354,7 +2224,6 @@ func Unmount(path string, flags int) (err error) { func libc_unmount_trampoline() -//go:linkname libc_unmount libc_unmount //go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2376,7 +2245,6 @@ func write(fd int, p []byte) (n int, err error) { func libc_write_trampoline() -//go:linkname libc_write libc_write //go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2392,7 +2260,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( func libc_mmap_trampoline() -//go:linkname libc_mmap libc_mmap //go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2407,7 +2274,6 @@ func munmap(addr uintptr, length uintptr) (err error) { func libc_munmap_trampoline() -//go:linkname libc_munmap libc_munmap //go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2444,7 +2310,6 @@ func Fstat(fd int, stat *Stat_t) (err error) { func libc_fstat64_trampoline() -//go:linkname libc_fstat64 libc_fstat64 //go:cgo_import_dynamic libc_fstat64 fstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2464,7 +2329,6 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { func libc_fstatat64_trampoline() -//go:linkname libc_fstatat64 libc_fstatat64 //go:cgo_import_dynamic libc_fstatat64 fstatat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2479,7 +2343,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { func libc_fstatfs64_trampoline() -//go:linkname libc_fstatfs64 libc_fstatfs64 //go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2495,7 +2358,6 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { func libc_getfsstat64_trampoline() -//go:linkname libc_getfsstat64 libc_getfsstat64 //go:cgo_import_dynamic libc_getfsstat64 getfsstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2515,7 +2377,6 @@ func Lstat(path string, stat *Stat_t) (err error) { func libc_lstat64_trampoline() -//go:linkname libc_lstat64 libc_lstat64 //go:cgo_import_dynamic libc_lstat64 lstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2530,7 +2391,6 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func libc_ptrace_trampoline() -//go:linkname libc_ptrace libc_ptrace //go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2550,7 +2410,6 @@ func Stat(path string, stat *Stat_t) (err error) { func libc_stat64_trampoline() -//go:linkname libc_stat64 libc_stat64 //go:cgo_import_dynamic libc_stat64 stat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2570,5 +2429,4 @@ func Statfs(path string, stat *Statfs_t) (err error) { func libc_statfs64_trampoline() -//go:linkname libc_statfs64 libc_statfs64 //go:cgo_import_dynamic libc_statfs64 statfs64 "/usr/lib/libSystem.B.dylib" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go index f519ce9afb..de4738fff8 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go @@ -24,7 +24,6 @@ func closedir(dir uintptr) (err error) { func libc_closedir_trampoline() -//go:linkname libc_closedir libc_closedir //go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -37,5 +36,4 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { func libc_readdir_r_trampoline() -//go:linkname libc_readdir_r libc_readdir_r //go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go index d6b5249c2f..8e79ad377b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go @@ -25,7 +25,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { func libc_getgroups_trampoline() -//go:linkname libc_getgroups libc_getgroups //go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -40,7 +39,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) { func libc_setgroups_trampoline() -//go:linkname libc_setgroups libc_setgroups //go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -56,7 +54,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err func libc_wait4_trampoline() -//go:linkname libc_wait4 libc_wait4 //go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -72,7 +69,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { func libc_accept_trampoline() -//go:linkname libc_accept libc_accept //go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -87,7 +83,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_bind_trampoline() -//go:linkname libc_bind libc_bind //go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -102,7 +97,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_connect_trampoline() -//go:linkname libc_connect libc_connect //go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -118,7 +112,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) { func libc_socket_trampoline() -//go:linkname libc_socket libc_socket //go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -133,7 +126,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen func libc_getsockopt_trampoline() -//go:linkname libc_getsockopt libc_getsockopt //go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -148,7 +140,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) func libc_setsockopt_trampoline() -//go:linkname libc_setsockopt libc_setsockopt //go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -163,7 +154,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getpeername_trampoline() -//go:linkname libc_getpeername libc_getpeername //go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -178,7 +168,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getsockname_trampoline() -//go:linkname libc_getsockname libc_getsockname //go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -193,7 +182,6 @@ func Shutdown(s int, how int) (err error) { func libc_shutdown_trampoline() -//go:linkname libc_shutdown libc_shutdown //go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -208,7 +196,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { func libc_socketpair_trampoline() -//go:linkname libc_socketpair libc_socketpair //go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -230,7 +217,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl func libc_recvfrom_trampoline() -//go:linkname libc_recvfrom libc_recvfrom //go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -251,7 +237,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( func libc_sendto_trampoline() -//go:linkname libc_sendto libc_sendto //go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -267,7 +252,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_recvmsg_trampoline() -//go:linkname libc_recvmsg libc_recvmsg //go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -283,7 +267,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_sendmsg_trampoline() -//go:linkname libc_sendmsg libc_sendmsg //go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -299,7 +282,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne func libc_kevent_trampoline() -//go:linkname libc_kevent libc_kevent //go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -319,7 +301,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) { func libc_utimes_trampoline() -//go:linkname libc_utimes libc_utimes //go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -334,7 +315,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) { func libc_futimes_trampoline() -//go:linkname libc_futimes libc_futimes //go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -350,7 +330,6 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { func libc_poll_trampoline() -//go:linkname libc_poll libc_poll //go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -371,7 +350,6 @@ func Madvise(b []byte, behav int) (err error) { func libc_madvise_trampoline() -//go:linkname libc_madvise libc_madvise //go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -392,7 +370,6 @@ func Mlock(b []byte) (err error) { func libc_mlock_trampoline() -//go:linkname libc_mlock libc_mlock //go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -407,7 +384,6 @@ func Mlockall(flags int) (err error) { func libc_mlockall_trampoline() -//go:linkname libc_mlockall libc_mlockall //go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -428,7 +404,6 @@ func Mprotect(b []byte, prot int) (err error) { func libc_mprotect_trampoline() -//go:linkname libc_mprotect libc_mprotect //go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -449,7 +424,6 @@ func Msync(b []byte, flags int) (err error) { func libc_msync_trampoline() -//go:linkname libc_msync libc_msync //go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -470,7 +444,6 @@ func Munlock(b []byte) (err error) { func libc_munlock_trampoline() -//go:linkname libc_munlock libc_munlock //go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -485,7 +458,6 @@ func Munlockall() (err error) { func libc_munlockall_trampoline() -//go:linkname libc_munlockall libc_munlockall //go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -502,7 +474,6 @@ func pipe() (r int, w int, err error) { func libc_pipe_trampoline() -//go:linkname libc_pipe libc_pipe //go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -528,7 +499,6 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o func libc_getxattr_trampoline() -//go:linkname libc_getxattr libc_getxattr //go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -549,7 +519,6 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio func libc_fgetxattr_trampoline() -//go:linkname libc_fgetxattr libc_fgetxattr //go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -574,7 +543,6 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o func libc_setxattr_trampoline() -//go:linkname libc_setxattr libc_setxattr //go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -594,7 +562,6 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio func libc_fsetxattr_trampoline() -//go:linkname libc_fsetxattr libc_fsetxattr //go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -619,7 +586,6 @@ func removexattr(path string, attr string, options int) (err error) { func libc_removexattr_trampoline() -//go:linkname libc_removexattr libc_removexattr //go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -639,7 +605,6 @@ func fremovexattr(fd int, attr string, options int) (err error) { func libc_fremovexattr_trampoline() -//go:linkname libc_fremovexattr libc_fremovexattr //go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -660,7 +625,6 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro func libc_listxattr_trampoline() -//go:linkname libc_listxattr libc_listxattr //go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -676,7 +640,6 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { func libc_flistxattr_trampoline() -//go:linkname libc_flistxattr libc_flistxattr //go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -691,7 +654,6 @@ func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp func libc_setattrlist_trampoline() -//go:linkname libc_setattrlist libc_setattrlist //go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -707,7 +669,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { func libc_fcntl_trampoline() -//go:linkname libc_fcntl libc_fcntl //go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -722,7 +683,6 @@ func kill(pid int, signum int, posix int) (err error) { func libc_kill_trampoline() -//go:linkname libc_kill libc_kill //go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -737,7 +697,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { func libc_ioctl_trampoline() -//go:linkname libc_ioctl libc_ioctl //go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -758,7 +717,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) func libc_sysctl_trampoline() -//go:linkname libc_sysctl libc_sysctl //go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -773,7 +731,6 @@ func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer func libc_sendfile_trampoline() -//go:linkname libc_sendfile libc_sendfile //go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -793,7 +750,6 @@ func Access(path string, mode uint32) (err error) { func libc_access_trampoline() -//go:linkname libc_access libc_access //go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -808,7 +764,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { func libc_adjtime_trampoline() -//go:linkname libc_adjtime libc_adjtime //go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -828,7 +783,6 @@ func Chdir(path string) (err error) { func libc_chdir_trampoline() -//go:linkname libc_chdir libc_chdir //go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -848,7 +802,6 @@ func Chflags(path string, flags int) (err error) { func libc_chflags_trampoline() -//go:linkname libc_chflags libc_chflags //go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -868,7 +821,6 @@ func Chmod(path string, mode uint32) (err error) { func libc_chmod_trampoline() -//go:linkname libc_chmod libc_chmod //go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -888,7 +840,6 @@ func Chown(path string, uid int, gid int) (err error) { func libc_chown_trampoline() -//go:linkname libc_chown libc_chown //go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -908,7 +859,6 @@ func Chroot(path string) (err error) { func libc_chroot_trampoline() -//go:linkname libc_chroot libc_chroot //go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -923,7 +873,6 @@ func ClockGettime(clockid int32, time *Timespec) (err error) { func libc_clock_gettime_trampoline() -//go:linkname libc_clock_gettime libc_clock_gettime //go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -938,7 +887,6 @@ func Close(fd int) (err error) { func libc_close_trampoline() -//go:linkname libc_close libc_close //go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -963,7 +911,6 @@ func Clonefile(src string, dst string, flags int) (err error) { func libc_clonefile_trampoline() -//go:linkname libc_clonefile libc_clonefile //go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -988,7 +935,6 @@ func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) func libc_clonefileat_trampoline() -//go:linkname libc_clonefileat libc_clonefileat //go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1004,7 +950,6 @@ func Dup(fd int) (nfd int, err error) { func libc_dup_trampoline() -//go:linkname libc_dup libc_dup //go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1019,7 +964,6 @@ func Dup2(from int, to int) (err error) { func libc_dup2_trampoline() -//go:linkname libc_dup2 libc_dup2 //go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1044,7 +988,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) { func libc_exchangedata_trampoline() -//go:linkname libc_exchangedata libc_exchangedata //go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1056,7 +999,6 @@ func Exit(code int) { func libc_exit_trampoline() -//go:linkname libc_exit libc_exit //go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1076,7 +1018,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { func libc_faccessat_trampoline() -//go:linkname libc_faccessat libc_faccessat //go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1091,7 +1032,6 @@ func Fchdir(fd int) (err error) { func libc_fchdir_trampoline() -//go:linkname libc_fchdir libc_fchdir //go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1106,7 +1046,6 @@ func Fchflags(fd int, flags int) (err error) { func libc_fchflags_trampoline() -//go:linkname libc_fchflags libc_fchflags //go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1121,7 +1060,6 @@ func Fchmod(fd int, mode uint32) (err error) { func libc_fchmod_trampoline() -//go:linkname libc_fchmod libc_fchmod //go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1141,7 +1079,6 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { func libc_fchmodat_trampoline() -//go:linkname libc_fchmodat libc_fchmodat //go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1156,7 +1093,6 @@ func Fchown(fd int, uid int, gid int) (err error) { func libc_fchown_trampoline() -//go:linkname libc_fchown libc_fchown //go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1176,7 +1112,6 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { func libc_fchownat_trampoline() -//go:linkname libc_fchownat libc_fchownat //go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1196,7 +1131,6 @@ func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) func libc_fclonefileat_trampoline() -//go:linkname libc_fclonefileat libc_fclonefileat //go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1211,7 +1145,6 @@ func Flock(fd int, how int) (err error) { func libc_flock_trampoline() -//go:linkname libc_flock libc_flock //go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1227,7 +1160,6 @@ func Fpathconf(fd int, name int) (val int, err error) { func libc_fpathconf_trampoline() -//go:linkname libc_fpathconf libc_fpathconf //go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1242,7 +1174,6 @@ func Fsync(fd int) (err error) { func libc_fsync_trampoline() -//go:linkname libc_fsync libc_fsync //go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1257,7 +1188,6 @@ func Ftruncate(fd int, length int64) (err error) { func libc_ftruncate_trampoline() -//go:linkname libc_ftruncate libc_ftruncate //go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1279,7 +1209,6 @@ func Getcwd(buf []byte) (n int, err error) { func libc_getcwd_trampoline() -//go:linkname libc_getcwd libc_getcwd //go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1292,7 +1221,6 @@ func Getdtablesize() (size int) { func libc_getdtablesize_trampoline() -//go:linkname libc_getdtablesize libc_getdtablesize //go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1305,7 +1233,6 @@ func Getegid() (egid int) { func libc_getegid_trampoline() -//go:linkname libc_getegid libc_getegid //go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1318,7 +1245,6 @@ func Geteuid() (uid int) { func libc_geteuid_trampoline() -//go:linkname libc_geteuid libc_geteuid //go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1331,7 +1257,6 @@ func Getgid() (gid int) { func libc_getgid_trampoline() -//go:linkname libc_getgid libc_getgid //go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1347,7 +1272,6 @@ func Getpgid(pid int) (pgid int, err error) { func libc_getpgid_trampoline() -//go:linkname libc_getpgid libc_getpgid //go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1360,7 +1284,6 @@ func Getpgrp() (pgrp int) { func libc_getpgrp_trampoline() -//go:linkname libc_getpgrp libc_getpgrp //go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1373,7 +1296,6 @@ func Getpid() (pid int) { func libc_getpid_trampoline() -//go:linkname libc_getpid libc_getpid //go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1386,7 +1308,6 @@ func Getppid() (ppid int) { func libc_getppid_trampoline() -//go:linkname libc_getppid libc_getppid //go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1402,7 +1323,6 @@ func Getpriority(which int, who int) (prio int, err error) { func libc_getpriority_trampoline() -//go:linkname libc_getpriority libc_getpriority //go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1417,7 +1337,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) { func libc_getrlimit_trampoline() -//go:linkname libc_getrlimit libc_getrlimit //go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1432,7 +1351,6 @@ func Getrusage(who int, rusage *Rusage) (err error) { func libc_getrusage_trampoline() -//go:linkname libc_getrusage libc_getrusage //go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1448,7 +1366,6 @@ func Getsid(pid int) (sid int, err error) { func libc_getsid_trampoline() -//go:linkname libc_getsid libc_getsid //go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1463,7 +1380,6 @@ func Gettimeofday(tp *Timeval) (err error) { func libc_gettimeofday_trampoline() -//go:linkname libc_gettimeofday libc_gettimeofday //go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1476,7 +1392,6 @@ func Getuid() (uid int) { func libc_getuid_trampoline() -//go:linkname libc_getuid libc_getuid //go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1489,7 +1404,6 @@ func Issetugid() (tainted bool) { func libc_issetugid_trampoline() -//go:linkname libc_issetugid libc_issetugid //go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1505,7 +1419,6 @@ func Kqueue() (fd int, err error) { func libc_kqueue_trampoline() -//go:linkname libc_kqueue libc_kqueue //go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1525,7 +1438,6 @@ func Lchown(path string, uid int, gid int) (err error) { func libc_lchown_trampoline() -//go:linkname libc_lchown libc_lchown //go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1550,7 +1462,6 @@ func Link(path string, link string) (err error) { func libc_link_trampoline() -//go:linkname libc_link libc_link //go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1575,7 +1486,6 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er func libc_linkat_trampoline() -//go:linkname libc_linkat libc_linkat //go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1590,7 +1500,6 @@ func Listen(s int, backlog int) (err error) { func libc_listen_trampoline() -//go:linkname libc_listen libc_listen //go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1610,7 +1519,6 @@ func Mkdir(path string, mode uint32) (err error) { func libc_mkdir_trampoline() -//go:linkname libc_mkdir libc_mkdir //go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1630,7 +1538,6 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { func libc_mkdirat_trampoline() -//go:linkname libc_mkdirat libc_mkdirat //go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1650,7 +1557,6 @@ func Mkfifo(path string, mode uint32) (err error) { func libc_mkfifo_trampoline() -//go:linkname libc_mkfifo libc_mkfifo //go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1670,7 +1576,6 @@ func Mknod(path string, mode uint32, dev int) (err error) { func libc_mknod_trampoline() -//go:linkname libc_mknod libc_mknod //go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1691,7 +1596,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { func libc_open_trampoline() -//go:linkname libc_open libc_open //go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1712,7 +1616,6 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { func libc_openat_trampoline() -//go:linkname libc_openat libc_openat //go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1733,7 +1636,6 @@ func Pathconf(path string, name int) (val int, err error) { func libc_pathconf_trampoline() -//go:linkname libc_pathconf libc_pathconf //go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1755,7 +1657,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { func libc_pread_trampoline() -//go:linkname libc_pread libc_pread //go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1777,7 +1678,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { func libc_pwrite_trampoline() -//go:linkname libc_pwrite libc_pwrite //go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1799,7 +1699,6 @@ func read(fd int, p []byte) (n int, err error) { func libc_read_trampoline() -//go:linkname libc_read libc_read //go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1826,7 +1725,6 @@ func Readlink(path string, buf []byte) (n int, err error) { func libc_readlink_trampoline() -//go:linkname libc_readlink libc_readlink //go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1853,7 +1751,6 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { func libc_readlinkat_trampoline() -//go:linkname libc_readlinkat libc_readlinkat //go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1878,7 +1775,6 @@ func Rename(from string, to string) (err error) { func libc_rename_trampoline() -//go:linkname libc_rename libc_rename //go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1903,7 +1799,6 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { func libc_renameat_trampoline() -//go:linkname libc_renameat libc_renameat //go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1923,7 +1818,6 @@ func Revoke(path string) (err error) { func libc_revoke_trampoline() -//go:linkname libc_revoke libc_revoke //go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1943,7 +1837,6 @@ func Rmdir(path string) (err error) { func libc_rmdir_trampoline() -//go:linkname libc_rmdir libc_rmdir //go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1959,7 +1852,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func libc_lseek_trampoline() -//go:linkname libc_lseek libc_lseek //go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1975,7 +1867,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err func libc_select_trampoline() -//go:linkname libc_select libc_select //go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1990,7 +1881,6 @@ func Setegid(egid int) (err error) { func libc_setegid_trampoline() -//go:linkname libc_setegid libc_setegid //go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2005,7 +1895,6 @@ func Seteuid(euid int) (err error) { func libc_seteuid_trampoline() -//go:linkname libc_seteuid libc_seteuid //go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2020,7 +1909,6 @@ func Setgid(gid int) (err error) { func libc_setgid_trampoline() -//go:linkname libc_setgid libc_setgid //go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2040,7 +1928,6 @@ func Setlogin(name string) (err error) { func libc_setlogin_trampoline() -//go:linkname libc_setlogin libc_setlogin //go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2055,7 +1942,6 @@ func Setpgid(pid int, pgid int) (err error) { func libc_setpgid_trampoline() -//go:linkname libc_setpgid libc_setpgid //go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2070,7 +1956,6 @@ func Setpriority(which int, who int, prio int) (err error) { func libc_setpriority_trampoline() -//go:linkname libc_setpriority libc_setpriority //go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2085,7 +1970,6 @@ func Setprivexec(flag int) (err error) { func libc_setprivexec_trampoline() -//go:linkname libc_setprivexec libc_setprivexec //go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2100,7 +1984,6 @@ func Setregid(rgid int, egid int) (err error) { func libc_setregid_trampoline() -//go:linkname libc_setregid libc_setregid //go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2115,7 +1998,6 @@ func Setreuid(ruid int, euid int) (err error) { func libc_setreuid_trampoline() -//go:linkname libc_setreuid libc_setreuid //go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2130,7 +2012,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) { func libc_setrlimit_trampoline() -//go:linkname libc_setrlimit libc_setrlimit //go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2146,7 +2027,6 @@ func Setsid() (pid int, err error) { func libc_setsid_trampoline() -//go:linkname libc_setsid libc_setsid //go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2161,7 +2041,6 @@ func Settimeofday(tp *Timeval) (err error) { func libc_settimeofday_trampoline() -//go:linkname libc_settimeofday libc_settimeofday //go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2176,7 +2055,6 @@ func Setuid(uid int) (err error) { func libc_setuid_trampoline() -//go:linkname libc_setuid libc_setuid //go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2201,7 +2079,6 @@ func Symlink(path string, link string) (err error) { func libc_symlink_trampoline() -//go:linkname libc_symlink libc_symlink //go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2226,7 +2103,6 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { func libc_symlinkat_trampoline() -//go:linkname libc_symlinkat libc_symlinkat //go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2241,7 +2117,6 @@ func Sync() (err error) { func libc_sync_trampoline() -//go:linkname libc_sync libc_sync //go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2261,7 +2136,6 @@ func Truncate(path string, length int64) (err error) { func libc_truncate_trampoline() -//go:linkname libc_truncate libc_truncate //go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2274,7 +2148,6 @@ func Umask(newmask int) (oldmask int) { func libc_umask_trampoline() -//go:linkname libc_umask libc_umask //go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2294,7 +2167,6 @@ func Undelete(path string) (err error) { func libc_undelete_trampoline() -//go:linkname libc_undelete libc_undelete //go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2314,7 +2186,6 @@ func Unlink(path string) (err error) { func libc_unlink_trampoline() -//go:linkname libc_unlink libc_unlink //go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2334,7 +2205,6 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { func libc_unlinkat_trampoline() -//go:linkname libc_unlinkat libc_unlinkat //go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2354,7 +2224,6 @@ func Unmount(path string, flags int) (err error) { func libc_unmount_trampoline() -//go:linkname libc_unmount libc_unmount //go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2376,7 +2245,6 @@ func write(fd int, p []byte) (n int, err error) { func libc_write_trampoline() -//go:linkname libc_write libc_write //go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2392,7 +2260,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( func libc_mmap_trampoline() -//go:linkname libc_mmap libc_mmap //go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2407,7 +2274,6 @@ func munmap(addr uintptr, length uintptr) (err error) { func libc_munmap_trampoline() -//go:linkname libc_munmap libc_munmap //go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2444,7 +2310,6 @@ func Fstat(fd int, stat *Stat_t) (err error) { func libc_fstat_trampoline() -//go:linkname libc_fstat libc_fstat //go:cgo_import_dynamic libc_fstat fstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2464,7 +2329,6 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { func libc_fstatat_trampoline() -//go:linkname libc_fstatat libc_fstatat //go:cgo_import_dynamic libc_fstatat fstatat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2479,7 +2343,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { func libc_fstatfs_trampoline() -//go:linkname libc_fstatfs libc_fstatfs //go:cgo_import_dynamic libc_fstatfs fstatfs "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2495,7 +2358,6 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { func libc_getfsstat_trampoline() -//go:linkname libc_getfsstat libc_getfsstat //go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2515,7 +2377,6 @@ func Lstat(path string, stat *Stat_t) (err error) { func libc_lstat_trampoline() -//go:linkname libc_lstat libc_lstat //go:cgo_import_dynamic libc_lstat lstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2535,7 +2396,6 @@ func Stat(path string, stat *Stat_t) (err error) { func libc_stat_trampoline() -//go:linkname libc_stat libc_stat //go:cgo_import_dynamic libc_stat stat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2555,5 +2415,4 @@ func Statfs(path string, stat *Statfs_t) (err error) { func libc_statfs_trampoline() -//go:linkname libc_statfs libc_statfs //go:cgo_import_dynamic libc_statfs statfs "/usr/lib/libSystem.B.dylib" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go index d64e6c806f..870eb37abf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go @@ -24,7 +24,6 @@ func closedir(dir uintptr) (err error) { func libc_closedir_trampoline() -//go:linkname libc_closedir libc_closedir //go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -37,5 +36,4 @@ func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { func libc_readdir_r_trampoline() -//go:linkname libc_readdir_r libc_readdir_r //go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 23b65a5301..23be592a9f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -25,7 +25,6 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { func libc_getgroups_trampoline() -//go:linkname libc_getgroups libc_getgroups //go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -40,7 +39,6 @@ func setgroups(ngid int, gid *_Gid_t) (err error) { func libc_setgroups_trampoline() -//go:linkname libc_setgroups libc_setgroups //go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -56,7 +54,6 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err func libc_wait4_trampoline() -//go:linkname libc_wait4 libc_wait4 //go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -72,7 +69,6 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { func libc_accept_trampoline() -//go:linkname libc_accept libc_accept //go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -87,7 +83,6 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_bind_trampoline() -//go:linkname libc_bind libc_bind //go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -102,7 +97,6 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func libc_connect_trampoline() -//go:linkname libc_connect libc_connect //go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -118,7 +112,6 @@ func socket(domain int, typ int, proto int) (fd int, err error) { func libc_socket_trampoline() -//go:linkname libc_socket libc_socket //go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -133,7 +126,6 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen func libc_getsockopt_trampoline() -//go:linkname libc_getsockopt libc_getsockopt //go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -148,7 +140,6 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) func libc_setsockopt_trampoline() -//go:linkname libc_setsockopt libc_setsockopt //go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -163,7 +154,6 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getpeername_trampoline() -//go:linkname libc_getpeername libc_getpeername //go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -178,7 +168,6 @@ func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func libc_getsockname_trampoline() -//go:linkname libc_getsockname libc_getsockname //go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -193,7 +182,6 @@ func Shutdown(s int, how int) (err error) { func libc_shutdown_trampoline() -//go:linkname libc_shutdown libc_shutdown //go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -208,7 +196,6 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { func libc_socketpair_trampoline() -//go:linkname libc_socketpair libc_socketpair //go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -230,7 +217,6 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl func libc_recvfrom_trampoline() -//go:linkname libc_recvfrom libc_recvfrom //go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -251,7 +237,6 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( func libc_sendto_trampoline() -//go:linkname libc_sendto libc_sendto //go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -267,7 +252,6 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_recvmsg_trampoline() -//go:linkname libc_recvmsg libc_recvmsg //go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -283,7 +267,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { func libc_sendmsg_trampoline() -//go:linkname libc_sendmsg libc_sendmsg //go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -299,7 +282,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne func libc_kevent_trampoline() -//go:linkname libc_kevent libc_kevent //go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -319,7 +301,6 @@ func utimes(path string, timeval *[2]Timeval) (err error) { func libc_utimes_trampoline() -//go:linkname libc_utimes libc_utimes //go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -334,7 +315,6 @@ func futimes(fd int, timeval *[2]Timeval) (err error) { func libc_futimes_trampoline() -//go:linkname libc_futimes libc_futimes //go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -350,7 +330,6 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { func libc_poll_trampoline() -//go:linkname libc_poll libc_poll //go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -371,7 +350,6 @@ func Madvise(b []byte, behav int) (err error) { func libc_madvise_trampoline() -//go:linkname libc_madvise libc_madvise //go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -392,7 +370,6 @@ func Mlock(b []byte) (err error) { func libc_mlock_trampoline() -//go:linkname libc_mlock libc_mlock //go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -407,7 +384,6 @@ func Mlockall(flags int) (err error) { func libc_mlockall_trampoline() -//go:linkname libc_mlockall libc_mlockall //go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -428,7 +404,6 @@ func Mprotect(b []byte, prot int) (err error) { func libc_mprotect_trampoline() -//go:linkname libc_mprotect libc_mprotect //go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -449,7 +424,6 @@ func Msync(b []byte, flags int) (err error) { func libc_msync_trampoline() -//go:linkname libc_msync libc_msync //go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -470,7 +444,6 @@ func Munlock(b []byte) (err error) { func libc_munlock_trampoline() -//go:linkname libc_munlock libc_munlock //go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -485,7 +458,6 @@ func Munlockall() (err error) { func libc_munlockall_trampoline() -//go:linkname libc_munlockall libc_munlockall //go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -502,7 +474,6 @@ func pipe() (r int, w int, err error) { func libc_pipe_trampoline() -//go:linkname libc_pipe libc_pipe //go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -528,7 +499,6 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o func libc_getxattr_trampoline() -//go:linkname libc_getxattr libc_getxattr //go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -549,7 +519,6 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio func libc_fgetxattr_trampoline() -//go:linkname libc_fgetxattr libc_fgetxattr //go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -574,7 +543,6 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o func libc_setxattr_trampoline() -//go:linkname libc_setxattr libc_setxattr //go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -594,7 +562,6 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio func libc_fsetxattr_trampoline() -//go:linkname libc_fsetxattr libc_fsetxattr //go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -619,7 +586,6 @@ func removexattr(path string, attr string, options int) (err error) { func libc_removexattr_trampoline() -//go:linkname libc_removexattr libc_removexattr //go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -639,7 +605,6 @@ func fremovexattr(fd int, attr string, options int) (err error) { func libc_fremovexattr_trampoline() -//go:linkname libc_fremovexattr libc_fremovexattr //go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -660,7 +625,6 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro func libc_listxattr_trampoline() -//go:linkname libc_listxattr libc_listxattr //go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -676,7 +640,6 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { func libc_flistxattr_trampoline() -//go:linkname libc_flistxattr libc_flistxattr //go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -691,7 +654,6 @@ func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp func libc_setattrlist_trampoline() -//go:linkname libc_setattrlist libc_setattrlist //go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -707,7 +669,6 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { func libc_fcntl_trampoline() -//go:linkname libc_fcntl libc_fcntl //go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -722,7 +683,6 @@ func kill(pid int, signum int, posix int) (err error) { func libc_kill_trampoline() -//go:linkname libc_kill libc_kill //go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -737,7 +697,6 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { func libc_ioctl_trampoline() -//go:linkname libc_ioctl libc_ioctl //go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -758,7 +717,6 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) func libc_sysctl_trampoline() -//go:linkname libc_sysctl libc_sysctl //go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -773,7 +731,6 @@ func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer func libc_sendfile_trampoline() -//go:linkname libc_sendfile libc_sendfile //go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -793,7 +750,6 @@ func Access(path string, mode uint32) (err error) { func libc_access_trampoline() -//go:linkname libc_access libc_access //go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -808,7 +764,6 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { func libc_adjtime_trampoline() -//go:linkname libc_adjtime libc_adjtime //go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -828,7 +783,6 @@ func Chdir(path string) (err error) { func libc_chdir_trampoline() -//go:linkname libc_chdir libc_chdir //go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -848,7 +802,6 @@ func Chflags(path string, flags int) (err error) { func libc_chflags_trampoline() -//go:linkname libc_chflags libc_chflags //go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -868,7 +821,6 @@ func Chmod(path string, mode uint32) (err error) { func libc_chmod_trampoline() -//go:linkname libc_chmod libc_chmod //go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -888,7 +840,6 @@ func Chown(path string, uid int, gid int) (err error) { func libc_chown_trampoline() -//go:linkname libc_chown libc_chown //go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -908,7 +859,6 @@ func Chroot(path string) (err error) { func libc_chroot_trampoline() -//go:linkname libc_chroot libc_chroot //go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -923,7 +873,6 @@ func ClockGettime(clockid int32, time *Timespec) (err error) { func libc_clock_gettime_trampoline() -//go:linkname libc_clock_gettime libc_clock_gettime //go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -938,7 +887,6 @@ func Close(fd int) (err error) { func libc_close_trampoline() -//go:linkname libc_close libc_close //go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -963,7 +911,6 @@ func Clonefile(src string, dst string, flags int) (err error) { func libc_clonefile_trampoline() -//go:linkname libc_clonefile libc_clonefile //go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -988,7 +935,6 @@ func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) func libc_clonefileat_trampoline() -//go:linkname libc_clonefileat libc_clonefileat //go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1004,7 +950,6 @@ func Dup(fd int) (nfd int, err error) { func libc_dup_trampoline() -//go:linkname libc_dup libc_dup //go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1019,7 +964,6 @@ func Dup2(from int, to int) (err error) { func libc_dup2_trampoline() -//go:linkname libc_dup2 libc_dup2 //go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1044,7 +988,6 @@ func Exchangedata(path1 string, path2 string, options int) (err error) { func libc_exchangedata_trampoline() -//go:linkname libc_exchangedata libc_exchangedata //go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1056,7 +999,6 @@ func Exit(code int) { func libc_exit_trampoline() -//go:linkname libc_exit libc_exit //go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1076,7 +1018,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { func libc_faccessat_trampoline() -//go:linkname libc_faccessat libc_faccessat //go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1091,7 +1032,6 @@ func Fchdir(fd int) (err error) { func libc_fchdir_trampoline() -//go:linkname libc_fchdir libc_fchdir //go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1106,7 +1046,6 @@ func Fchflags(fd int, flags int) (err error) { func libc_fchflags_trampoline() -//go:linkname libc_fchflags libc_fchflags //go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1121,7 +1060,6 @@ func Fchmod(fd int, mode uint32) (err error) { func libc_fchmod_trampoline() -//go:linkname libc_fchmod libc_fchmod //go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1141,7 +1079,6 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { func libc_fchmodat_trampoline() -//go:linkname libc_fchmodat libc_fchmodat //go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1156,7 +1093,6 @@ func Fchown(fd int, uid int, gid int) (err error) { func libc_fchown_trampoline() -//go:linkname libc_fchown libc_fchown //go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1176,7 +1112,6 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { func libc_fchownat_trampoline() -//go:linkname libc_fchownat libc_fchownat //go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1196,7 +1131,6 @@ func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) func libc_fclonefileat_trampoline() -//go:linkname libc_fclonefileat libc_fclonefileat //go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1211,7 +1145,6 @@ func Flock(fd int, how int) (err error) { func libc_flock_trampoline() -//go:linkname libc_flock libc_flock //go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1227,7 +1160,6 @@ func Fpathconf(fd int, name int) (val int, err error) { func libc_fpathconf_trampoline() -//go:linkname libc_fpathconf libc_fpathconf //go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1242,7 +1174,6 @@ func Fsync(fd int) (err error) { func libc_fsync_trampoline() -//go:linkname libc_fsync libc_fsync //go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1257,7 +1188,6 @@ func Ftruncate(fd int, length int64) (err error) { func libc_ftruncate_trampoline() -//go:linkname libc_ftruncate libc_ftruncate //go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1279,7 +1209,6 @@ func Getcwd(buf []byte) (n int, err error) { func libc_getcwd_trampoline() -//go:linkname libc_getcwd libc_getcwd //go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1292,7 +1221,6 @@ func Getdtablesize() (size int) { func libc_getdtablesize_trampoline() -//go:linkname libc_getdtablesize libc_getdtablesize //go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1305,7 +1233,6 @@ func Getegid() (egid int) { func libc_getegid_trampoline() -//go:linkname libc_getegid libc_getegid //go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1318,7 +1245,6 @@ func Geteuid() (uid int) { func libc_geteuid_trampoline() -//go:linkname libc_geteuid libc_geteuid //go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1331,7 +1257,6 @@ func Getgid() (gid int) { func libc_getgid_trampoline() -//go:linkname libc_getgid libc_getgid //go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1347,7 +1272,6 @@ func Getpgid(pid int) (pgid int, err error) { func libc_getpgid_trampoline() -//go:linkname libc_getpgid libc_getpgid //go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1360,7 +1284,6 @@ func Getpgrp() (pgrp int) { func libc_getpgrp_trampoline() -//go:linkname libc_getpgrp libc_getpgrp //go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1373,7 +1296,6 @@ func Getpid() (pid int) { func libc_getpid_trampoline() -//go:linkname libc_getpid libc_getpid //go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1386,7 +1308,6 @@ func Getppid() (ppid int) { func libc_getppid_trampoline() -//go:linkname libc_getppid libc_getppid //go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1402,7 +1323,6 @@ func Getpriority(which int, who int) (prio int, err error) { func libc_getpriority_trampoline() -//go:linkname libc_getpriority libc_getpriority //go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1417,7 +1337,6 @@ func Getrlimit(which int, lim *Rlimit) (err error) { func libc_getrlimit_trampoline() -//go:linkname libc_getrlimit libc_getrlimit //go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1432,7 +1351,6 @@ func Getrusage(who int, rusage *Rusage) (err error) { func libc_getrusage_trampoline() -//go:linkname libc_getrusage libc_getrusage //go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1448,7 +1366,6 @@ func Getsid(pid int) (sid int, err error) { func libc_getsid_trampoline() -//go:linkname libc_getsid libc_getsid //go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1463,7 +1380,6 @@ func Gettimeofday(tp *Timeval) (err error) { func libc_gettimeofday_trampoline() -//go:linkname libc_gettimeofday libc_gettimeofday //go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1476,7 +1392,6 @@ func Getuid() (uid int) { func libc_getuid_trampoline() -//go:linkname libc_getuid libc_getuid //go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1489,7 +1404,6 @@ func Issetugid() (tainted bool) { func libc_issetugid_trampoline() -//go:linkname libc_issetugid libc_issetugid //go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1505,7 +1419,6 @@ func Kqueue() (fd int, err error) { func libc_kqueue_trampoline() -//go:linkname libc_kqueue libc_kqueue //go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1525,7 +1438,6 @@ func Lchown(path string, uid int, gid int) (err error) { func libc_lchown_trampoline() -//go:linkname libc_lchown libc_lchown //go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1550,7 +1462,6 @@ func Link(path string, link string) (err error) { func libc_link_trampoline() -//go:linkname libc_link libc_link //go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1575,7 +1486,6 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er func libc_linkat_trampoline() -//go:linkname libc_linkat libc_linkat //go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1590,7 +1500,6 @@ func Listen(s int, backlog int) (err error) { func libc_listen_trampoline() -//go:linkname libc_listen libc_listen //go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1610,7 +1519,6 @@ func Mkdir(path string, mode uint32) (err error) { func libc_mkdir_trampoline() -//go:linkname libc_mkdir libc_mkdir //go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1630,7 +1538,6 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { func libc_mkdirat_trampoline() -//go:linkname libc_mkdirat libc_mkdirat //go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1650,7 +1557,6 @@ func Mkfifo(path string, mode uint32) (err error) { func libc_mkfifo_trampoline() -//go:linkname libc_mkfifo libc_mkfifo //go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1670,7 +1576,6 @@ func Mknod(path string, mode uint32, dev int) (err error) { func libc_mknod_trampoline() -//go:linkname libc_mknod libc_mknod //go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1691,7 +1596,6 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { func libc_open_trampoline() -//go:linkname libc_open libc_open //go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1712,7 +1616,6 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { func libc_openat_trampoline() -//go:linkname libc_openat libc_openat //go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1733,7 +1636,6 @@ func Pathconf(path string, name int) (val int, err error) { func libc_pathconf_trampoline() -//go:linkname libc_pathconf libc_pathconf //go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1755,7 +1657,6 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { func libc_pread_trampoline() -//go:linkname libc_pread libc_pread //go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1777,7 +1678,6 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { func libc_pwrite_trampoline() -//go:linkname libc_pwrite libc_pwrite //go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1799,7 +1699,6 @@ func read(fd int, p []byte) (n int, err error) { func libc_read_trampoline() -//go:linkname libc_read libc_read //go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1826,7 +1725,6 @@ func Readlink(path string, buf []byte) (n int, err error) { func libc_readlink_trampoline() -//go:linkname libc_readlink libc_readlink //go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1853,7 +1751,6 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { func libc_readlinkat_trampoline() -//go:linkname libc_readlinkat libc_readlinkat //go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1878,7 +1775,6 @@ func Rename(from string, to string) (err error) { func libc_rename_trampoline() -//go:linkname libc_rename libc_rename //go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1903,7 +1799,6 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { func libc_renameat_trampoline() -//go:linkname libc_renameat libc_renameat //go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1923,7 +1818,6 @@ func Revoke(path string) (err error) { func libc_revoke_trampoline() -//go:linkname libc_revoke libc_revoke //go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1943,7 +1837,6 @@ func Rmdir(path string) (err error) { func libc_rmdir_trampoline() -//go:linkname libc_rmdir libc_rmdir //go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1959,7 +1852,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func libc_lseek_trampoline() -//go:linkname libc_lseek libc_lseek //go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1975,7 +1867,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err func libc_select_trampoline() -//go:linkname libc_select libc_select //go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1990,7 +1881,6 @@ func Setegid(egid int) (err error) { func libc_setegid_trampoline() -//go:linkname libc_setegid libc_setegid //go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2005,7 +1895,6 @@ func Seteuid(euid int) (err error) { func libc_seteuid_trampoline() -//go:linkname libc_seteuid libc_seteuid //go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2020,7 +1909,6 @@ func Setgid(gid int) (err error) { func libc_setgid_trampoline() -//go:linkname libc_setgid libc_setgid //go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2040,7 +1928,6 @@ func Setlogin(name string) (err error) { func libc_setlogin_trampoline() -//go:linkname libc_setlogin libc_setlogin //go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2055,7 +1942,6 @@ func Setpgid(pid int, pgid int) (err error) { func libc_setpgid_trampoline() -//go:linkname libc_setpgid libc_setpgid //go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2070,7 +1956,6 @@ func Setpriority(which int, who int, prio int) (err error) { func libc_setpriority_trampoline() -//go:linkname libc_setpriority libc_setpriority //go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2085,7 +1970,6 @@ func Setprivexec(flag int) (err error) { func libc_setprivexec_trampoline() -//go:linkname libc_setprivexec libc_setprivexec //go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2100,7 +1984,6 @@ func Setregid(rgid int, egid int) (err error) { func libc_setregid_trampoline() -//go:linkname libc_setregid libc_setregid //go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2115,7 +1998,6 @@ func Setreuid(ruid int, euid int) (err error) { func libc_setreuid_trampoline() -//go:linkname libc_setreuid libc_setreuid //go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2130,7 +2012,6 @@ func Setrlimit(which int, lim *Rlimit) (err error) { func libc_setrlimit_trampoline() -//go:linkname libc_setrlimit libc_setrlimit //go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2146,7 +2027,6 @@ func Setsid() (pid int, err error) { func libc_setsid_trampoline() -//go:linkname libc_setsid libc_setsid //go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2161,7 +2041,6 @@ func Settimeofday(tp *Timeval) (err error) { func libc_settimeofday_trampoline() -//go:linkname libc_settimeofday libc_settimeofday //go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2176,7 +2055,6 @@ func Setuid(uid int) (err error) { func libc_setuid_trampoline() -//go:linkname libc_setuid libc_setuid //go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2201,7 +2079,6 @@ func Symlink(path string, link string) (err error) { func libc_symlink_trampoline() -//go:linkname libc_symlink libc_symlink //go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2226,7 +2103,6 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { func libc_symlinkat_trampoline() -//go:linkname libc_symlinkat libc_symlinkat //go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2241,7 +2117,6 @@ func Sync() (err error) { func libc_sync_trampoline() -//go:linkname libc_sync libc_sync //go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2261,7 +2136,6 @@ func Truncate(path string, length int64) (err error) { func libc_truncate_trampoline() -//go:linkname libc_truncate libc_truncate //go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2274,7 +2148,6 @@ func Umask(newmask int) (oldmask int) { func libc_umask_trampoline() -//go:linkname libc_umask libc_umask //go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2294,7 +2167,6 @@ func Undelete(path string) (err error) { func libc_undelete_trampoline() -//go:linkname libc_undelete libc_undelete //go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2314,7 +2186,6 @@ func Unlink(path string) (err error) { func libc_unlink_trampoline() -//go:linkname libc_unlink libc_unlink //go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2334,7 +2205,6 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { func libc_unlinkat_trampoline() -//go:linkname libc_unlinkat libc_unlinkat //go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2354,7 +2224,6 @@ func Unmount(path string, flags int) (err error) { func libc_unmount_trampoline() -//go:linkname libc_unmount libc_unmount //go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2376,7 +2245,6 @@ func write(fd int, p []byte) (n int, err error) { func libc_write_trampoline() -//go:linkname libc_write libc_write //go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2392,7 +2260,6 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( func libc_mmap_trampoline() -//go:linkname libc_mmap libc_mmap //go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2407,7 +2274,6 @@ func munmap(addr uintptr, length uintptr) (err error) { func libc_munmap_trampoline() -//go:linkname libc_munmap libc_munmap //go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2444,7 +2310,6 @@ func Fstat(fd int, stat *Stat_t) (err error) { func libc_fstat_trampoline() -//go:linkname libc_fstat libc_fstat //go:cgo_import_dynamic libc_fstat fstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2464,7 +2329,6 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { func libc_fstatat_trampoline() -//go:linkname libc_fstatat libc_fstatat //go:cgo_import_dynamic libc_fstatat fstatat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2479,7 +2343,6 @@ func Fstatfs(fd int, stat *Statfs_t) (err error) { func libc_fstatfs_trampoline() -//go:linkname libc_fstatfs libc_fstatfs //go:cgo_import_dynamic libc_fstatfs fstatfs "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2495,7 +2358,6 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { func libc_getfsstat_trampoline() -//go:linkname libc_getfsstat libc_getfsstat //go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2515,7 +2377,6 @@ func Lstat(path string, stat *Stat_t) (err error) { func libc_lstat_trampoline() -//go:linkname libc_lstat libc_lstat //go:cgo_import_dynamic libc_lstat lstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2530,7 +2391,6 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func libc_ptrace_trampoline() -//go:linkname libc_ptrace libc_ptrace //go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2550,7 +2410,6 @@ func Stat(path string, stat *Stat_t) (err error) { func libc_stat_trampoline() -//go:linkname libc_stat libc_stat //go:cgo_import_dynamic libc_stat stat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2570,5 +2429,4 @@ func Statfs(path string, stat *Statfs_t) (err error) { func libc_statfs_trampoline() -//go:linkname libc_statfs libc_statfs //go:cgo_import_dynamic libc_statfs statfs "/usr/lib/libSystem.B.dylib" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index aebfe511ad..1aaccd3615 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -362,6 +362,16 @@ func pipe() (r int, w int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func extpread(fd int, p []byte, flags int, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go index 830fbb35c0..725b4bee27 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go @@ -269,6 +269,7 @@ const ( SizeofSockaddrDatalink = 0x14 SizeofSockaddrCtl = 0x20 SizeofLinger = 0x8 + SizeofIovec = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index e53a7c49ff..080ffce325 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -274,6 +274,7 @@ const ( SizeofSockaddrDatalink = 0x14 SizeofSockaddrCtl = 0x20 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go index 98be973ef9..f2a77bc4e2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go @@ -269,6 +269,7 @@ const ( SizeofSockaddrDatalink = 0x14 SizeofSockaddrCtl = 0x20 SizeofLinger = 0x8 + SizeofIovec = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index ddae5afe1b..c9492428bf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -274,6 +274,7 @@ const ( SizeofSockaddrDatalink = 0x14 SizeofSockaddrCtl = 0x20 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go index a96ad4c299..504ef131fb 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -2981,3 +2981,21 @@ type PPSKTime struct { Nsec int32 Flags uint32 } + +const ( + LWTUNNEL_ENCAP_NONE = 0x0 + LWTUNNEL_ENCAP_MPLS = 0x1 + LWTUNNEL_ENCAP_IP = 0x2 + LWTUNNEL_ENCAP_ILA = 0x3 + LWTUNNEL_ENCAP_IP6 = 0x4 + LWTUNNEL_ENCAP_SEG6 = 0x5 + LWTUNNEL_ENCAP_BPF = 0x6 + LWTUNNEL_ENCAP_SEG6_LOCAL = 0x7 + LWTUNNEL_ENCAP_RPL = 0x8 + LWTUNNEL_ENCAP_MAX = 0x8 + + MPLS_IPTUNNEL_UNSPEC = 0x0 + MPLS_IPTUNNEL_DST = 0x1 + MPLS_IPTUNNEL_TTL = 0x2 + MPLS_IPTUNNEL_MAX = 0x2 +) diff --git a/src/cmd/vendor/golang.org/x/sys/windows/dll_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/dll_windows.go index 82076fb74f..115341fba6 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/dll_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/dll_windows.go @@ -32,6 +32,8 @@ type DLLError struct { func (e *DLLError) Error() string { return e.Msg } +func (e *DLLError) Unwrap() error { return e.Err } + // A DLL implements access to a single DLL. type DLL struct { Name string @@ -389,7 +391,6 @@ func loadLibraryEx(name string, system bool) (*DLL, error) { var flags uintptr if system { if canDoSearchSystem32() { - const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 flags = LOAD_LIBRARY_SEARCH_SYSTEM32 } else if isBaseName(name) { // WindowsXP or unpatched Windows machine diff --git a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go index 9e3c44a855..69eb462c59 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go @@ -624,6 +624,7 @@ func (tml *Tokenmandatorylabel) Size() uint32 { // Authorization Functions //sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership +//sys isTokenRestricted(tokenHandle Token) (ret bool, err error) [!failretval] = advapi32.IsTokenRestricted //sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken //sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken //sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf @@ -837,6 +838,16 @@ func (t Token) IsMember(sid *SID) (bool, error) { return b != 0, nil } +// IsRestricted reports whether the access token t is a restricted token. +func (t Token) IsRestricted() (isRestricted bool, err error) { + isRestricted, err = isTokenRestricted(t) + if !isRestricted && err == syscall.EINVAL { + // If err is EINVAL, this returned ERROR_SUCCESS indicating a non-restricted token. + err = nil + } + return +} + const ( WTS_CONSOLE_CONNECT = 0x1 WTS_CONSOLE_DISCONNECT = 0x2 @@ -1103,9 +1114,10 @@ type OBJECTS_AND_NAME struct { } //sys getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetSecurityInfo -//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) = advapi32.SetSecurityInfo +//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetSecurityInfo //sys getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetNamedSecurityInfoW //sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW +//sys SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) = advapi32.SetKernelObjectSecurity //sys buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) = advapi32.BuildSecurityDescriptorW //sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor diff --git a/src/cmd/vendor/golang.org/x/sys/windows/service.go b/src/cmd/vendor/golang.org/x/sys/windows/service.go index f54ff90aac..b269850d06 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/service.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/service.go @@ -128,6 +128,10 @@ const ( SERVICE_NOTIFY_CREATED = 0x00000080 SERVICE_NOTIFY_DELETED = 0x00000100 SERVICE_NOTIFY_DELETE_PENDING = 0x00000200 + + SC_EVENT_DATABASE_CHANGE = 0 + SC_EVENT_PROPERTY_CHANGE = 1 + SC_EVENT_STATUS_CHANGE = 2 ) type SERVICE_STATUS struct { @@ -229,3 +233,5 @@ type QUERY_SERVICE_LOCK_STATUS struct { //sys EnumServicesStatusEx(mgr Handle, infoLevel uint32, serviceType uint32, serviceState uint32, services *byte, bufSize uint32, bytesNeeded *uint32, servicesReturned *uint32, resumeHandle *uint32, groupName *uint16) (err error) = advapi32.EnumServicesStatusExW //sys QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceStatusEx //sys NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) = advapi32.NotifyServiceStatusChangeW +//sys SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) = sechost.SubscribeServiceChangeNotifications? +//sys UnsubscribeServiceChangeNotifications(subscription uintptr) = sechost.UnsubscribeServiceChangeNotifications? diff --git a/src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go new file mode 100644 index 0000000000..1681810e04 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go @@ -0,0 +1,100 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package windows + +import "syscall" + +const ( + ERROR_EXPECTED_SECTION_NAME syscall.Errno = 0x20000000 | 0xC0000000 | 0 + ERROR_BAD_SECTION_NAME_LINE syscall.Errno = 0x20000000 | 0xC0000000 | 1 + ERROR_SECTION_NAME_TOO_LONG syscall.Errno = 0x20000000 | 0xC0000000 | 2 + ERROR_GENERAL_SYNTAX syscall.Errno = 0x20000000 | 0xC0000000 | 3 + ERROR_WRONG_INF_STYLE syscall.Errno = 0x20000000 | 0xC0000000 | 0x100 + ERROR_SECTION_NOT_FOUND syscall.Errno = 0x20000000 | 0xC0000000 | 0x101 + ERROR_LINE_NOT_FOUND syscall.Errno = 0x20000000 | 0xC0000000 | 0x102 + ERROR_NO_BACKUP syscall.Errno = 0x20000000 | 0xC0000000 | 0x103 + ERROR_NO_ASSOCIATED_CLASS syscall.Errno = 0x20000000 | 0xC0000000 | 0x200 + ERROR_CLASS_MISMATCH syscall.Errno = 0x20000000 | 0xC0000000 | 0x201 + ERROR_DUPLICATE_FOUND syscall.Errno = 0x20000000 | 0xC0000000 | 0x202 + ERROR_NO_DRIVER_SELECTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x203 + ERROR_KEY_DOES_NOT_EXIST syscall.Errno = 0x20000000 | 0xC0000000 | 0x204 + ERROR_INVALID_DEVINST_NAME syscall.Errno = 0x20000000 | 0xC0000000 | 0x205 + ERROR_INVALID_CLASS syscall.Errno = 0x20000000 | 0xC0000000 | 0x206 + ERROR_DEVINST_ALREADY_EXISTS syscall.Errno = 0x20000000 | 0xC0000000 | 0x207 + ERROR_DEVINFO_NOT_REGISTERED syscall.Errno = 0x20000000 | 0xC0000000 | 0x208 + ERROR_INVALID_REG_PROPERTY syscall.Errno = 0x20000000 | 0xC0000000 | 0x209 + ERROR_NO_INF syscall.Errno = 0x20000000 | 0xC0000000 | 0x20A + ERROR_NO_SUCH_DEVINST syscall.Errno = 0x20000000 | 0xC0000000 | 0x20B + ERROR_CANT_LOAD_CLASS_ICON syscall.Errno = 0x20000000 | 0xC0000000 | 0x20C + ERROR_INVALID_CLASS_INSTALLER syscall.Errno = 0x20000000 | 0xC0000000 | 0x20D + ERROR_DI_DO_DEFAULT syscall.Errno = 0x20000000 | 0xC0000000 | 0x20E + ERROR_DI_NOFILECOPY syscall.Errno = 0x20000000 | 0xC0000000 | 0x20F + ERROR_INVALID_HWPROFILE syscall.Errno = 0x20000000 | 0xC0000000 | 0x210 + ERROR_NO_DEVICE_SELECTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x211 + ERROR_DEVINFO_LIST_LOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x212 + ERROR_DEVINFO_DATA_LOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x213 + ERROR_DI_BAD_PATH syscall.Errno = 0x20000000 | 0xC0000000 | 0x214 + ERROR_NO_CLASSINSTALL_PARAMS syscall.Errno = 0x20000000 | 0xC0000000 | 0x215 + ERROR_FILEQUEUE_LOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x216 + ERROR_BAD_SERVICE_INSTALLSECT syscall.Errno = 0x20000000 | 0xC0000000 | 0x217 + ERROR_NO_CLASS_DRIVER_LIST syscall.Errno = 0x20000000 | 0xC0000000 | 0x218 + ERROR_NO_ASSOCIATED_SERVICE syscall.Errno = 0x20000000 | 0xC0000000 | 0x219 + ERROR_NO_DEFAULT_DEVICE_INTERFACE syscall.Errno = 0x20000000 | 0xC0000000 | 0x21A + ERROR_DEVICE_INTERFACE_ACTIVE syscall.Errno = 0x20000000 | 0xC0000000 | 0x21B + ERROR_DEVICE_INTERFACE_REMOVED syscall.Errno = 0x20000000 | 0xC0000000 | 0x21C + ERROR_BAD_INTERFACE_INSTALLSECT syscall.Errno = 0x20000000 | 0xC0000000 | 0x21D + ERROR_NO_SUCH_INTERFACE_CLASS syscall.Errno = 0x20000000 | 0xC0000000 | 0x21E + ERROR_INVALID_REFERENCE_STRING syscall.Errno = 0x20000000 | 0xC0000000 | 0x21F + ERROR_INVALID_MACHINENAME syscall.Errno = 0x20000000 | 0xC0000000 | 0x220 + ERROR_REMOTE_COMM_FAILURE syscall.Errno = 0x20000000 | 0xC0000000 | 0x221 + ERROR_MACHINE_UNAVAILABLE syscall.Errno = 0x20000000 | 0xC0000000 | 0x222 + ERROR_NO_CONFIGMGR_SERVICES syscall.Errno = 0x20000000 | 0xC0000000 | 0x223 + ERROR_INVALID_PROPPAGE_PROVIDER syscall.Errno = 0x20000000 | 0xC0000000 | 0x224 + ERROR_NO_SUCH_DEVICE_INTERFACE syscall.Errno = 0x20000000 | 0xC0000000 | 0x225 + ERROR_DI_POSTPROCESSING_REQUIRED syscall.Errno = 0x20000000 | 0xC0000000 | 0x226 + ERROR_INVALID_COINSTALLER syscall.Errno = 0x20000000 | 0xC0000000 | 0x227 + ERROR_NO_COMPAT_DRIVERS syscall.Errno = 0x20000000 | 0xC0000000 | 0x228 + ERROR_NO_DEVICE_ICON syscall.Errno = 0x20000000 | 0xC0000000 | 0x229 + ERROR_INVALID_INF_LOGCONFIG syscall.Errno = 0x20000000 | 0xC0000000 | 0x22A + ERROR_DI_DONT_INSTALL syscall.Errno = 0x20000000 | 0xC0000000 | 0x22B + ERROR_INVALID_FILTER_DRIVER syscall.Errno = 0x20000000 | 0xC0000000 | 0x22C + ERROR_NON_WINDOWS_NT_DRIVER syscall.Errno = 0x20000000 | 0xC0000000 | 0x22D + ERROR_NON_WINDOWS_DRIVER syscall.Errno = 0x20000000 | 0xC0000000 | 0x22E + ERROR_NO_CATALOG_FOR_OEM_INF syscall.Errno = 0x20000000 | 0xC0000000 | 0x22F + ERROR_DEVINSTALL_QUEUE_NONNATIVE syscall.Errno = 0x20000000 | 0xC0000000 | 0x230 + ERROR_NOT_DISABLEABLE syscall.Errno = 0x20000000 | 0xC0000000 | 0x231 + ERROR_CANT_REMOVE_DEVINST syscall.Errno = 0x20000000 | 0xC0000000 | 0x232 + ERROR_INVALID_TARGET syscall.Errno = 0x20000000 | 0xC0000000 | 0x233 + ERROR_DRIVER_NONNATIVE syscall.Errno = 0x20000000 | 0xC0000000 | 0x234 + ERROR_IN_WOW64 syscall.Errno = 0x20000000 | 0xC0000000 | 0x235 + ERROR_SET_SYSTEM_RESTORE_POINT syscall.Errno = 0x20000000 | 0xC0000000 | 0x236 + ERROR_SCE_DISABLED syscall.Errno = 0x20000000 | 0xC0000000 | 0x238 + ERROR_UNKNOWN_EXCEPTION syscall.Errno = 0x20000000 | 0xC0000000 | 0x239 + ERROR_PNP_REGISTRY_ERROR syscall.Errno = 0x20000000 | 0xC0000000 | 0x23A + ERROR_REMOTE_REQUEST_UNSUPPORTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x23B + ERROR_NOT_AN_INSTALLED_OEM_INF syscall.Errno = 0x20000000 | 0xC0000000 | 0x23C + ERROR_INF_IN_USE_BY_DEVICES syscall.Errno = 0x20000000 | 0xC0000000 | 0x23D + ERROR_DI_FUNCTION_OBSOLETE syscall.Errno = 0x20000000 | 0xC0000000 | 0x23E + ERROR_NO_AUTHENTICODE_CATALOG syscall.Errno = 0x20000000 | 0xC0000000 | 0x23F + ERROR_AUTHENTICODE_DISALLOWED syscall.Errno = 0x20000000 | 0xC0000000 | 0x240 + ERROR_AUTHENTICODE_TRUSTED_PUBLISHER syscall.Errno = 0x20000000 | 0xC0000000 | 0x241 + ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED syscall.Errno = 0x20000000 | 0xC0000000 | 0x242 + ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x243 + ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH syscall.Errno = 0x20000000 | 0xC0000000 | 0x244 + ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE syscall.Errno = 0x20000000 | 0xC0000000 | 0x245 + ERROR_DEVICE_INSTALLER_NOT_READY syscall.Errno = 0x20000000 | 0xC0000000 | 0x246 + ERROR_DRIVER_STORE_ADD_FAILED syscall.Errno = 0x20000000 | 0xC0000000 | 0x247 + ERROR_DEVICE_INSTALL_BLOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x248 + ERROR_DRIVER_INSTALL_BLOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x249 + ERROR_WRONG_INF_TYPE syscall.Errno = 0x20000000 | 0xC0000000 | 0x24A + ERROR_FILE_HASH_NOT_IN_CATALOG syscall.Errno = 0x20000000 | 0xC0000000 | 0x24B + ERROR_DRIVER_STORE_DELETE_FAILED syscall.Errno = 0x20000000 | 0xC0000000 | 0x24C + ERROR_UNRECOVERABLE_STACK_OVERFLOW syscall.Errno = 0x20000000 | 0xC0000000 | 0x300 + EXCEPTION_SPAPI_UNRECOVERABLE_STACK_OVERFLOW syscall.Errno = ERROR_UNRECOVERABLE_STACK_OVERFLOW + ERROR_NO_DEFAULT_INTERFACE_DEVICE syscall.Errno = ERROR_NO_DEFAULT_DEVICE_INTERFACE + ERROR_INTERFACE_DEVICE_ACTIVE syscall.Errno = ERROR_DEVICE_INTERFACE_ACTIVE + ERROR_INTERFACE_DEVICE_REMOVED syscall.Errno = ERROR_DEVICE_INTERFACE_REMOVED + ERROR_NO_SUCH_INTERFACE_DEVICE syscall.Errno = ERROR_NO_SUCH_DEVICE_INTERFACE +) diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go index 008ffc11a0..c71bad127d 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -170,10 +170,13 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys GetProcAddress(module Handle, procname string) (proc uintptr, err error) //sys GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) = kernel32.GetModuleFileNameW //sys GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) = kernel32.GetModuleHandleExW +//sys SetDefaultDllDirectories(directoryFlags uint32) (err error) +//sys SetDllDirectory(path string) (err error) = kernel32.SetDllDirectoryW //sys GetVersion() (ver uint32, err error) //sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW //sys ExitProcess(exitcode uint32) //sys IsWow64Process(handle Handle, isWow64 *bool) (err error) = IsWow64Process +//sys IsWow64Process2(handle Handle, processMachine *uint16, nativeMachine *uint16) (err error) = IsWow64Process2? //sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW //sys ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) //sys WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) @@ -187,6 +190,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys FindClose(handle Handle) (err error) //sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) //sys GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, outBufferLen uint32) (err error) +//sys SetFileInformationByHandle(handle Handle, class uint32, inBuffer *byte, inBufferLen uint32) (err error) //sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW //sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW //sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW @@ -243,6 +247,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW //sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW //sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW +//sys GetFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW //sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW //sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) //sys UnmapViewOfFile(addr uintptr) (err error) @@ -255,7 +260,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile //sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW //sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW -//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore +//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) = crypt32.CertOpenStore //sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore //sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore //sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore @@ -351,7 +356,6 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetThreadPreferredUILanguages //sys getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetUserPreferredUILanguages //sys getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetSystemPreferredUILanguages -//sys GetFinalPathNameByHandleW(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW // Process Status API (PSAPI) //sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses diff --git a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go index da1652e74b..265d797cac 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go @@ -1772,3 +1772,51 @@ const ( MUI_LANGUAGE_INSTALLED = 0x20 MUI_LANGUAGE_LICENSED = 0x40 ) + +// FILE_INFO_BY_HANDLE_CLASS constants for SetFileInformationByHandle/GetFileInformationByHandleEx +const ( + FileBasicInfo = 0 + FileStandardInfo = 1 + FileNameInfo = 2 + FileRenameInfo = 3 + FileDispositionInfo = 4 + FileAllocationInfo = 5 + FileEndOfFileInfo = 6 + FileStreamInfo = 7 + FileCompressionInfo = 8 + FileAttributeTagInfo = 9 + FileIdBothDirectoryInfo = 10 + FileIdBothDirectoryRestartInfo = 11 + FileIoPriorityHintInfo = 12 + FileRemoteProtocolInfo = 13 + FileFullDirectoryInfo = 14 + FileFullDirectoryRestartInfo = 15 + FileStorageInfo = 16 + FileAlignmentInfo = 17 + FileIdInfo = 18 + FileIdExtdDirectoryInfo = 19 + FileIdExtdDirectoryRestartInfo = 20 + FileDispositionInfoEx = 21 + FileRenameInfoEx = 22 + FileCaseSensitiveInfo = 23 + FileNormalizedNameInfo = 24 +) + +// LoadLibrary flags for determining from where to search for a DLL +const ( + DONT_RESOLVE_DLL_REFERENCES = 0x1 + LOAD_LIBRARY_AS_DATAFILE = 0x2 + LOAD_WITH_ALTERED_SEARCH_PATH = 0x8 + LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x10 + LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x20 + LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x40 + LOAD_LIBRARY_REQUIRE_SIGNED_TARGET = 0x80 + LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100 + LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x200 + LOAD_LIBRARY_SEARCH_USER_DIRS = 0x400 + LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x800 + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000 + LOAD_LIBRARY_SAFE_CURRENT_DIRS = 0x00002000 + LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER = 0x00004000 + LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY = 0x00008000 +) diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go index d400c3512d..a933c0ee37 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -46,6 +46,7 @@ var ( modntdll = NewLazySystemDLL("ntdll.dll") modole32 = NewLazySystemDLL("ole32.dll") modpsapi = NewLazySystemDLL("psapi.dll") + modsechost = NewLazySystemDLL("sechost.dll") modsecur32 = NewLazySystemDLL("secur32.dll") modshell32 = NewLazySystemDLL("shell32.dll") moduser32 = NewLazySystemDLL("user32.dll") @@ -95,6 +96,7 @@ var ( procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") procInitializeSecurityDescriptor = modadvapi32.NewProc("InitializeSecurityDescriptor") procInitiateSystemShutdownExW = modadvapi32.NewProc("InitiateSystemShutdownExW") + procIsTokenRestricted = modadvapi32.NewProc("IsTokenRestricted") procIsValidSecurityDescriptor = modadvapi32.NewProc("IsValidSecurityDescriptor") procIsValidSid = modadvapi32.NewProc("IsValidSid") procIsWellKnownSid = modadvapi32.NewProc("IsWellKnownSid") @@ -122,6 +124,7 @@ var ( procReportEventW = modadvapi32.NewProc("ReportEventW") procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW") + procSetKernelObjectSecurity = modadvapi32.NewProc("SetKernelObjectSecurity") procSetNamedSecurityInfoW = modadvapi32.NewProc("SetNamedSecurityInfoW") procSetSecurityDescriptorControl = modadvapi32.NewProc("SetSecurityDescriptorControl") procSetSecurityDescriptorDacl = modadvapi32.NewProc("SetSecurityDescriptorDacl") @@ -248,6 +251,7 @@ var ( procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW") procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW") procIsWow64Process = modkernel32.NewProc("IsWow64Process") + procIsWow64Process2 = modkernel32.NewProc("IsWow64Process2") procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW") procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") procLocalFree = modkernel32.NewProc("LocalFree") @@ -277,12 +281,15 @@ var ( procSetConsoleCursorPosition = modkernel32.NewProc("SetConsoleCursorPosition") procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") + procSetDefaultDllDirectories = modkernel32.NewProc("SetDefaultDllDirectories") + procSetDllDirectoryW = modkernel32.NewProc("SetDllDirectoryW") procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") procSetErrorMode = modkernel32.NewProc("SetErrorMode") procSetEvent = modkernel32.NewProc("SetEvent") procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") procSetFilePointer = modkernel32.NewProc("SetFilePointer") procSetFileTime = modkernel32.NewProc("SetFileTime") procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") @@ -323,6 +330,8 @@ var ( procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") procStringFromGUID2 = modole32.NewProc("StringFromGUID2") procEnumProcesses = modpsapi.NewProc("EnumProcesses") + procSubscribeServiceChangeNotifications = modsechost.NewProc("SubscribeServiceChangeNotifications") + procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications") procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") procTranslateNameW = modsecur32.NewProc("TranslateNameW") procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") @@ -753,6 +762,15 @@ func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint return } +func isTokenRestricted(tokenHandle Token) (ret bool, err error) { + r0, _, e1 := syscall.Syscall(procIsTokenRestricted.Addr(), 1, uintptr(tokenHandle), 0, 0) + ret = r0 != 0 + if !ret { + err = errnoErr(e1) + } + return +} + func isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) { r0, _, _ := syscall.Syscall(procIsValidSecurityDescriptor.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) isValid = r0 != 0 @@ -970,6 +988,14 @@ func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCE return } +func SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) { + r1, _, e1 := syscall.Syscall(procSetKernelObjectSecurity.Addr(), 3, uintptr(handle), uintptr(securityInformation), uintptr(unsafe.Pointer(securityDescriptor))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { var _p0 *uint16 _p0, ret = syscall.UTF16PtrFromString(objectName) @@ -1056,8 +1082,11 @@ func setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl * return } -func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) { - syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) +func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { + r0, _, _ := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } return } @@ -1167,7 +1196,7 @@ func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, a func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) { r0, _, e1 := syscall.Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0) handle = Handle(r0) - if handle == InvalidHandle { + if handle == 0 { err = errnoErr(e1) } return @@ -1727,7 +1756,7 @@ func GetFileType(filehandle Handle) (n uint32, err error) { return } -func GetFinalPathNameByHandleW(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) { +func GetFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) { r0, _, e1 := syscall.Syscall6(procGetFinalPathNameByHandleW.Addr(), 4, uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags), 0, 0) n = uint32(r0) if n == 0 { @@ -2055,6 +2084,18 @@ func IsWow64Process(handle Handle, isWow64 *bool) (err error) { return } +func IsWow64Process2(handle Handle, processMachine *uint16, nativeMachine *uint16) (err error) { + err = procIsWow64Process2.Find() + if err != nil { + return + } + r1, _, e1 := syscall.Syscall(procIsWow64Process2.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(processMachine)), uintptr(unsafe.Pointer(nativeMachine))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) { var _p0 *uint16 _p0, err = syscall.UTF16PtrFromString(libname) @@ -2340,6 +2381,31 @@ func SetCurrentDirectory(path *uint16) (err error) { return } +func SetDefaultDllDirectories(directoryFlags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetDefaultDllDirectories.Addr(), 1, uintptr(directoryFlags), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetDllDirectory(path string) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(path) + if err != nil { + return + } + return _SetDllDirectory(_p0) +} + +func _SetDllDirectory(path *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procSetDllDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SetEndOfFile(handle Handle) (err error) { r1, _, e1 := syscall.Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0) if r1 == 0 { @@ -2386,6 +2452,14 @@ func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) return } +func SetFileInformationByHandle(handle Handle, class uint32, inBuffer *byte, inBufferLen uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) newlowoffset = uint32(r0) @@ -2718,6 +2792,27 @@ func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) { return } +func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) { + ret = procSubscribeServiceChangeNotifications.Find() + if ret != nil { + return + } + r0, _, _ := syscall.Syscall6(procSubscribeServiceChangeNotifications.Addr(), 5, uintptr(service), uintptr(eventType), uintptr(callback), uintptr(callbackCtx), uintptr(unsafe.Pointer(subscription)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func UnsubscribeServiceChangeNotifications(subscription uintptr) (err error) { + err = procUnsubscribeServiceChangeNotifications.Find() + if err != nil { + return + } + syscall.Syscall(procUnsubscribeServiceChangeNotifications.Addr(), 1, uintptr(subscription), 0, 0) + return +} + func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) { r1, _, e1 := syscall.Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) if r1&0xff == 0 { diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 48aac279e9..cda5fd0556 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -39,7 +39,7 @@ golang.org/x/mod/sumdb/dirhash golang.org/x/mod/sumdb/note golang.org/x/mod/sumdb/tlog golang.org/x/mod/zip -# golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 +# golang.org/x/sys v0.0.0-20201204225414-ed752295db88 ## explicit golang.org/x/sys/internal/unsafeheader golang.org/x/sys/unix diff --git a/src/go.mod b/src/go.mod index 37091e116a..1fcd02f9ba 100644 --- a/src/go.mod +++ b/src/go.mod @@ -5,6 +5,6 @@ go 1.16 require ( golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d - golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 // indirect + golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect golang.org/x/text v0.3.4 // indirect ) diff --git a/src/go.sum b/src/go.sum index 3f0270fb9a..913e6ea68d 100644 --- a/src/go.sum +++ b/src/go.sum @@ -8,8 +8,8 @@ golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 h1:Qo9oJ566/Sq7N4hrGftVXs8GI2CXBCuOd4S2wHE/e0M= -golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index 0eea2b87a9..c1a12ccba3 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -260,7 +260,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile //sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW //sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW -//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore +//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) = crypt32.CertOpenStore //sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore //sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore //sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go index 5d03ca9de9..86c4cac2ad 100644 --- a/src/syscall/zsyscall_windows.go +++ b/src/syscall/zsyscall_windows.go @@ -399,7 +399,7 @@ func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, a func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) { r0, _, e1 := Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0) handle = Handle(r0) - if handle == InvalidHandle { + if handle == 0 { err = errnoErr(e1) } return diff --git a/src/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s b/src/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s index 06f84b8555..6b4027b33f 100644 --- a/src/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s +++ b/src/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/src/vendor/golang.org/x/sys/cpu/cpu_arm64.s index a54436e390..cfc08c9794 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_arm64.s +++ b/src/vendor/golang.org/x/sys/cpu/cpu_arm64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/src/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go index 7b88e865a4..7f7f272a01 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc package cpu diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go b/src/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go index 568bcd031a..75a9556616 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc package cpu diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go index f7cb46971c..4adb89cf9c 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build 386 amd64 amd64p32 -// +build !gccgo +// +build gc package cpu diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_s390x.s b/src/vendor/golang.org/x/sys/cpu/cpu_s390x.s index e5037d92e0..964946df95 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_s390x.s +++ b/src/vendor/golang.org/x/sys/cpu/cpu_s390x.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_x86.s b/src/vendor/golang.org/x/sys/cpu/cpu_x86.s index 47f084128c..2f557a5887 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_x86.s +++ b/src/vendor/golang.org/x/sys/cpu/cpu_x86.s @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build 386 amd64 amd64p32 -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/src/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go b/src/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go index 78fe25e86f..5b427d67e2 100644 --- a/src/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go +++ b/src/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go @@ -7,7 +7,7 @@ // (See golang.org/issue/32102) // +build aix,ppc64 -// +build !gccgo +// +build gc package cpu diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 24a3751400..de727ef71f 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -18,7 +18,7 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 +# golang.org/x/sys v0.0.0-20201204225414-ed752295db88 ## explicit golang.org/x/sys/cpu # golang.org/x/text v0.3.4 From 3b2a578166bdedd94110698c971ba8990771eb89 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Sat, 5 Dec 2020 14:43:53 +0000 Subject: [PATCH 150/212] internal/cpu: fix typo in cpu_arm64.go auxillary -> auxiliary Change-Id: I7c29c4a63d236c3688b8e4f5af70650d43cd89c0 GitHub-Last-Rev: d4a18c71a15cf0803bd847225ed5bf898c52e0f3 GitHub-Pull-Request: golang/go#43024 Reviewed-on: https://go-review.googlesource.com/c/go/+/275592 Reviewed-by: Ian Lance Taylor Trust: Keith Randall --- src/internal/cpu/cpu_arm64.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go index 4e9ea8ca96..a8f7b2b458 100644 --- a/src/internal/cpu/cpu_arm64.go +++ b/src/internal/cpu/cpu_arm64.go @@ -36,7 +36,7 @@ func doinit() { switch GOOS { case "linux", "android": - // HWCap was populated by the runtime from the auxillary vector. + // HWCap was populated by the runtime from the auxiliary vector. // Use HWCap information since reading aarch64 system registers // is not supported in user space on older linux kernels. ARM64.HasAES = isSet(HWCap, hwcap_AES) @@ -103,7 +103,7 @@ func doinit() { ARM64.HasATOMICS = true } default: - // Other operating systems do not support reading HWCap from auxillary vector + // Other operating systems do not support reading HWCap from auxiliary vector // or reading privileged aarch64 system registers in user space. } } From 6c5967e528f1efc9dfed107c33dccf2d305f2a25 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 5 Dec 2020 15:49:03 -0800 Subject: [PATCH 151/212] [dev.regabi] cmd/compile: change NodeSet to NameSet The only user of NodeSet (computing initialization dependencies) only needs to store *Names in this structure. So change its definition to match that need, and update the code in initorder.go accordingly. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: I181a8aaf9bc71e88f4ac009c4f381a718080e48f Reviewed-on: https://go-review.googlesource.com/c/go/+/275752 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/initorder.go | 22 +++++++++++----------- src/cmd/compile/internal/ir/node.go | 14 +++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/gc/initorder.go b/src/cmd/compile/internal/gc/initorder.go index 87a78ae053..7f1f3cba92 100644 --- a/src/cmd/compile/internal/gc/initorder.go +++ b/src/cmd/compile/internal/gc/initorder.go @@ -110,7 +110,7 @@ func initOrder(l []ir.Node) []ir.Node { // first. base.ExitIfErrors() - findInitLoopAndExit(firstLHS(n), new([]ir.Node)) + findInitLoopAndExit(firstLHS(n), new([]*ir.Name)) base.Fatalf("initialization unfinished, but failed to identify loop") } } @@ -136,7 +136,7 @@ func (o *InitOrder) processAssign(n ir.Node) { // Compute number of variable dependencies and build the // inverse dependency ("blocking") graph. for dep := range collectDeps(n, true) { - defn := dep.Name().Defn + defn := dep.Defn // Skip dependencies on functions (PFUNC) and // variables already initialized (InitDone). if dep.Class() != ir.PEXTERN || defn.Initorder() == InitDone { @@ -183,7 +183,7 @@ func (o *InitOrder) flushReady(initialize func(ir.Node)) { // path points to a slice used for tracking the sequence of // variables/functions visited. Using a pointer to a slice allows the // slice capacity to grow and limit reallocations. -func findInitLoopAndExit(n ir.Node, path *[]ir.Node) { +func findInitLoopAndExit(n *ir.Name, path *[]*ir.Name) { // We implement a simple DFS loop-finding algorithm. This // could be faster, but initialization cycles are rare. @@ -196,14 +196,14 @@ func findInitLoopAndExit(n ir.Node, path *[]ir.Node) { // There might be multiple loops involving n; by sorting // references, we deterministically pick the one reported. - refers := collectDeps(n.Name().Defn, false).Sorted(func(ni, nj ir.Node) bool { + refers := collectDeps(n.Name().Defn, false).Sorted(func(ni, nj *ir.Name) bool { return ni.Pos().Before(nj.Pos()) }) *path = append(*path, n) for _, ref := range refers { // Short-circuit variables that were initialized. - if ref.Class() == ir.PEXTERN && ref.Name().Defn.Initorder() == InitDone { + if ref.Class() == ir.PEXTERN && ref.Defn.Initorder() == InitDone { continue } @@ -215,7 +215,7 @@ func findInitLoopAndExit(n ir.Node, path *[]ir.Node) { // reportInitLoopAndExit reports and initialization loop as an error // and exits. However, if l is not actually an initialization loop, it // simply returns instead. -func reportInitLoopAndExit(l []ir.Node) { +func reportInitLoopAndExit(l []*ir.Name) { // Rotate loop so that the earliest variable declaration is at // the start. i := -1 @@ -250,7 +250,7 @@ func reportInitLoopAndExit(l []ir.Node) { // variables that declaration n depends on. If transitive is true, // then it also includes the transitive dependencies of any depended // upon functions (but not variables). -func collectDeps(n ir.Node, transitive bool) ir.NodeSet { +func collectDeps(n ir.Node, transitive bool) ir.NameSet { d := initDeps{transitive: transitive} switch n.Op() { case ir.OAS: @@ -267,7 +267,7 @@ func collectDeps(n ir.Node, transitive bool) ir.NodeSet { type initDeps struct { transitive bool - seen ir.NodeSet + seen ir.NameSet } func (d *initDeps) inspect(n ir.Node) { ir.Inspect(n, d.visit) } @@ -345,12 +345,12 @@ func (s *declOrder) Pop() interface{} { // firstLHS returns the first expression on the left-hand side of // assignment n. -func firstLHS(n ir.Node) ir.Node { +func firstLHS(n ir.Node) *ir.Name { switch n.Op() { case ir.OAS: - return n.Left() + return n.Left().Name() case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2RECV, ir.OAS2MAPR: - return n.List().First() + return n.List().First().Name() } base.Fatalf("unexpected Op: %v", n.Op()) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index f44d22313c..a0ee8aa0fe 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -585,26 +585,26 @@ func (q *NodeQueue) PopLeft() Node { return n } -// NodeSet is a set of Nodes. -type NodeSet map[Node]struct{} +// NameSet is a set of Names. +type NameSet map[*Name]struct{} // Has reports whether s contains n. -func (s NodeSet) Has(n Node) bool { +func (s NameSet) Has(n *Name) bool { _, isPresent := s[n] return isPresent } // Add adds n to s. -func (s *NodeSet) Add(n Node) { +func (s *NameSet) Add(n *Name) { if *s == nil { - *s = make(map[Node]struct{}) + *s = make(map[*Name]struct{}) } (*s)[n] = struct{}{} } // Sorted returns s sorted according to less. -func (s NodeSet) Sorted(less func(Node, Node) bool) []Node { - var res []Node +func (s NameSet) Sorted(less func(*Name, *Name) bool) []*Name { + var res []*Name for n := range s { res = append(res, n) } From 1b5eed89828f41e290ae212c596ff301c5db7204 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 6 Dec 2020 12:29:42 -0800 Subject: [PATCH 152/212] [dev.regabi] cmd/compile: replace NodeQueue with NameQueue Similar to the previous CL, the only two users of NodeQueue only needed it for tracking objects, not arbitrary AST nodes. So change it's signature to use *Name instead of Node. This does require a tweak to the nowritebarrierrec checker, because previously it was pushing the ODCLFUNC *Func pointers into the queue, whereas now we push the ONAME/PFUNC *Name pointers instead. However, it's trivial and safe to flip between them. Also, this changes a handful of export-related code from Node to *Name, to avoid introducing type assertions within iexport.go. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: I867f9752121509fc3da753978c6a41d5015bc0ce Reviewed-on: https://go-review.googlesource.com/c/go/+/275753 Reviewed-by: Cuong Manh Le Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/dcl.go | 8 ++++---- src/cmd/compile/internal/gc/export.go | 4 ++-- src/cmd/compile/internal/gc/go.go | 2 +- src/cmd/compile/internal/gc/iexport.go | 6 +++--- src/cmd/compile/internal/ir/node.go | 22 +++++++++++----------- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index ce13f0bdfc..56f8d1b9bf 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -931,7 +931,7 @@ func (c *nowritebarrierrecChecker) check() { // acts as the set of marks for the BFS of the call graph. funcs := make(map[ir.Node]nowritebarrierrecCall) // q is the queue of ODCLFUNC Nodes to visit in BFS order. - var q ir.NodeQueue + var q ir.NameQueue for _, n := range xtop { if n.Op() != ir.ODCLFUNC { @@ -944,7 +944,7 @@ func (c *nowritebarrierrecChecker) check() { // Make nowritebarrierrec functions BFS roots. if fn.Pragma&ir.Nowritebarrierrec != 0 { funcs[fn] = nowritebarrierrecCall{} - q.PushRight(fn) + q.PushRight(fn.Nname) } // Check go:nowritebarrier functions. if fn.Pragma&ir.Nowritebarrier != 0 && fn.WBPos.IsKnown() { @@ -966,10 +966,10 @@ func (c *nowritebarrierrecChecker) check() { // Record the path. funcs[target] = nowritebarrierrecCall{target: src, lineno: pos} - q.PushRight(target) + q.PushRight(target.Nname) } for !q.Empty() { - fn := q.PopLeft().(*ir.Func) + fn := q.PopLeft().Func() // Check fn. if fn.WBPos.IsKnown() { diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 44fc70be03..b632a15865 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -24,7 +24,7 @@ func exportf(bout *bio.Writer, format string, args ...interface{}) { var asmlist []ir.Node // exportsym marks n for export (or reexport). -func exportsym(n ir.Node) { +func exportsym(n *ir.Name) { if n.Sym().OnExportList() { return } @@ -41,7 +41,7 @@ func initname(s string) bool { return s == "init" } -func autoexport(n ir.Node, ctxt ir.Class) { +func autoexport(n *ir.Name, ctxt ir.Class) { if n.Sym().Pkg != ir.LocalPkg { return } diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index c493165c76..c4b9c185dc 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -130,7 +130,7 @@ var ( var xtop []ir.Node -var exportlist []ir.Node +var exportlist []*ir.Name var importlist []*ir.Func // imported functions and methods with inlinable bodies diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index bb6f2b11e6..14614d8ab8 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -368,7 +368,7 @@ type iexporter struct { // main index. allPkgs map[*types.Pkg]bool - declTodo ir.NodeQueue + declTodo ir.NameQueue strings intWriter stringIndex map[string]uint64 @@ -394,7 +394,7 @@ func (p *iexporter) stringOff(s string) uint64 { } // pushDecl adds n to the declaration work queue, if not already present. -func (p *iexporter) pushDecl(n ir.Node) { +func (p *iexporter) pushDecl(n *ir.Name) { if n.Sym() == nil || n.Sym().Def != n && n.Op() != ir.OTYPE { base.Fatalf("weird Sym: %v, %v", n, n.Sym()) } @@ -573,7 +573,7 @@ func (w *exportWriter) pkg(pkg *types.Pkg) { func (w *exportWriter) qualifiedIdent(n ir.Node) { // Ensure any referenced declarations are written out too. - w.p.pushDecl(n) + w.p.pushDecl(n.Name()) s := n.Sym() w.string(s.Name) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index a0ee8aa0fe..7fd02925ba 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -539,25 +539,25 @@ func (n Nodes) Copy() Nodes { return c } -// nodeQueue is a FIFO queue of *Node. The zero value of nodeQueue is +// NameQueue is a FIFO queue of *Name. The zero value of NameQueue is // a ready-to-use empty queue. -type NodeQueue struct { - ring []Node +type NameQueue struct { + ring []*Name head, tail int } -// empty reports whether q contains no Nodes. -func (q *NodeQueue) Empty() bool { +// Empty reports whether q contains no Names. +func (q *NameQueue) Empty() bool { return q.head == q.tail } -// pushRight appends n to the right of the queue. -func (q *NodeQueue) PushRight(n Node) { +// PushRight appends n to the right of the queue. +func (q *NameQueue) PushRight(n *Name) { if len(q.ring) == 0 { - q.ring = make([]Node, 16) + q.ring = make([]*Name, 16) } else if q.head+len(q.ring) == q.tail { // Grow the ring. - nring := make([]Node, len(q.ring)*2) + nring := make([]*Name, len(q.ring)*2) // Copy the old elements. part := q.ring[q.head%len(q.ring):] if q.tail-q.head <= len(part) { @@ -574,9 +574,9 @@ func (q *NodeQueue) PushRight(n Node) { q.tail++ } -// popLeft pops a node from the left of the queue. It panics if q is +// PopLeft pops a Name from the left of the queue. It panics if q is // empty. -func (q *NodeQueue) PopLeft() Node { +func (q *NameQueue) PopLeft() *Name { if q.Empty() { panic("dequeue empty") } From 2d4c95565a770227ef2943b68ebe9fac02f79377 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 5 Dec 2020 16:33:59 -0800 Subject: [PATCH 153/212] [dev.regabi] cmd/compile: change nowritebarrierrec to use map[*ir.Func] All of the uses were already using *ir.Func index operands, so only needs the map type itself updated. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: I568d8601f3eb077e07e887f2071aa1a2667d803c Reviewed-on: https://go-review.googlesource.com/c/go/+/275754 Reviewed-by: Cuong Manh Le Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky --- src/cmd/compile/internal/gc/dcl.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 56f8d1b9bf..5936aeb950 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -838,7 +838,7 @@ type nowritebarrierrecChecker struct { // extraCalls contains extra function calls that may not be // visible during later analysis. It maps from the ODCLFUNC of // the caller to a list of callees. - extraCalls map[ir.Node][]nowritebarrierrecCall + extraCalls map[*ir.Func][]nowritebarrierrecCall // curfn is the current function during AST walks. curfn *ir.Func @@ -853,7 +853,7 @@ type nowritebarrierrecCall struct { // must be called before transformclosure and walk. func newNowritebarrierrecChecker() *nowritebarrierrecChecker { c := &nowritebarrierrecChecker{ - extraCalls: make(map[ir.Node][]nowritebarrierrecCall), + extraCalls: make(map[*ir.Func][]nowritebarrierrecCall), } // Find all systemstack calls and record their targets. In @@ -929,7 +929,7 @@ func (c *nowritebarrierrecChecker) check() { // that are directly marked go:nowritebarrierrec are in this // map with a zero-valued nowritebarrierrecCall. This also // acts as the set of marks for the BFS of the call graph. - funcs := make(map[ir.Node]nowritebarrierrecCall) + funcs := make(map[*ir.Func]nowritebarrierrecCall) // q is the queue of ODCLFUNC Nodes to visit in BFS order. var q ir.NameQueue From e885df2731cb36925c9a9de9cf1a34a167461cd7 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 6 Dec 2020 12:14:46 -0800 Subject: [PATCH 154/212] [dev.regabi] cmd/compile: change iexport to avoid map[ir.Node] In the past, we had a lot of trouble with misusing *types.Sym throughout the frontend, so I tried to push us towards always passing around ONAMEs instead. But for constructing and writing out the symbol indexes for the indexed export data, keying by *types.Sym is exactly what we want. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: Idd8f1fb057d75a52a34ebc7788d9332fb49caf8d Reviewed-on: https://go-review.googlesource.com/c/go/+/275755 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/gc/iexport.go | 62 +++++++++++++------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 14614d8ab8..003cf3b446 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -259,8 +259,8 @@ func iexport(out *bufio.Writer) { p := iexporter{ allPkgs: map[*types.Pkg]bool{}, stringIndex: map[string]uint64{}, - declIndex: map[ir.Node]uint64{}, - inlineIndex: map[ir.Node]uint64{}, + declIndex: map[*types.Sym]uint64{}, + inlineIndex: map[*types.Sym]uint64{}, typIndex: map[*types.Type]uint64{}, } @@ -310,37 +310,34 @@ func iexport(out *bufio.Writer) { out.Write(base.Ctxt.Fingerprint[:]) } -// writeIndex writes out an object index. mainIndex indicates whether +// writeIndex writes out a symbol index. mainIndex indicates whether // we're writing out the main index, which is also read by // non-compiler tools and includes a complete package description // (i.e., name and height). -func (w *exportWriter) writeIndex(index map[ir.Node]uint64, mainIndex bool) { - // Build a map from packages to objects from that package. - pkgObjs := map[*types.Pkg][]ir.Node{} +func (w *exportWriter) writeIndex(index map[*types.Sym]uint64, mainIndex bool) { + // Build a map from packages to symbols from that package. + pkgSyms := map[*types.Pkg][]*types.Sym{} // For the main index, make sure to include every package that // we reference, even if we're not exporting (or reexporting) // any symbols from it. if mainIndex { - pkgObjs[ir.LocalPkg] = nil + pkgSyms[ir.LocalPkg] = nil for pkg := range w.p.allPkgs { - pkgObjs[pkg] = nil + pkgSyms[pkg] = nil } } - for n := range index { - pkgObjs[n.Sym().Pkg] = append(pkgObjs[n.Sym().Pkg], n) + // Group symbols by package. + for sym := range index { + pkgSyms[sym.Pkg] = append(pkgSyms[sym.Pkg], sym) } + // Sort packages by path. var pkgs []*types.Pkg - for pkg, objs := range pkgObjs { + for pkg := range pkgSyms { pkgs = append(pkgs, pkg) - - sort.Slice(objs, func(i, j int) bool { - return objs[i].Sym().Name < objs[j].Sym().Name - }) } - sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].Path < pkgs[j].Path }) @@ -353,11 +350,16 @@ func (w *exportWriter) writeIndex(index map[ir.Node]uint64, mainIndex bool) { w.uint64(uint64(pkg.Height)) } - objs := pkgObjs[pkg] - w.uint64(uint64(len(objs))) - for _, n := range objs { - w.string(n.Sym().Name) - w.uint64(index[n]) + // Sort symbols within a package by name. + syms := pkgSyms[pkg] + sort.Slice(syms, func(i, j int) bool { + return syms[i].Name < syms[j].Name + }) + + w.uint64(uint64(len(syms))) + for _, sym := range syms { + w.string(sym.Name) + w.uint64(index[sym]) } } } @@ -374,8 +376,8 @@ type iexporter struct { stringIndex map[string]uint64 data0 intWriter - declIndex map[ir.Node]uint64 - inlineIndex map[ir.Node]uint64 + declIndex map[*types.Sym]uint64 + inlineIndex map[*types.Sym]uint64 typIndex map[*types.Type]uint64 } @@ -404,11 +406,11 @@ func (p *iexporter) pushDecl(n *ir.Name) { return } - if _, ok := p.declIndex[n]; ok { + if _, ok := p.declIndex[n.Sym()]; ok { return } - p.declIndex[n] = ^uint64(0) // mark n present in work queue + p.declIndex[n.Sym()] = ^uint64(0) // mark n present in work queue p.declTodo.PushRight(n) } @@ -423,13 +425,12 @@ type exportWriter struct { prevColumn int64 } -func (p *iexporter) doDecl(n ir.Node) { +func (p *iexporter) doDecl(n *ir.Name) { w := p.newWriter() w.setPkg(n.Sym().Pkg, false) switch n.Op() { case ir.ONAME: - n := n.(*ir.Name) switch n.Class() { case ir.PEXTERN: // Variable. @@ -455,7 +456,8 @@ func (p *iexporter) doDecl(n ir.Node) { case ir.OLITERAL: // Constant. - n = typecheck(n, ctxExpr) + // TODO(mdempsky): Do we still need this typecheck? If so, why? + n = typecheck(n, ctxExpr).(*ir.Name) w.tag('C') w.pos(n.Pos()) w.value(n.Type(), n.Val()) @@ -509,7 +511,7 @@ func (p *iexporter) doDecl(n ir.Node) { base.Fatalf("unexpected node: %v", n) } - p.declIndex[n] = w.flush() + p.declIndex[n.Sym()] = w.flush() } func (w *exportWriter) tag(tag byte) { @@ -522,7 +524,7 @@ func (p *iexporter) doInline(f *ir.Name) { w.stmtList(ir.AsNodes(f.Func().Inl.Body)) - p.inlineIndex[f] = w.flush() + p.inlineIndex[f.Sym()] = w.flush() } func (w *exportWriter) pos(pos src.XPos) { From e10c94af26b95f4af71c4a040b3d3f01499d01de Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 3 Dec 2020 11:27:05 +0100 Subject: [PATCH 155/212] doc/go1.16: document riscv64 port changes For #36641 For #40700 Change-Id: Ib268559a2ce7839372dbf273d95876d8d4521a45 Reviewed-on: https://go-review.googlesource.com/c/go/+/274478 Trust: Tobias Klauser Reviewed-by: Joel Sing Reviewed-by: Austin Clements Reviewed-by: Cherry Zhang --- doc/go1.16.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/go1.16.html b/doc/go1.16.html index fb7022b354..bc4fc0e64b 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -81,6 +81,14 @@ Do not send CLs removing the interior tags from such phrases. with GO386=softfloat.

+

RISC-V

+ +

+ The linux/riscv64 port now supports cgo and + -buildmode=pie. This release also includes performance + optimizations and code generation improvements for RISC-V. +

+

Tools

From d90b199e9c3d6673b1951ddb6a78addd7e0dda26 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 3 Dec 2020 14:00:19 -0800 Subject: [PATCH 156/212] [dev.regabi] cmd/compile: silence errors about missing blank methods If an interface contains a blank method, that's already an error. No need for useless follow-up error messages about not implementing them. Fixes #42964. Change-Id: I5bf53a8f27d75d4c86c61588c5e2e3e95563d320 Reviewed-on: https://go-review.googlesource.com/c/go/+/275294 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/gc/dcl.go | 12 ------------ src/cmd/compile/internal/gc/noder.go | 5 ++++- test/interface/explicit.go | 7 ++++--- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 5936aeb950..a77c1aed45 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -317,18 +317,6 @@ func colasdefn(left []ir.Node, defn ir.Node) { } } -// declare the arguments in an -// interface field declaration. -func ifacedcl(n *ir.Field) { - if n.Sym == nil { - base.Fatalf("ifacedcl") - } - - if n.Sym.IsBlank() { - base.Errorf("methods must have a unique non-blank name") - } -} - // declare the function proper // and declare the arguments. // called in extern-declaration context diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 61320123a8..1cd8375677 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -899,10 +899,13 @@ func (p *noder) interfaceType(expr *syntax.InterfaceType) ir.Node { n = ir.NewField(p.pos(method), nil, importName(p.packname(method.Type)).(ir.Ntype), nil) } else { mname := p.name(method.Name) + if mname.IsBlank() { + base.Errorf("methods must have a unique non-blank name") + continue + } sig := p.typeExpr(method.Type).(*ir.FuncType) sig.Recv = fakeRecv() n = ir.NewField(p.pos(method), mname, sig, nil) - ifacedcl(n) } l = append(l, n) } diff --git a/test/interface/explicit.go b/test/interface/explicit.go index 3f9451e8d2..b705b97676 100644 --- a/test/interface/explicit.go +++ b/test/interface/explicit.go @@ -100,6 +100,7 @@ type T2 struct{} func (t *T2) M() {} func (t *T2) _() {} -// Check that nothing satisfies an interface with blank methods. -var b1 B1 = &T2{} // ERROR "incompatible|missing _ method" -var b2 B2 = &T2{} // ERROR "incompatible|missing _ method" +// Already reported about the invalid blank interface method above; +// no need to report about not implementing it. +var b1 B1 = &T2{} +var b2 B2 = &T2{} From c15593197453b8bf90fc3a9080ba2afeaf7934ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Sat, 21 Nov 2020 17:44:04 +0100 Subject: [PATCH 157/212] internal/cpu: add darwin/arm64 CPU feature detection support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #42747 Change-Id: I6b1679348c77161f075f0678818bb003fc0e8c86 Reviewed-on: https://go-review.googlesource.com/c/go/+/271989 Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- src/internal/cpu/cpu_android.go | 7 -- src/internal/cpu/cpu_arm64.go | 97 +------------------ .../{cpu_linux.go => cpu_arm64_android.go} | 6 +- src/internal/cpu/cpu_arm64_darwin.go | 34 +++++++ src/internal/cpu/cpu_arm64_freebsd.go | 45 +++++++++ src/internal/cpu/cpu_arm64_hwcap.go | 63 ++++++++++++ .../cpu/{cpu_other.go => cpu_arm64_linux.go} | 8 +- src/internal/cpu/cpu_arm64_other.go | 17 ++++ src/internal/cpu/cpu_freebsd.go | 7 -- src/internal/cpu/cpu_test.go | 7 +- src/runtime/os_darwin.go | 12 +++ src/runtime/sys_darwin.go | 10 +- src/runtime/sys_darwin_amd64.s | 20 +++- src/runtime/sys_darwin_arm64.s | 18 +++- 14 files changed, 223 insertions(+), 128 deletions(-) delete mode 100644 src/internal/cpu/cpu_android.go rename src/internal/cpu/{cpu_linux.go => cpu_arm64_android.go} (75%) create mode 100644 src/internal/cpu/cpu_arm64_darwin.go create mode 100644 src/internal/cpu/cpu_arm64_freebsd.go create mode 100644 src/internal/cpu/cpu_arm64_hwcap.go rename src/internal/cpu/{cpu_other.go => cpu_arm64_linux.go} (73%) create mode 100644 src/internal/cpu/cpu_arm64_other.go delete mode 100644 src/internal/cpu/cpu_freebsd.go diff --git a/src/internal/cpu/cpu_android.go b/src/internal/cpu/cpu_android.go deleted file mode 100644 index d995e8d5a7..0000000000 --- a/src/internal/cpu/cpu_android.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const GOOS = "android" diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go index a8f7b2b458..f64d9e4dd3 100644 --- a/src/internal/cpu/cpu_arm64.go +++ b/src/internal/cpu/cpu_arm64.go @@ -6,21 +6,6 @@ package cpu const CacheLinePadSize = 64 -// HWCap may be initialized by archauxv and -// should not be changed after it was initialized. -var HWCap uint - -// HWCAP bits. These are exposed by Linux. -const ( - hwcap_AES = 1 << 3 - hwcap_PMULL = 1 << 4 - hwcap_SHA1 = 1 << 5 - hwcap_SHA2 = 1 << 6 - hwcap_CRC32 = 1 << 7 - hwcap_ATOMICS = 1 << 8 - hwcap_CPUID = 1 << 11 -) - func doinit() { options = []option{ {Name: "aes", Feature: &ARM64.HasAES}, @@ -34,86 +19,8 @@ func doinit() { {Name: "isZeus", Feature: &ARM64.IsZeus}, } - switch GOOS { - case "linux", "android": - // HWCap was populated by the runtime from the auxiliary vector. - // Use HWCap information since reading aarch64 system registers - // is not supported in user space on older linux kernels. - ARM64.HasAES = isSet(HWCap, hwcap_AES) - ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL) - ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1) - ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2) - ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) - ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID) - - // The Samsung S9+ kernel reports support for atomics, but not all cores - // actually support them, resulting in SIGILL. See issue #28431. - // TODO(elias.naur): Only disable the optimization on bad chipsets on android. - ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && GOOS != "android" - - // Check to see if executing on a NeoverseN1 and in order to do that, - // check the AUXV for the CPUID bit. The getMIDR function executes an - // instruction which would normally be an illegal instruction, but it's - // trapped by the kernel, the value sanitized and then returned. Without - // the CPUID bit the kernel will not trap the instruction and the process - // will be terminated with SIGILL. - if ARM64.HasCPUID { - midr := getMIDR() - part_num := uint16((midr >> 4) & 0xfff) - implementor := byte((midr >> 24) & 0xff) - - if implementor == 'A' && part_num == 0xd0c { - ARM64.IsNeoverseN1 = true - } - if implementor == 'A' && part_num == 0xd40 { - ARM64.IsZeus = true - } - } - - case "freebsd": - // Retrieve info from system register ID_AA64ISAR0_EL1. - isar0 := getisar0() - - // ID_AA64ISAR0_EL1 - switch extractBits(isar0, 4, 7) { - case 1: - ARM64.HasAES = true - case 2: - ARM64.HasAES = true - ARM64.HasPMULL = true - } - - switch extractBits(isar0, 8, 11) { - case 1: - ARM64.HasSHA1 = true - } - - switch extractBits(isar0, 12, 15) { - case 1, 2: - ARM64.HasSHA2 = true - } - - switch extractBits(isar0, 16, 19) { - case 1: - ARM64.HasCRC32 = true - } - - switch extractBits(isar0, 20, 23) { - case 2: - ARM64.HasATOMICS = true - } - default: - // Other operating systems do not support reading HWCap from auxiliary vector - // or reading privileged aarch64 system registers in user space. - } -} - -func extractBits(data uint64, start, end uint) uint { - return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 + // arm64 uses different ways to detect CPU features at runtime depending on the operating system. + osInit() } func getisar0() uint64 diff --git a/src/internal/cpu/cpu_linux.go b/src/internal/cpu/cpu_arm64_android.go similarity index 75% rename from src/internal/cpu/cpu_linux.go rename to src/internal/cpu/cpu_arm64_android.go index ec0b84c510..3c9e57c52a 100644 --- a/src/internal/cpu/cpu_linux.go +++ b/src/internal/cpu/cpu_arm64_android.go @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !android +// +build arm64 package cpu -const GOOS = "linux" +func osInit() { + hwcapInit("android") +} diff --git a/src/internal/cpu/cpu_arm64_darwin.go b/src/internal/cpu/cpu_arm64_darwin.go new file mode 100644 index 0000000000..e094b97f97 --- /dev/null +++ b/src/internal/cpu/cpu_arm64_darwin.go @@ -0,0 +1,34 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build arm64 +// +build darwin +// +build !ios + +package cpu + +func osInit() { + ARM64.HasATOMICS = sysctlEnabled([]byte("hw.optional.armv8_1_atomics\x00")) + ARM64.HasCRC32 = sysctlEnabled([]byte("hw.optional.armv8_crc32\x00")) + + // There are no hw.optional sysctl values for the below features on Mac OS 11.0 + // to detect their supported state dynamically. Assume the CPU features that + // Apple Silicon M1 supports to be available as a minimal set of features + // to all Go programs running on darwin/arm64. + ARM64.HasAES = true + ARM64.HasPMULL = true + ARM64.HasSHA1 = true + ARM64.HasSHA2 = true +} + +//go:noescape +func getsysctlbyname(name []byte) (int32, int32) + +func sysctlEnabled(name []byte) bool { + ret, value := getsysctlbyname(name) + if ret < 0 { + return false + } + return value > 0 +} diff --git a/src/internal/cpu/cpu_arm64_freebsd.go b/src/internal/cpu/cpu_arm64_freebsd.go new file mode 100644 index 0000000000..9de2005c2e --- /dev/null +++ b/src/internal/cpu/cpu_arm64_freebsd.go @@ -0,0 +1,45 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build arm64 + +package cpu + +func osInit() { + // Retrieve info from system register ID_AA64ISAR0_EL1. + isar0 := getisar0() + + // ID_AA64ISAR0_EL1 + switch extractBits(isar0, 4, 7) { + case 1: + ARM64.HasAES = true + case 2: + ARM64.HasAES = true + ARM64.HasPMULL = true + } + + switch extractBits(isar0, 8, 11) { + case 1: + ARM64.HasSHA1 = true + } + + switch extractBits(isar0, 12, 15) { + case 1, 2: + ARM64.HasSHA2 = true + } + + switch extractBits(isar0, 16, 19) { + case 1: + ARM64.HasCRC32 = true + } + + switch extractBits(isar0, 20, 23) { + case 2: + ARM64.HasATOMICS = true + } +} + +func extractBits(data uint64, start, end uint) uint { + return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) +} diff --git a/src/internal/cpu/cpu_arm64_hwcap.go b/src/internal/cpu/cpu_arm64_hwcap.go new file mode 100644 index 0000000000..fdaf43e1a2 --- /dev/null +++ b/src/internal/cpu/cpu_arm64_hwcap.go @@ -0,0 +1,63 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build arm64 +// +build linux + +package cpu + +// HWCap may be initialized by archauxv and +// should not be changed after it was initialized. +var HWCap uint + +// HWCAP bits. These are exposed by Linux. +const ( + hwcap_AES = 1 << 3 + hwcap_PMULL = 1 << 4 + hwcap_SHA1 = 1 << 5 + hwcap_SHA2 = 1 << 6 + hwcap_CRC32 = 1 << 7 + hwcap_ATOMICS = 1 << 8 + hwcap_CPUID = 1 << 11 +) + +func hwcapInit(os string) { + // HWCap was populated by the runtime from the auxiliary vector. + // Use HWCap information since reading aarch64 system registers + // is not supported in user space on older linux kernels. + ARM64.HasAES = isSet(HWCap, hwcap_AES) + ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL) + ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1) + ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2) + ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) + ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID) + + // The Samsung S9+ kernel reports support for atomics, but not all cores + // actually support them, resulting in SIGILL. See issue #28431. + // TODO(elias.naur): Only disable the optimization on bad chipsets on android. + ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && os != "android" + + // Check to see if executing on a NeoverseN1 and in order to do that, + // check the AUXV for the CPUID bit. The getMIDR function executes an + // instruction which would normally be an illegal instruction, but it's + // trapped by the kernel, the value sanitized and then returned. Without + // the CPUID bit the kernel will not trap the instruction and the process + // will be terminated with SIGILL. + if ARM64.HasCPUID { + midr := getMIDR() + part_num := uint16((midr >> 4) & 0xfff) + implementor := byte((midr >> 24) & 0xff) + + if implementor == 'A' && part_num == 0xd0c { + ARM64.IsNeoverseN1 = true + } + if implementor == 'A' && part_num == 0xd40 { + ARM64.IsZeus = true + } + } +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/src/internal/cpu/cpu_other.go b/src/internal/cpu/cpu_arm64_linux.go similarity index 73% rename from src/internal/cpu/cpu_other.go rename to src/internal/cpu/cpu_arm64_linux.go index 8a15fbe79d..2f7411ff1e 100644 --- a/src/internal/cpu/cpu_other.go +++ b/src/internal/cpu/cpu_arm64_linux.go @@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !linux -// +build !freebsd +// +build arm64 +// +build linux // +build !android package cpu -const GOOS = "other" +func osInit() { + hwcapInit("linux") +} diff --git a/src/internal/cpu/cpu_arm64_other.go b/src/internal/cpu/cpu_arm64_other.go new file mode 100644 index 0000000000..f191db28d2 --- /dev/null +++ b/src/internal/cpu/cpu_arm64_other.go @@ -0,0 +1,17 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build arm64 +// +build !linux +// +build !freebsd +// +build !android +// +build !darwin ios + +package cpu + +func osInit() { + // Other operating systems do not support reading HWCap from auxiliary vector, + // reading privileged aarch64 system registers or sysctl in user space to detect + // CPU features at runtime. +} diff --git a/src/internal/cpu/cpu_freebsd.go b/src/internal/cpu/cpu_freebsd.go deleted file mode 100644 index dc37173dac..0000000000 --- a/src/internal/cpu/cpu_freebsd.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const GOOS = "freebsd" diff --git a/src/internal/cpu/cpu_test.go b/src/internal/cpu/cpu_test.go index 919bbd5ed7..2de7365732 100644 --- a/src/internal/cpu/cpu_test.go +++ b/src/internal/cpu/cpu_test.go @@ -18,7 +18,7 @@ func TestMinimalFeatures(t *testing.T) { // TODO: maybe do MustSupportFeatureDectection(t) ? if runtime.GOARCH == "arm64" { switch runtime.GOOS { - case "linux", "android": + case "linux", "android", "darwin": default: t.Skipf("%s/%s is not supported", runtime.GOOS, runtime.GOARCH) } @@ -38,10 +38,7 @@ func MustHaveDebugOptionsSupport(t *testing.T) { } func MustSupportFeatureDectection(t *testing.T) { - if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" { - t.Skipf("CPU feature detection is not supported on %s/%s", runtime.GOOS, runtime.GOARCH) - } - // TODO: maybe there are other platforms? + // TODO: add platforms that do not have CPU feature detection support. } func runDebugOptionsTest(t *testing.T, test string, options string) { diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index 52f3cd1fef..e0a43c28aa 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -130,6 +130,18 @@ func osinit() { physPageSize = getPageSize() } +func sysctlbynameInt32(name []byte) (int32, int32) { + out := int32(0) + nout := unsafe.Sizeof(out) + ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) + return ret, out +} + +//go:linkname internal_cpu_getsysctlbyname internal/cpu.getsysctlbyname +func internal_cpu_getsysctlbyname(name []byte) (int32, int32) { + return sysctlbynameInt32(name) +} + const ( _CTL_HW = 6 _HW_NCPU = 3 diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index c63ba8c6cd..c89ce78012 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -360,11 +360,18 @@ func setitimer_trampoline() //go:nosplit //go:cgo_unsafe_args -func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 { +func sysctl(mib *uint32, miblen uint32, oldp *byte, oldlenp *uintptr, newp *byte, newlen uintptr) int32 { return libcCall(unsafe.Pointer(funcPC(sysctl_trampoline)), unsafe.Pointer(&mib)) } func sysctl_trampoline() +//go:nosplit +//go:cgo_unsafe_args +func sysctlbyname(name *byte, oldp *byte, oldlenp *uintptr, newp *byte, newlen uintptr) int32 { + return libcCall(unsafe.Pointer(funcPC(sysctlbyname_trampoline)), unsafe.Pointer(&name)) +} +func sysctlbyname_trampoline() + //go:nosplit //go:cgo_unsafe_args func fcntl(fd, cmd, arg int32) int32 { @@ -486,6 +493,7 @@ func setNonblock(fd int32) { //go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_setitimer setitimer "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index 9b5b23901d..630fb5df64 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -371,15 +371,27 @@ TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP MOVL 8(DI), SI // arg 2 miblen - MOVQ 16(DI), DX // arg 3 out - MOVQ 24(DI), CX // arg 4 size - MOVQ 32(DI), R8 // arg 5 dst - MOVQ 40(DI), R9 // arg 6 ndst + MOVQ 16(DI), DX // arg 3 oldp + MOVQ 24(DI), CX // arg 4 oldlenp + MOVQ 32(DI), R8 // arg 5 newp + MOVQ 40(DI), R9 // arg 6 newlen MOVQ 0(DI), DI // arg 1 mib CALL libc_sysctl(SB) POPQ BP RET +TEXT runtime·sysctlbyname_trampoline(SB),NOSPLIT,$0 + PUSHQ BP + MOVQ SP, BP + MOVQ 8(DI), SI // arg 2 oldp + MOVQ 16(DI), DX // arg 3 oldlenp + MOVQ 24(DI), CX // arg 4 newp + MOVQ 32(DI), R8 // arg 5 newlen + MOVQ 0(DI), DI // arg 1 name + CALL libc_sysctlbyname(SB) + POPQ BP + RET + TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s index 9d4d116c50..96d2ed1076 100644 --- a/src/runtime/sys_darwin_arm64.s +++ b/src/runtime/sys_darwin_arm64.s @@ -301,14 +301,24 @@ TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0 TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0 MOVW 8(R0), R1 // arg 2 miblen - MOVD 16(R0), R2 // arg 3 out - MOVD 24(R0), R3 // arg 4 size - MOVD 32(R0), R4 // arg 5 dst - MOVD 40(R0), R5 // arg 6 ndst + MOVD 16(R0), R2 // arg 3 oldp + MOVD 24(R0), R3 // arg 4 oldlenp + MOVD 32(R0), R4 // arg 5 newp + MOVD 40(R0), R5 // arg 6 newlen MOVD 0(R0), R0 // arg 1 mib BL libc_sysctl(SB) RET +TEXT runtime·sysctlbyname_trampoline(SB),NOSPLIT,$0 + MOVD 8(R0), R1 // arg 2 oldp + MOVD 16(R0), R2 // arg 3 oldlenp + MOVD 24(R0), R3 // arg 4 newp + MOVD 32(R0), R4 // arg 5 newlen + MOVD 0(R0), R0 // arg 1 name + BL libc_sysctlbyname(SB) + RET + + TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0 BL libc_kqueue(SB) RET From ac0ba6707c1655ea4316b41d06571a0303cc60eb Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 7 Dec 2020 11:33:00 +0100 Subject: [PATCH 158/212] doc/go1.16: add missing tag For #40700 Change-Id: Ic4e16106cbbe18d0c9efffee81c5234ddeedfd32 Reviewed-on: https://go-review.googlesource.com/c/go/+/275674 Trust: Tobias Klauser Reviewed-by: Alberto Donizetti --- doc/go1.16.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index bc4fc0e64b..4f1789a659 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -805,7 +805,7 @@ Do not send CLs removing the interior tags from such phrases.

runtime/debug

- The runtime.Error values + The runtime.Error values used when SetPanicOnFault is enabled may now have an Addr method. If that method exists, it returns the memory address that triggered the fault. From 7f9a2bc2bc6201d7ffb3b5066b88a19d2da96592 Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Mon, 7 Dec 2020 18:10:56 +0100 Subject: [PATCH 159/212] doc/go1.16: fix typo For #40700 Change-Id: Idea442d45d18ca8cedc0b160df23eac6b86755ef Reviewed-on: https://go-review.googlesource.com/c/go/+/275677 Trust: Alberto Donizetti Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser --- doc/go1.16.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 4f1789a659..5ad3cae6d9 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -194,7 +194,7 @@ Do not send CLs removing the interior tags from such phrases. The go get -insecure flag is deprecated and will be removed in a future version. This flag permits fetching from repositories and resolving custom domains using insecure - schemes such as HTTP, and also bypassess module sum validation using the + schemes such as HTTP, and also bypasses module sum validation using the checksum database. To permit the use of insecure schemes, use the GOINSECURE environment variable instead. To bypass module sum validation, use GOPRIVATE or GONOSUMDB. From 9c0e2db051093767526c96cbe02d3c3b7d28f770 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 5 Dec 2020 08:08:47 -0800 Subject: [PATCH 160/212] test: add new test that gofrontend failed to handle The gofrontend code would in some circumstances incorrectly generate a type descriptor for an alias type, causing the type to fail to be equal to the unaliased type. Change-Id: I47d33b0bfde3c72a9a186049539732bdd5a6a96e Reviewed-on: https://go-review.googlesource.com/c/go/+/275632 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- test/fixedbugs/bug510.dir/a.go | 13 +++++++++++++ test/fixedbugs/bug510.dir/b.go | 14 ++++++++++++++ test/fixedbugs/bug510.go | 9 +++++++++ 3 files changed, 36 insertions(+) create mode 100644 test/fixedbugs/bug510.dir/a.go create mode 100644 test/fixedbugs/bug510.dir/b.go create mode 100644 test/fixedbugs/bug510.go diff --git a/test/fixedbugs/bug510.dir/a.go b/test/fixedbugs/bug510.dir/a.go new file mode 100644 index 0000000000..db1cfef366 --- /dev/null +++ b/test/fixedbugs/bug510.dir/a.go @@ -0,0 +1,13 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import "reflect" + +type A = map[int] bool + +func F() interface{} { + return reflect.New(reflect.TypeOf((*A)(nil))).Elem().Interface() +} diff --git a/test/fixedbugs/bug510.dir/b.go b/test/fixedbugs/bug510.dir/b.go new file mode 100644 index 0000000000..56b0201858 --- /dev/null +++ b/test/fixedbugs/bug510.dir/b.go @@ -0,0 +1,14 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "./a" + +func main() { + _, ok := a.F().(*map[int]bool) + if !ok { + panic("bad type") + } +} diff --git a/test/fixedbugs/bug510.go b/test/fixedbugs/bug510.go new file mode 100644 index 0000000000..8a6da5dfd6 --- /dev/null +++ b/test/fixedbugs/bug510.go @@ -0,0 +1,9 @@ +// rundir + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Gccgo confused type descriptors for aliases. + +package ignored From 8d3458517199f5aa2be0ec0f316fd406c9ca6cbb Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sun, 6 Dec 2020 21:28:36 -0500 Subject: [PATCH 161/212] doc/go1.16: announce openbsd/mips64 port Updates #40995. For #40700. Change-Id: I4dced8d70e2f1fa2da98e2eb1a5f1f829f55bb6b Reviewed-on: https://go-review.googlesource.com/c/go/+/275787 Trust: Austin Clements Reviewed-by: Joel Sing --- doc/go1.16.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/go1.16.html b/doc/go1.16.html index 5ad3cae6d9..a1f07c10fd 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -70,6 +70,14 @@ Do not send CLs removing the interior tags from such phrases. netbsd/arm64 port).

+

OpenBSD

+ +

+ Go now supports the MIPS64 architecture on OpenBSD + (the openbsd/mips64 port). This port does not yet + support cgo. +

+

386

From 50cdb2d8e9ca8d7b79a05121c88271b46f7c9607 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Sun, 6 Dec 2020 20:13:47 +0000 Subject: [PATCH 162/212] runtime/cgo: fix building on musl sys/unistd.h only exists in glibc and not in musl so use the standard location. This is a regression from CL 210639 Change-Id: Idd4c75510d9829316b44300c36c34df6d667cc05 GitHub-Last-Rev: 0fa4162f1c7c460bda7585300285f47d1781985d GitHub-Pull-Request: golang/go#43038 Reviewed-on: https://go-review.googlesource.com/c/go/+/275732 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Andrew G. Morgan Reviewed-by: Ian Lance Taylor Trust: Filippo Valsorda --- src/runtime/cgo/linux_syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/cgo/linux_syscall.c b/src/runtime/cgo/linux_syscall.c index c8e91918a1..56f3d67d8b 100644 --- a/src/runtime/cgo/linux_syscall.c +++ b/src/runtime/cgo/linux_syscall.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include "libcgo.h" From 2cec6c4a8cca6106c9939ae1560d614dec656839 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 4 Dec 2020 10:17:50 -0500 Subject: [PATCH 163/212] [dev.regabi] cmd/compile: generate Node methods using program Add Node method generator by Matthew Dempsky, lightly adapted to account for a few special cases. No more writing these by hand. Change-Id: I6933b895df666928b851bddf81b994799c0c97f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/275434 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/expr.go | 455 +--------- src/cmd/compile/internal/ir/func.go | 13 - src/cmd/compile/internal/ir/mini.go | 8 + src/cmd/compile/internal/ir/mknode.go | 175 ++++ src/cmd/compile/internal/ir/name.go | 14 +- src/cmd/compile/internal/ir/node_gen.go | 1029 +++++++++++++++++++++++ src/cmd/compile/internal/ir/stmt.go | 382 --------- src/cmd/compile/internal/ir/type.go | 113 --- 8 files changed, 1214 insertions(+), 975 deletions(-) create mode 100644 src/cmd/compile/internal/ir/mknode.go create mode 100644 src/cmd/compile/internal/ir/node_gen.go diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index cfdb86f221..7b1aeedcdf 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -8,7 +8,6 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/types" "cmd/internal/src" - "fmt" "go/constant" ) @@ -95,25 +94,6 @@ func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr { return n } -func (n *AddStringExpr) String() string { return fmt.Sprint(n) } -func (n *AddStringExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AddStringExpr) copy() Node { - c := *n - c.init = c.init.Copy() - c.list = c.list.Copy() - return &c -} -func (n *AddStringExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDoList(n.list, err, do) - return err -} -func (n *AddStringExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - editList(n.list, edit) -} - func (n *AddStringExpr) List() Nodes { return n.list } func (n *AddStringExpr) PtrList() *Nodes { return &n.list } func (n *AddStringExpr) SetList(x Nodes) { n.list = x } @@ -133,24 +113,6 @@ func NewAddrExpr(pos src.XPos, x Node) *AddrExpr { return n } -func (n *AddrExpr) String() string { return fmt.Sprint(n) } -func (n *AddrExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AddrExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *AddrExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - return err -} -func (n *AddrExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) -} - func (n *AddrExpr) Left() Node { return n.X } func (n *AddrExpr) SetLeft(x Node) { n.X = x } func (n *AddrExpr) Right() Node { return n.Alloc } @@ -180,26 +142,6 @@ func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr { return n } -func (n *BinaryExpr) String() string { return fmt.Sprint(n) } -func (n *BinaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *BinaryExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *BinaryExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - err = maybeDo(n.Y, err, do) - return err -} -func (n *BinaryExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) - n.Y = maybeEdit(n.Y, edit) -} - func (n *BinaryExpr) Left() Node { return n.X } func (n *BinaryExpr) SetLeft(x Node) { n.X = x } func (n *BinaryExpr) Right() Node { return n.Y } @@ -250,33 +192,6 @@ func NewCallExpr(pos src.XPos, fun Node, args []Node) *CallExpr { return n } -func (n *CallExpr) String() string { return fmt.Sprint(n) } -func (n *CallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CallExpr) copy() Node { - c := *n - c.init = c.init.Copy() - c.Args = c.Args.Copy() - c.Rargs = c.Rargs.Copy() - c.body = c.body.Copy() - return &c -} -func (n *CallExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - err = maybeDoList(n.Args, err, do) - err = maybeDoList(n.Rargs, err, do) - err = maybeDoList(n.body, err, do) - return err -} -func (n *CallExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) - editList(n.Args, edit) - editList(n.Rargs, edit) - editList(n.body, edit) -} - func (n *CallExpr) Orig() Node { return n.orig } func (n *CallExpr) SetOrig(x Node) { n.orig = x } func (n *CallExpr) Left() Node { return n.X } @@ -322,24 +237,6 @@ func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallP return n } -func (n *CallPartExpr) String() string { return fmt.Sprint(n) } -func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CallPartExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *CallPartExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - return err -} -func (n *CallPartExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) -} - func (n *CallPartExpr) Func() *Func { return n.fn } func (n *CallPartExpr) Left() Node { return n.X } func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym } @@ -358,22 +255,6 @@ func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr { return n } -func (n *ClosureExpr) String() string { return fmt.Sprint(n) } -func (n *ClosureExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ClosureExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *ClosureExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - return err -} -func (n *ClosureExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) -} - func (n *ClosureExpr) Func() *Func { return n.fn } // A ClosureRead denotes reading a variable stored within a closure struct. @@ -389,24 +270,8 @@ func NewClosureRead(typ *types.Type, offset int64) *ClosureRead { return n } -func (n *ClosureRead) String() string { return fmt.Sprint(n) } -func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ClosureRead) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} - func (n *ClosureRead) Type() *types.Type { return n.typ } func (n *ClosureRead) Offset() int64 { return n.offset } -func (n *ClosureRead) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - return err -} -func (n *ClosureRead) editChildren(edit func(Node) Node) { - editList(n.init, edit) -} // A CompLitExpr is a composite literal Type{Vals}. // Before type-checking, the type is Ntype. @@ -426,27 +291,6 @@ func NewCompLitExpr(pos src.XPos, typ Ntype, list []Node) *CompLitExpr { return n } -func (n *CompLitExpr) String() string { return fmt.Sprint(n) } -func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CompLitExpr) copy() Node { - c := *n - c.init = c.init.Copy() - c.list = c.list.Copy() - return &c -} -func (n *CompLitExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Ntype, err, do) - err = maybeDoList(n.list, err, do) - return err -} -func (n *CompLitExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Ntype = toNtype(maybeEdit(n.Ntype, edit)) - editList(n.list, edit) -} - func (n *CompLitExpr) Orig() Node { return n.orig } func (n *CompLitExpr) SetOrig(x Node) { n.orig = x } func (n *CompLitExpr) Right() Node { return n.Ntype } @@ -480,12 +324,6 @@ func NewConstExpr(val constant.Value, orig Node) Node { return n } -func (n *ConstExpr) String() string { return fmt.Sprint(n) } -func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ConstExpr) copy() Node { c := *n; return &c } -func (n *ConstExpr) doChildren(do func(Node) error) error { return nil } -func (n *ConstExpr) editChildren(edit func(Node) Node) {} - func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() } func (n *ConstExpr) Orig() Node { return n.orig } func (n *ConstExpr) SetOrig(orig Node) { panic(n.no("SetOrig")) } @@ -495,8 +333,7 @@ func (n *ConstExpr) Val() constant.Value { return n.val } // It may end up being a value or a type. type ConvExpr struct { miniExpr - orig Node - X Node + X Node } func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr { @@ -504,29 +341,9 @@ func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr { n.pos = pos n.typ = typ n.SetOp(op) - n.orig = n return n } -func (n *ConvExpr) String() string { return fmt.Sprint(n) } -func (n *ConvExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ConvExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *ConvExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - return err -} -func (n *ConvExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) -} - -func (n *ConvExpr) rawCopy() Node { c := *n; return &c } func (n *ConvExpr) Left() Node { return n.X } func (n *ConvExpr) SetLeft(x Node) { n.X = x } @@ -554,26 +371,6 @@ func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr { return n } -func (n *IndexExpr) String() string { return fmt.Sprint(n) } -func (n *IndexExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *IndexExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *IndexExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - err = maybeDo(n.Index, err, do) - return err -} -func (n *IndexExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) - n.Index = maybeEdit(n.Index, edit) -} - func (n *IndexExpr) Left() Node { return n.X } func (n *IndexExpr) SetLeft(x Node) { n.X = x } func (n *IndexExpr) Right() Node { return n.Index } @@ -608,26 +405,6 @@ func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr { return n } -func (n *KeyExpr) String() string { return fmt.Sprint(n) } -func (n *KeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *KeyExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *KeyExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Key, err, do) - err = maybeDo(n.Value, err, do) - return err -} -func (n *KeyExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Key = maybeEdit(n.Key, edit) - n.Value = maybeEdit(n.Value, edit) -} - func (n *KeyExpr) Left() Node { return n.Key } func (n *KeyExpr) SetLeft(x Node) { n.Key = x } func (n *KeyExpr) Right() Node { return n.Value } @@ -662,28 +439,6 @@ func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { return n } -func (n *InlinedCallExpr) String() string { return fmt.Sprint(n) } -func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *InlinedCallExpr) copy() Node { - c := *n - c.init = c.init.Copy() - c.body = c.body.Copy() - c.ReturnVars = c.ReturnVars.Copy() - return &c -} -func (n *InlinedCallExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDoList(n.body, err, do) - err = maybeDoList(n.ReturnVars, err, do) - return err -} -func (n *InlinedCallExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - editList(n.body, edit) - editList(n.ReturnVars, edit) -} - func (n *InlinedCallExpr) Body() Nodes { return n.body } func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.body } func (n *InlinedCallExpr) SetBody(x Nodes) { n.body = x } @@ -707,26 +462,6 @@ func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr { return n } -func (n *MakeExpr) String() string { return fmt.Sprint(n) } -func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *MakeExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *MakeExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Len, err, do) - err = maybeDo(n.Cap, err, do) - return err -} -func (n *MakeExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Len = maybeEdit(n.Len, edit) - n.Cap = maybeEdit(n.Cap, edit) -} - func (n *MakeExpr) Left() Node { return n.Len } func (n *MakeExpr) SetLeft(x Node) { n.Len = x } func (n *MakeExpr) Right() Node { return n.Cap } @@ -760,26 +495,6 @@ func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr { return n } -func (n *MethodExpr) String() string { return fmt.Sprint(n) } -func (n *MethodExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *MethodExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *MethodExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - err = maybeDo(n.M, err, do) - return err -} -func (n *MethodExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) - n.M = maybeEdit(n.M, edit) -} - func (n *MethodExpr) Left() Node { return n.X } func (n *MethodExpr) SetLeft(x Node) { n.X = x } func (n *MethodExpr) Right() Node { return n.M } @@ -805,22 +520,6 @@ func NewNilExpr(pos src.XPos) *NilExpr { return n } -func (n *NilExpr) String() string { return fmt.Sprint(n) } -func (n *NilExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *NilExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *NilExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - return err -} -func (n *NilExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) -} - func (n *NilExpr) Sym() *types.Sym { return n.sym } func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x } @@ -838,24 +537,6 @@ func NewParenExpr(pos src.XPos, x Node) *ParenExpr { return n } -func (n *ParenExpr) String() string { return fmt.Sprint(n) } -func (n *ParenExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ParenExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *ParenExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - return err -} -func (n *ParenExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) -} - func (n *ParenExpr) Left() Node { return n.X } func (n *ParenExpr) SetLeft(x Node) { n.X = x } @@ -883,22 +564,6 @@ func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr { return n } -func (n *ResultExpr) String() string { return fmt.Sprint(n) } -func (n *ResultExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ResultExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *ResultExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - return err -} -func (n *ResultExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) -} - func (n *ResultExpr) Offset() int64 { return n.offset } func (n *ResultExpr) SetOffset(x int64) { n.offset = x } @@ -928,24 +593,6 @@ func (n *SelectorExpr) SetOp(op Op) { } } -func (n *SelectorExpr) String() string { return fmt.Sprint(n) } -func (n *SelectorExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SelectorExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *SelectorExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - return err -} -func (n *SelectorExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) -} - func (n *SelectorExpr) Left() Node { return n.X } func (n *SelectorExpr) SetLeft(x Node) { n.X = x } func (n *SelectorExpr) Sym() *types.Sym { return n.Sel } @@ -971,27 +618,6 @@ func NewSliceExpr(pos src.XPos, op Op, x Node) *SliceExpr { return n } -func (n *SliceExpr) String() string { return fmt.Sprint(n) } -func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SliceExpr) copy() Node { - c := *n - c.init = c.init.Copy() - c.list = c.list.Copy() - return &c -} -func (n *SliceExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - err = maybeDoList(n.list, err, do) - return err -} -func (n *SliceExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) - editList(n.list, edit) -} - func (n *SliceExpr) Left() Node { return n.X } func (n *SliceExpr) SetLeft(x Node) { n.X = x } func (n *SliceExpr) List() Nodes { return n.list } @@ -1091,26 +717,6 @@ func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *Slic return n } -func (n *SliceHeaderExpr) String() string { return fmt.Sprint(n) } -func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SliceHeaderExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *SliceHeaderExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Ptr, err, do) - err = maybeDoList(n.lenCap, err, do) - return err -} -func (n *SliceHeaderExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Ptr = maybeEdit(n.Ptr, edit) - editList(n.lenCap, edit) -} - func (n *SliceHeaderExpr) Left() Node { return n.Ptr } func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x } func (n *SliceHeaderExpr) List() Nodes { return n.lenCap } @@ -1131,24 +737,6 @@ func NewStarExpr(pos src.XPos, x Node) *StarExpr { return n } -func (n *StarExpr) String() string { return fmt.Sprint(n) } -func (n *StarExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *StarExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *StarExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - return err -} -func (n *StarExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) -} - func (n *StarExpr) Left() Node { return n.X } func (n *StarExpr) SetLeft(x Node) { n.X = x } @@ -1179,29 +767,6 @@ func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr { return n } -func (n *TypeAssertExpr) String() string { return fmt.Sprint(n) } -func (n *TypeAssertExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *TypeAssertExpr) copy() Node { - c := *n - c.init = c.init.Copy() - c.Itab = c.Itab.Copy() - return &c -} -func (n *TypeAssertExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - err = maybeDo(n.Ntype, err, do) - err = maybeDoList(n.Itab, err, do) - return err -} -func (n *TypeAssertExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) - n.Ntype = maybeEdit(n.Ntype, edit) - editList(n.Itab, edit) -} - func (n *TypeAssertExpr) Left() Node { return n.X } func (n *TypeAssertExpr) SetLeft(x Node) { n.X = x } func (n *TypeAssertExpr) Right() Node { return n.Ntype } @@ -1233,24 +798,6 @@ func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr { return n } -func (n *UnaryExpr) String() string { return fmt.Sprint(n) } -func (n *UnaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *UnaryExpr) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *UnaryExpr) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - return err -} -func (n *UnaryExpr) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) -} - func (n *UnaryExpr) Left() Node { return n.X } func (n *UnaryExpr) SetLeft(x Node) { n.X = x } diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 78e98c4d31..38e00da7da 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -9,7 +9,6 @@ import ( "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/src" - "fmt" ) // A Func corresponds to a single function in a Go program @@ -115,18 +114,6 @@ func NewFunc(pos src.XPos) *Func { return f } -func (f *Func) String() string { return fmt.Sprint(f) } -func (f *Func) Format(s fmt.State, verb rune) { FmtNode(f, s, verb) } -func (f *Func) copy() Node { panic(f.no("copy")) } -func (f *Func) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(f.body, err, do) - return err -} -func (f *Func) editChildren(edit func(Node) Node) { - editList(f.body, edit) -} - func (f *Func) Func() *Func { return f } func (f *Func) Body() Nodes { return f.body } func (f *Func) PtrBody() *Nodes { return &f.body } diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index 909ca0220d..612e7d62c3 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:generate go run -mod=mod mknode.go + package ir import ( @@ -33,6 +35,12 @@ type miniNode struct { esc uint16 } +func (n *miniNode) String() string { panic(1) } +func (n *miniNode) Format(s fmt.State, verb rune) { panic(1) } +func (n *miniNode) copy() Node { panic(1) } +func (n *miniNode) doChildren(do func(Node) error) error { panic(1) } +func (n *miniNode) editChildren(edit func(Node) Node) { panic(1) } + // posOr returns pos if known, or else n.pos. // For use in DeepCopy. func (n *miniNode) posOr(pos src.XPos) src.XPos { diff --git a/src/cmd/compile/internal/ir/mknode.go b/src/cmd/compile/internal/ir/mknode.go new file mode 100644 index 0000000000..2c007f93f1 --- /dev/null +++ b/src/cmd/compile/internal/ir/mknode.go @@ -0,0 +1,175 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "bytes" + "fmt" + "go/format" + "go/types" + "io/ioutil" + "log" + "strings" + + "golang.org/x/tools/go/packages" +) + +func main() { + cfg := &packages.Config{ + Mode: packages.NeedSyntax | packages.NeedTypes, + } + pkgs, err := packages.Load(cfg, "cmd/compile/internal/ir") + if err != nil { + log.Fatal(err) + } + + pkg := pkgs[0].Types + scope := pkg.Scope() + + lookup := func(name string) *types.Named { + return scope.Lookup(name).(*types.TypeName).Type().(*types.Named) + } + + nodeType := lookup("Node") + ntypeType := lookup("Ntype") + nodesType := lookup("Nodes") + ptrFieldType := types.NewPointer(lookup("Field")) + slicePtrFieldType := types.NewSlice(ptrFieldType) + ptrNameType := types.NewPointer(lookup("Name")) + + var buf bytes.Buffer + fmt.Fprintln(&buf, "// Code generated by mknode.go. DO NOT EDIT.") + fmt.Fprintln(&buf) + fmt.Fprintln(&buf, "package ir") + fmt.Fprintln(&buf) + fmt.Fprintln(&buf, `import "fmt"`) + + for _, name := range scope.Names() { + obj, ok := scope.Lookup(name).(*types.TypeName) + if !ok { + continue + } + + typName := obj.Name() + typ, ok := obj.Type().(*types.Named).Underlying().(*types.Struct) + if !ok { + continue + } + + if strings.HasPrefix(typName, "mini") || !hasMiniNode(typ) { + continue + } + + fmt.Fprintf(&buf, "\n") + fmt.Fprintf(&buf, "func (n *%s) String() string { return fmt.Sprint(n) }\n", name) + fmt.Fprintf(&buf, "func (n *%s) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }\n", name) + + fmt.Fprintf(&buf, "func (n *%s) copy() Node { c := *n\n", name) + forNodeFields(typName, typ, func(name string, is func(types.Type) bool) { + switch { + case is(nodesType): + fmt.Fprintf(&buf, "c.%s = c.%s.Copy()\n", name, name) + case is(ptrFieldType): + fmt.Fprintf(&buf, "if c.%s != nil { c.%s = c.%s.copy() }\n", name, name, name) + case is(slicePtrFieldType): + fmt.Fprintf(&buf, "c.%s = copyFields(c.%s)\n", name, name) + } + }) + fmt.Fprintf(&buf, "return &c }\n") + + fmt.Fprintf(&buf, "func (n *%s) doChildren(do func(Node) error) error { var err error\n", name) + forNodeFields(typName, typ, func(name string, is func(types.Type) bool) { + switch { + case is(ptrNameType): + fmt.Fprintf(&buf, "if n.%s != nil { err = maybeDo(n.%s, err, do) }\n", name, name) + case is(nodeType), is(ntypeType): + fmt.Fprintf(&buf, "err = maybeDo(n.%s, err, do)\n", name) + case is(nodesType): + fmt.Fprintf(&buf, "err = maybeDoList(n.%s, err, do)\n", name) + case is(ptrFieldType): + fmt.Fprintf(&buf, "err = maybeDoField(n.%s, err, do)\n", name) + case is(slicePtrFieldType): + fmt.Fprintf(&buf, "err = maybeDoFields(n.%s, err, do)\n", name) + } + }) + fmt.Fprintf(&buf, "return err }\n") + + fmt.Fprintf(&buf, "func (n *%s) editChildren(edit func(Node) Node) {\n", name) + forNodeFields(typName, typ, func(name string, is func(types.Type) bool) { + switch { + case is(ptrNameType): + fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Name) }\n", name, name, name) + case is(nodeType): + fmt.Fprintf(&buf, "n.%s = maybeEdit(n.%s, edit)\n", name, name) + case is(ntypeType): + fmt.Fprintf(&buf, "n.%s = toNtype(maybeEdit(n.%s, edit))\n", name, name) + case is(nodesType): + fmt.Fprintf(&buf, "editList(n.%s, edit)\n", name) + case is(ptrFieldType): + fmt.Fprintf(&buf, "editField(n.%s, edit)\n", name) + case is(slicePtrFieldType): + fmt.Fprintf(&buf, "editFields(n.%s, edit)\n", name) + } + }) + fmt.Fprintf(&buf, "}\n") + } + + out, err := format.Source(buf.Bytes()) + if err != nil { + // write out mangled source so we can see the bug. + out = buf.Bytes() + } + + err = ioutil.WriteFile("node_gen.go", out, 0666) + if err != nil { + log.Fatal(err) + } +} + +func forNodeFields(typName string, typ *types.Struct, f func(name string, is func(types.Type) bool)) { + for i, n := 0, typ.NumFields(); i < n; i++ { + v := typ.Field(i) + if v.Embedded() { + if typ, ok := v.Type().Underlying().(*types.Struct); ok { + forNodeFields(typName, typ, f) + continue + } + } + switch typName { + case "Func": + if v.Name() != "body" { + continue + } + case "Name", "Pack": + continue + } + switch v.Name() { + case "orig": + continue + } + switch typName + "." + v.Name() { + case "AddStringExpr.Alloc": + continue + } + f(v.Name(), func(t types.Type) bool { return types.Identical(t, v.Type()) }) + } +} + +func hasMiniNode(typ *types.Struct) bool { + for i, n := 0, typ.NumFields(); i < n; i++ { + v := typ.Field(i) + if v.Name() == "miniNode" { + return true + } + if v.Embedded() { + if typ, ok := v.Type().Underlying().(*types.Struct); ok && hasMiniNode(typ) { + return true + } + } + } + return false +} diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 030fb82a7d..06cffe0325 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -9,7 +9,7 @@ import ( "cmd/compile/internal/types" "cmd/internal/objabi" "cmd/internal/src" - "fmt" + "go/constant" ) @@ -149,12 +149,6 @@ func newNameAt(pos src.XPos, op Op, sym *types.Sym) *Name { return n } -func (n *Name) String() string { return fmt.Sprint(n) } -func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *Name) copy() Node { c := *n; return &c } -func (n *Name) doChildren(do func(Node) error) error { return nil } -func (n *Name) editChildren(edit func(Node) Node) {} - func (n *Name) Name() *Name { return n } func (n *Name) Sym() *types.Sym { return n.sym } func (n *Name) SetSym(x *types.Sym) { n.sym = x } @@ -361,12 +355,6 @@ type PkgName struct { Used bool } -func (p *PkgName) String() string { return fmt.Sprint(p) } -func (p *PkgName) Format(s fmt.State, verb rune) { FmtNode(p, s, verb) } -func (p *PkgName) copy() Node { c := *p; return &c } -func (p *PkgName) doChildren(do func(Node) error) error { return nil } -func (p *PkgName) editChildren(edit func(Node) Node) {} - func (p *PkgName) Sym() *types.Sym { return p.sym } func (*PkgName) CanBeNtype() {} diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go new file mode 100644 index 0000000000..4c47a4486e --- /dev/null +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -0,0 +1,1029 @@ +// Code generated by mknode.go. DO NOT EDIT. + +package ir + +import "fmt" + +func (n *AddStringExpr) String() string { return fmt.Sprint(n) } +func (n *AddStringExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AddStringExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.list = c.list.Copy() + return &c +} +func (n *AddStringExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.list, err, do) + return err +} +func (n *AddStringExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.list, edit) +} + +func (n *AddrExpr) String() string { return fmt.Sprint(n) } +func (n *AddrExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AddrExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *AddrExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Alloc, err, do) + return err +} +func (n *AddrExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Alloc = maybeEdit(n.Alloc, edit) +} + +func (n *ArrayType) String() string { return fmt.Sprint(n) } +func (n *ArrayType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ArrayType) copy() Node { + c := *n + return &c +} +func (n *ArrayType) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.Len, err, do) + err = maybeDo(n.Elem, err, do) + return err +} +func (n *ArrayType) editChildren(edit func(Node) Node) { + n.Len = maybeEdit(n.Len, edit) + n.Elem = maybeEdit(n.Elem, edit) +} + +func (n *AssignListStmt) String() string { return fmt.Sprint(n) } +func (n *AssignListStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AssignListStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Lhs = c.Lhs.Copy() + c.Rhs = c.Rhs.Copy() + return &c +} +func (n *AssignListStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Lhs, err, do) + err = maybeDoList(n.Rhs, err, do) + return err +} +func (n *AssignListStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Lhs, edit) + editList(n.Rhs, edit) +} + +func (n *AssignOpStmt) String() string { return fmt.Sprint(n) } +func (n *AssignOpStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AssignOpStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *AssignOpStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Y, err, do) + return err +} +func (n *AssignOpStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Y = maybeEdit(n.Y, edit) +} + +func (n *AssignStmt) String() string { return fmt.Sprint(n) } +func (n *AssignStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *AssignStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *AssignStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Y, err, do) + return err +} +func (n *AssignStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Y = maybeEdit(n.Y, edit) +} + +func (n *BinaryExpr) String() string { return fmt.Sprint(n) } +func (n *BinaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *BinaryExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *BinaryExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Y, err, do) + return err +} +func (n *BinaryExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Y = maybeEdit(n.Y, edit) +} + +func (n *BlockStmt) String() string { return fmt.Sprint(n) } +func (n *BlockStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *BlockStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.list = c.list.Copy() + return &c +} +func (n *BlockStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.list, err, do) + return err +} +func (n *BlockStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.list, edit) +} + +func (n *BranchStmt) String() string { return fmt.Sprint(n) } +func (n *BranchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *BranchStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *BranchStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} +func (n *BranchStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} + +func (n *CallExpr) String() string { return fmt.Sprint(n) } +func (n *CallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *CallExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.Args = c.Args.Copy() + c.Rargs = c.Rargs.Copy() + c.body = c.body.Copy() + return &c +} +func (n *CallExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDoList(n.Args, err, do) + err = maybeDoList(n.Rargs, err, do) + err = maybeDoList(n.body, err, do) + return err +} +func (n *CallExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + editList(n.Args, edit) + editList(n.Rargs, edit) + editList(n.body, edit) +} + +func (n *CallPartExpr) String() string { return fmt.Sprint(n) } +func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *CallPartExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *CallPartExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} +func (n *CallPartExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} + +func (n *CaseStmt) String() string { return fmt.Sprint(n) } +func (n *CaseStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *CaseStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Vars = c.Vars.Copy() + c.list = c.list.Copy() + c.body = c.body.Copy() + return &c +} +func (n *CaseStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Vars, err, do) + err = maybeDoList(n.list, err, do) + err = maybeDo(n.Comm, err, do) + err = maybeDoList(n.body, err, do) + return err +} +func (n *CaseStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Vars, edit) + editList(n.list, edit) + n.Comm = maybeEdit(n.Comm, edit) + editList(n.body, edit) +} + +func (n *ChanType) String() string { return fmt.Sprint(n) } +func (n *ChanType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ChanType) copy() Node { + c := *n + return &c +} +func (n *ChanType) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.Elem, err, do) + return err +} +func (n *ChanType) editChildren(edit func(Node) Node) { + n.Elem = maybeEdit(n.Elem, edit) +} + +func (n *ClosureExpr) String() string { return fmt.Sprint(n) } +func (n *ClosureExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ClosureExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *ClosureExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} +func (n *ClosureExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} + +func (n *ClosureRead) String() string { return fmt.Sprint(n) } +func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ClosureRead) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *ClosureRead) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} +func (n *ClosureRead) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} + +func (n *CompLitExpr) String() string { return fmt.Sprint(n) } +func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *CompLitExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.list = c.list.Copy() + return &c +} +func (n *CompLitExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Ntype, err, do) + err = maybeDoList(n.list, err, do) + return err +} +func (n *CompLitExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Ntype = toNtype(maybeEdit(n.Ntype, edit)) + editList(n.list, edit) +} + +func (n *ConstExpr) String() string { return fmt.Sprint(n) } +func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ConstExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *ConstExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} +func (n *ConstExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} + +func (n *ConvExpr) String() string { return fmt.Sprint(n) } +func (n *ConvExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ConvExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *ConvExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} +func (n *ConvExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} + +func (n *Decl) String() string { return fmt.Sprint(n) } +func (n *Decl) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *Decl) copy() Node { + c := *n + return &c +} +func (n *Decl) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.X, err, do) + return err +} +func (n *Decl) editChildren(edit func(Node) Node) { + n.X = maybeEdit(n.X, edit) +} + +func (n *DeferStmt) String() string { return fmt.Sprint(n) } +func (n *DeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *DeferStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *DeferStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Call, err, do) + return err +} +func (n *DeferStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Call = maybeEdit(n.Call, edit) +} + +func (n *ForStmt) String() string { return fmt.Sprint(n) } +func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ForStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Late = c.Late.Copy() + c.body = c.body.Copy() + return &c +} +func (n *ForStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Cond, err, do) + err = maybeDoList(n.Late, err, do) + err = maybeDo(n.Post, err, do) + err = maybeDoList(n.body, err, do) + return err +} +func (n *ForStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Cond = maybeEdit(n.Cond, edit) + editList(n.Late, edit) + n.Post = maybeEdit(n.Post, edit) + editList(n.body, edit) +} + +func (n *Func) String() string { return fmt.Sprint(n) } +func (n *Func) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *Func) copy() Node { + c := *n + c.body = c.body.Copy() + return &c +} +func (n *Func) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.body, err, do) + return err +} +func (n *Func) editChildren(edit func(Node) Node) { + editList(n.body, edit) +} + +func (n *FuncType) String() string { return fmt.Sprint(n) } +func (n *FuncType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *FuncType) copy() Node { + c := *n + if c.Recv != nil { + c.Recv = c.Recv.copy() + } + c.Params = copyFields(c.Params) + c.Results = copyFields(c.Results) + return &c +} +func (n *FuncType) doChildren(do func(Node) error) error { + var err error + err = maybeDoField(n.Recv, err, do) + err = maybeDoFields(n.Params, err, do) + err = maybeDoFields(n.Results, err, do) + return err +} +func (n *FuncType) editChildren(edit func(Node) Node) { + editField(n.Recv, edit) + editFields(n.Params, edit) + editFields(n.Results, edit) +} + +func (n *GoStmt) String() string { return fmt.Sprint(n) } +func (n *GoStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *GoStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *GoStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Call, err, do) + return err +} +func (n *GoStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Call = maybeEdit(n.Call, edit) +} + +func (n *IfStmt) String() string { return fmt.Sprint(n) } +func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *IfStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.body = c.body.Copy() + c.Else = c.Else.Copy() + return &c +} +func (n *IfStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Cond, err, do) + err = maybeDoList(n.body, err, do) + err = maybeDoList(n.Else, err, do) + return err +} +func (n *IfStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Cond = maybeEdit(n.Cond, edit) + editList(n.body, edit) + editList(n.Else, edit) +} + +func (n *IndexExpr) String() string { return fmt.Sprint(n) } +func (n *IndexExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *IndexExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *IndexExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Index, err, do) + return err +} +func (n *IndexExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Index = maybeEdit(n.Index, edit) +} + +func (n *InlineMarkStmt) String() string { return fmt.Sprint(n) } +func (n *InlineMarkStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *InlineMarkStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *InlineMarkStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} +func (n *InlineMarkStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} + +func (n *InlinedCallExpr) String() string { return fmt.Sprint(n) } +func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *InlinedCallExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.body = c.body.Copy() + c.ReturnVars = c.ReturnVars.Copy() + return &c +} +func (n *InlinedCallExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.body, err, do) + err = maybeDoList(n.ReturnVars, err, do) + return err +} +func (n *InlinedCallExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.body, edit) + editList(n.ReturnVars, edit) +} + +func (n *InterfaceType) String() string { return fmt.Sprint(n) } +func (n *InterfaceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *InterfaceType) copy() Node { + c := *n + c.Methods = copyFields(c.Methods) + return &c +} +func (n *InterfaceType) doChildren(do func(Node) error) error { + var err error + err = maybeDoFields(n.Methods, err, do) + return err +} +func (n *InterfaceType) editChildren(edit func(Node) Node) { + editFields(n.Methods, edit) +} + +func (n *KeyExpr) String() string { return fmt.Sprint(n) } +func (n *KeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *KeyExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *KeyExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Key, err, do) + err = maybeDo(n.Value, err, do) + return err +} +func (n *KeyExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Key = maybeEdit(n.Key, edit) + n.Value = maybeEdit(n.Value, edit) +} + +func (n *LabelStmt) String() string { return fmt.Sprint(n) } +func (n *LabelStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *LabelStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *LabelStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} +func (n *LabelStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} + +func (n *MakeExpr) String() string { return fmt.Sprint(n) } +func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *MakeExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *MakeExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Len, err, do) + err = maybeDo(n.Cap, err, do) + return err +} +func (n *MakeExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Len = maybeEdit(n.Len, edit) + n.Cap = maybeEdit(n.Cap, edit) +} + +func (n *MapType) String() string { return fmt.Sprint(n) } +func (n *MapType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *MapType) copy() Node { + c := *n + return &c +} +func (n *MapType) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.Key, err, do) + err = maybeDo(n.Elem, err, do) + return err +} +func (n *MapType) editChildren(edit func(Node) Node) { + n.Key = maybeEdit(n.Key, edit) + n.Elem = maybeEdit(n.Elem, edit) +} + +func (n *MethodExpr) String() string { return fmt.Sprint(n) } +func (n *MethodExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *MethodExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *MethodExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.M, err, do) + return err +} +func (n *MethodExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.M = maybeEdit(n.M, edit) +} + +func (n *Name) String() string { return fmt.Sprint(n) } +func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *Name) copy() Node { + c := *n + return &c +} +func (n *Name) doChildren(do func(Node) error) error { + var err error + return err +} +func (n *Name) editChildren(edit func(Node) Node) { +} + +func (n *NilExpr) String() string { return fmt.Sprint(n) } +func (n *NilExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *NilExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *NilExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} +func (n *NilExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} + +func (n *ParenExpr) String() string { return fmt.Sprint(n) } +func (n *ParenExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ParenExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *ParenExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} +func (n *ParenExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} + +func (n *PkgName) String() string { return fmt.Sprint(n) } +func (n *PkgName) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *PkgName) copy() Node { + c := *n + return &c +} +func (n *PkgName) doChildren(do func(Node) error) error { + var err error + return err +} +func (n *PkgName) editChildren(edit func(Node) Node) { +} + +func (n *RangeStmt) String() string { return fmt.Sprint(n) } +func (n *RangeStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *RangeStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Vars = c.Vars.Copy() + c.body = c.body.Copy() + return &c +} +func (n *RangeStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Vars, err, do) + err = maybeDo(n.X, err, do) + err = maybeDoList(n.body, err, do) + return err +} +func (n *RangeStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Vars, edit) + n.X = maybeEdit(n.X, edit) + editList(n.body, edit) +} + +func (n *ResultExpr) String() string { return fmt.Sprint(n) } +func (n *ResultExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ResultExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *ResultExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} +func (n *ResultExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} + +func (n *ReturnStmt) String() string { return fmt.Sprint(n) } +func (n *ReturnStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ReturnStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Results = c.Results.Copy() + return &c +} +func (n *ReturnStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Results, err, do) + return err +} +func (n *ReturnStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Results, edit) +} + +func (n *SelectStmt) String() string { return fmt.Sprint(n) } +func (n *SelectStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SelectStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Cases = c.Cases.Copy() + c.Compiled = c.Compiled.Copy() + return &c +} +func (n *SelectStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDoList(n.Cases, err, do) + err = maybeDoList(n.Compiled, err, do) + return err +} +func (n *SelectStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + editList(n.Cases, edit) + editList(n.Compiled, edit) +} + +func (n *SelectorExpr) String() string { return fmt.Sprint(n) } +func (n *SelectorExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SelectorExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *SelectorExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} +func (n *SelectorExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} + +func (n *SendStmt) String() string { return fmt.Sprint(n) } +func (n *SendStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SendStmt) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *SendStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Chan, err, do) + err = maybeDo(n.Value, err, do) + return err +} +func (n *SendStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Chan = maybeEdit(n.Chan, edit) + n.Value = maybeEdit(n.Value, edit) +} + +func (n *SliceExpr) String() string { return fmt.Sprint(n) } +func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SliceExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.list = c.list.Copy() + return &c +} +func (n *SliceExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDoList(n.list, err, do) + return err +} +func (n *SliceExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + editList(n.list, edit) +} + +func (n *SliceHeaderExpr) String() string { return fmt.Sprint(n) } +func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SliceHeaderExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.lenCap = c.lenCap.Copy() + return &c +} +func (n *SliceHeaderExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Ptr, err, do) + err = maybeDoList(n.lenCap, err, do) + return err +} +func (n *SliceHeaderExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Ptr = maybeEdit(n.Ptr, edit) + editList(n.lenCap, edit) +} + +func (n *SliceType) String() string { return fmt.Sprint(n) } +func (n *SliceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SliceType) copy() Node { + c := *n + return &c +} +func (n *SliceType) doChildren(do func(Node) error) error { + var err error + err = maybeDo(n.Elem, err, do) + return err +} +func (n *SliceType) editChildren(edit func(Node) Node) { + n.Elem = maybeEdit(n.Elem, edit) +} + +func (n *StarExpr) String() string { return fmt.Sprint(n) } +func (n *StarExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *StarExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *StarExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} +func (n *StarExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} + +func (n *StructType) String() string { return fmt.Sprint(n) } +func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *StructType) copy() Node { + c := *n + c.Fields = copyFields(c.Fields) + return &c +} +func (n *StructType) doChildren(do func(Node) error) error { + var err error + err = maybeDoFields(n.Fields, err, do) + return err +} +func (n *StructType) editChildren(edit func(Node) Node) { + editFields(n.Fields, edit) +} + +func (n *SwitchStmt) String() string { return fmt.Sprint(n) } +func (n *SwitchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *SwitchStmt) copy() Node { + c := *n + c.init = c.init.Copy() + c.Cases = c.Cases.Copy() + c.Compiled = c.Compiled.Copy() + return &c +} +func (n *SwitchStmt) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Tag, err, do) + err = maybeDoList(n.Cases, err, do) + err = maybeDoList(n.Compiled, err, do) + return err +} +func (n *SwitchStmt) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Tag = maybeEdit(n.Tag, edit) + editList(n.Cases, edit) + editList(n.Compiled, edit) +} + +func (n *TypeAssertExpr) String() string { return fmt.Sprint(n) } +func (n *TypeAssertExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *TypeAssertExpr) copy() Node { + c := *n + c.init = c.init.Copy() + c.Itab = c.Itab.Copy() + return &c +} +func (n *TypeAssertExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Ntype, err, do) + err = maybeDoList(n.Itab, err, do) + return err +} +func (n *TypeAssertExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Ntype = maybeEdit(n.Ntype, edit) + editList(n.Itab, edit) +} + +func (n *TypeSwitchGuard) String() string { return fmt.Sprint(n) } +func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *TypeSwitchGuard) copy() Node { + c := *n + return &c +} +func (n *TypeSwitchGuard) doChildren(do func(Node) error) error { + var err error + if n.name != nil { + err = maybeDo(n.name, err, do) + } + err = maybeDo(n.X, err, do) + return err +} +func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) { + if n.name != nil { + n.name = edit(n.name).(*Name) + } + n.X = maybeEdit(n.X, edit) +} + +func (n *UnaryExpr) String() string { return fmt.Sprint(n) } +func (n *UnaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *UnaryExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *UnaryExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + return err +} +func (n *UnaryExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) +} + +func (n *typeNode) String() string { return fmt.Sprint(n) } +func (n *typeNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *typeNode) copy() Node { + c := *n + return &c +} +func (n *typeNode) doChildren(do func(Node) error) error { + var err error + return err +} +func (n *typeNode) editChildren(edit func(Node) Node) { +} diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index c859fae55b..19f90ce1fa 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -7,7 +7,6 @@ package ir import ( "cmd/compile/internal/types" "cmd/internal/src" - "fmt" ) // A Decl is a declaration of a const, type, or var. (A declared func is a Func.) @@ -28,18 +27,6 @@ func NewDecl(pos src.XPos, op Op, x Node) *Decl { return n } -func (n *Decl) String() string { return fmt.Sprint(n) } -func (n *Decl) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *Decl) copy() Node { c := *n; return &c } -func (n *Decl) doChildren(do func(Node) error) error { - var err error - err = maybeDo(n.X, err, do) - return err -} -func (n *Decl) editChildren(edit func(Node) Node) { - n.X = maybeEdit(n.X, edit) -} - func (n *Decl) Left() Node { return n.X } func (n *Decl) SetLeft(x Node) { n.X = x } @@ -76,28 +63,6 @@ func NewAssignListStmt(pos src.XPos, lhs, rhs []Node) *AssignListStmt { return n } -func (n *AssignListStmt) String() string { return fmt.Sprint(n) } -func (n *AssignListStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AssignListStmt) copy() Node { - c := *n - c.init = c.init.Copy() - c.Lhs = c.Lhs.Copy() - c.Rhs = c.Rhs.Copy() - return &c -} -func (n *AssignListStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDoList(n.Lhs, err, do) - err = maybeDoList(n.Rhs, err, do) - return err -} -func (n *AssignListStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - editList(n.Lhs, edit) - editList(n.Rhs, edit) -} - func (n *AssignListStmt) List() Nodes { return n.Lhs } func (n *AssignListStmt) PtrList() *Nodes { return &n.Lhs } func (n *AssignListStmt) SetList(x Nodes) { n.Lhs = x } @@ -136,26 +101,6 @@ func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt { return n } -func (n *AssignStmt) String() string { return fmt.Sprint(n) } -func (n *AssignStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AssignStmt) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *AssignStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - err = maybeDo(n.Y, err, do) - return err -} -func (n *AssignStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) - n.Y = maybeEdit(n.Y, edit) -} - func (n *AssignStmt) Left() Node { return n.X } func (n *AssignStmt) SetLeft(x Node) { n.X = x } func (n *AssignStmt) Right() Node { return n.Y } @@ -191,26 +136,6 @@ func NewAssignOpStmt(pos src.XPos, op Op, x, y Node) *AssignOpStmt { return n } -func (n *AssignOpStmt) String() string { return fmt.Sprint(n) } -func (n *AssignOpStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *AssignOpStmt) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *AssignOpStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.X, err, do) - err = maybeDo(n.Y, err, do) - return err -} -func (n *AssignOpStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.X = maybeEdit(n.X, edit) - n.Y = maybeEdit(n.Y, edit) -} - func (n *AssignOpStmt) Left() Node { return n.X } func (n *AssignOpStmt) SetLeft(x Node) { n.X = x } func (n *AssignOpStmt) Right() Node { return n.Y } @@ -236,25 +161,6 @@ func NewBlockStmt(pos src.XPos, list []Node) *BlockStmt { return n } -func (n *BlockStmt) String() string { return fmt.Sprint(n) } -func (n *BlockStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *BlockStmt) copy() Node { - c := *n - c.init = c.init.Copy() - c.list = c.list.Copy() - return &c -} -func (n *BlockStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDoList(n.list, err, do) - return err -} -func (n *BlockStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - editList(n.list, edit) -} - func (n *BlockStmt) List() Nodes { return n.list } func (n *BlockStmt) PtrList() *Nodes { return &n.list } func (n *BlockStmt) SetList(x Nodes) { n.list = x } @@ -281,22 +187,6 @@ func NewBranchStmt(pos src.XPos, op Op, label *types.Sym) *BranchStmt { return n } -func (n *BranchStmt) String() string { return fmt.Sprint(n) } -func (n *BranchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *BranchStmt) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *BranchStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - return err -} -func (n *BranchStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) -} - func (n *BranchStmt) Sym() *types.Sym { return n.Label } func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym } @@ -318,33 +208,6 @@ func NewCaseStmt(pos src.XPos, list, body []Node) *CaseStmt { return n } -func (n *CaseStmt) String() string { return fmt.Sprint(n) } -func (n *CaseStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *CaseStmt) copy() Node { - c := *n - c.init = c.init.Copy() - c.Vars = c.Vars.Copy() - c.list = c.list.Copy() - c.body = c.body.Copy() - return &c -} -func (n *CaseStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDoList(n.Vars, err, do) - err = maybeDoList(n.list, err, do) - err = maybeDo(n.Comm, err, do) - err = maybeDoList(n.body, err, do) - return err -} -func (n *CaseStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - editList(n.Vars, edit) - editList(n.list, edit) - n.Comm = maybeEdit(n.Comm, edit) - editList(n.body, edit) -} - func (n *CaseStmt) List() Nodes { return n.list } func (n *CaseStmt) PtrList() *Nodes { return &n.list } func (n *CaseStmt) SetList(x Nodes) { n.list = x } @@ -370,24 +233,6 @@ func NewDeferStmt(pos src.XPos, call Node) *DeferStmt { return n } -func (n *DeferStmt) String() string { return fmt.Sprint(n) } -func (n *DeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *DeferStmt) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *DeferStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Call, err, do) - return err -} -func (n *DeferStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Call = maybeEdit(n.Call, edit) -} - func (n *DeferStmt) Left() Node { return n.Call } func (n *DeferStmt) SetLeft(x Node) { n.Call = x } @@ -412,32 +257,6 @@ func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStm return n } -func (n *ForStmt) String() string { return fmt.Sprint(n) } -func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ForStmt) copy() Node { - c := *n - c.init = c.init.Copy() - c.Late = c.Late.Copy() - c.body = c.body.Copy() - return &c -} -func (n *ForStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Cond, err, do) - err = maybeDoList(n.Late, err, do) - err = maybeDo(n.Post, err, do) - err = maybeDoList(n.body, err, do) - return err -} -func (n *ForStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Cond = maybeEdit(n.Cond, edit) - editList(n.Late, edit) - n.Post = maybeEdit(n.Post, edit) - editList(n.body, edit) -} - func (n *ForStmt) Sym() *types.Sym { return n.Label } func (n *ForStmt) SetSym(x *types.Sym) { n.Label = x } func (n *ForStmt) Left() Node { return n.Cond } @@ -473,24 +292,6 @@ func NewGoStmt(pos src.XPos, call Node) *GoStmt { return n } -func (n *GoStmt) String() string { return fmt.Sprint(n) } -func (n *GoStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *GoStmt) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *GoStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Call, err, do) - return err -} -func (n *GoStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Call = maybeEdit(n.Call, edit) -} - func (n *GoStmt) Left() Node { return n.Call } func (n *GoStmt) SetLeft(x Node) { n.Call = x } @@ -512,30 +313,6 @@ func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt { return n } -func (n *IfStmt) String() string { return fmt.Sprint(n) } -func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *IfStmt) copy() Node { - c := *n - c.init = c.init.Copy() - c.body = c.body.Copy() - c.Else = c.Else.Copy() - return &c -} -func (n *IfStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Cond, err, do) - err = maybeDoList(n.body, err, do) - err = maybeDoList(n.Else, err, do) - return err -} -func (n *IfStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Cond = maybeEdit(n.Cond, edit) - editList(n.body, edit) - editList(n.Else, edit) -} - func (n *IfStmt) Left() Node { return n.Cond } func (n *IfStmt) SetLeft(x Node) { n.Cond = x } func (n *IfStmt) Body() Nodes { return n.body } @@ -560,22 +337,6 @@ func NewInlineMarkStmt(pos src.XPos, index int64) *InlineMarkStmt { return n } -func (n *InlineMarkStmt) String() string { return fmt.Sprint(n) } -func (n *InlineMarkStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *InlineMarkStmt) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *InlineMarkStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - return err -} -func (n *InlineMarkStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) -} - func (n *InlineMarkStmt) Offset() int64 { return n.Index } func (n *InlineMarkStmt) SetOffset(x int64) { n.Index = x } @@ -592,22 +353,6 @@ func NewLabelStmt(pos src.XPos, label *types.Sym) *LabelStmt { return n } -func (n *LabelStmt) String() string { return fmt.Sprint(n) } -func (n *LabelStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *LabelStmt) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *LabelStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - return err -} -func (n *LabelStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) -} - func (n *LabelStmt) Sym() *types.Sym { return n.Label } func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x } @@ -633,30 +378,6 @@ func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt { return n } -func (n *RangeStmt) String() string { return fmt.Sprint(n) } -func (n *RangeStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *RangeStmt) copy() Node { - c := *n - c.init = c.init.Copy() - c.Vars = c.Vars.Copy() - c.body = c.body.Copy() - return &c -} -func (n *RangeStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDoList(n.Vars, err, do) - err = maybeDo(n.X, err, do) - err = maybeDoList(n.body, err, do) - return err -} -func (n *RangeStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - editList(n.Vars, edit) - n.X = maybeEdit(n.X, edit) - editList(n.body, edit) -} - func (n *RangeStmt) Sym() *types.Sym { return n.Label } func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x } func (n *RangeStmt) Right() Node { return n.X } @@ -690,25 +411,6 @@ func NewReturnStmt(pos src.XPos, results []Node) *ReturnStmt { return n } -func (n *ReturnStmt) String() string { return fmt.Sprint(n) } -func (n *ReturnStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ReturnStmt) copy() Node { - c := *n - c.init = c.init.Copy() - c.Results = c.Results.Copy() - return &c -} -func (n *ReturnStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDoList(n.Results, err, do) - return err -} -func (n *ReturnStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - editList(n.Results, edit) -} - func (n *ReturnStmt) Orig() Node { return n.orig } func (n *ReturnStmt) SetOrig(x Node) { n.orig = x } func (n *ReturnStmt) List() Nodes { return n.Results } @@ -735,28 +437,6 @@ func NewSelectStmt(pos src.XPos, cases []Node) *SelectStmt { return n } -func (n *SelectStmt) String() string { return fmt.Sprint(n) } -func (n *SelectStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SelectStmt) copy() Node { - c := *n - c.init = c.init.Copy() - c.Cases = c.Cases.Copy() - c.Compiled = c.Compiled.Copy() - return &c -} -func (n *SelectStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDoList(n.Cases, err, do) - err = maybeDoList(n.Compiled, err, do) - return err -} -func (n *SelectStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - editList(n.Cases, edit) - editList(n.Compiled, edit) -} - func (n *SelectStmt) List() Nodes { return n.Cases } func (n *SelectStmt) PtrList() *Nodes { return &n.Cases } func (n *SelectStmt) SetList(x Nodes) { n.Cases = x } @@ -782,26 +462,6 @@ func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt { return n } -func (n *SendStmt) String() string { return fmt.Sprint(n) } -func (n *SendStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SendStmt) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *SendStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Chan, err, do) - err = maybeDo(n.Value, err, do) - return err -} -func (n *SendStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Chan = maybeEdit(n.Chan, edit) - n.Value = maybeEdit(n.Value, edit) -} - func (n *SendStmt) Left() Node { return n.Chan } func (n *SendStmt) SetLeft(x Node) { n.Chan = x } func (n *SendStmt) Right() Node { return n.Value } @@ -827,30 +487,6 @@ func NewSwitchStmt(pos src.XPos, tag Node, cases []Node) *SwitchStmt { return n } -func (n *SwitchStmt) String() string { return fmt.Sprint(n) } -func (n *SwitchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SwitchStmt) copy() Node { - c := *n - c.init = c.init.Copy() - c.Cases = c.Cases.Copy() - c.Compiled = c.Compiled.Copy() - return &c -} -func (n *SwitchStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Tag, err, do) - err = maybeDoList(n.Cases, err, do) - err = maybeDoList(n.Compiled, err, do) - return err -} -func (n *SwitchStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Tag = maybeEdit(n.Tag, edit) - editList(n.Cases, edit) - editList(n.Compiled, edit) -} - func (n *SwitchStmt) Left() Node { return n.Tag } func (n *SwitchStmt) SetLeft(x Node) { n.Tag = x } func (n *SwitchStmt) List() Nodes { return n.Cases } @@ -881,24 +517,6 @@ func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard { return n } -func (n *TypeSwitchGuard) String() string { return fmt.Sprint(n) } -func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *TypeSwitchGuard) copy() Node { c := *n; return &c } -func (n *TypeSwitchGuard) doChildren(do func(Node) error) error { - var err error - if n.name != nil { - err = maybeDo(n.name, err, do) - } - err = maybeDo(n.X, err, do) - return err -} -func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) { - if n.name != nil { - n.name = edit(n.name).(*Name) - } - n.X = maybeEdit(n.X, edit) -} - func (n *TypeSwitchGuard) Left() Node { if n.name == nil { return nil diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index 9f82c9faa2..5e6d76229d 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -72,17 +72,6 @@ func NewChanType(pos src.XPos, elem Node, dir types.ChanDir) *ChanType { return n } -func (n *ChanType) String() string { return fmt.Sprint(n) } -func (n *ChanType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ChanType) copy() Node { c := *n; return &c } -func (n *ChanType) doChildren(do func(Node) error) error { - var err error - err = maybeDo(n.Elem, err, do) - return err -} -func (n *ChanType) editChildren(edit func(Node) Node) { - n.Elem = maybeEdit(n.Elem, edit) -} func (n *ChanType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -102,19 +91,6 @@ func NewMapType(pos src.XPos, key, elem Node) *MapType { return n } -func (n *MapType) String() string { return fmt.Sprint(n) } -func (n *MapType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *MapType) copy() Node { c := *n; return &c } -func (n *MapType) doChildren(do func(Node) error) error { - var err error - err = maybeDo(n.Key, err, do) - err = maybeDo(n.Elem, err, do) - return err -} -func (n *MapType) editChildren(edit func(Node) Node) { - n.Key = maybeEdit(n.Key, edit) - n.Elem = maybeEdit(n.Elem, edit) -} func (n *MapType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Key = nil @@ -134,22 +110,6 @@ func NewStructType(pos src.XPos, fields []*Field) *StructType { return n } -func (n *StructType) String() string { return fmt.Sprint(n) } -func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *StructType) copy() Node { - c := *n - c.Fields = copyFields(c.Fields) - return &c -} -func (n *StructType) doChildren(do func(Node) error) error { - var err error - err = maybeDoFields(n.Fields, err, do) - return err -} -func (n *StructType) editChildren(edit func(Node) Node) { - editFields(n.Fields, edit) -} - func (n *StructType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Fields = nil @@ -176,22 +136,6 @@ func NewInterfaceType(pos src.XPos, methods []*Field) *InterfaceType { return n } -func (n *InterfaceType) String() string { return fmt.Sprint(n) } -func (n *InterfaceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *InterfaceType) copy() Node { - c := *n - c.Methods = copyFields(c.Methods) - return &c -} -func (n *InterfaceType) doChildren(do func(Node) error) error { - var err error - err = maybeDoFields(n.Methods, err, do) - return err -} -func (n *InterfaceType) editChildren(edit func(Node) Node) { - editFields(n.Methods, edit) -} - func (n *InterfaceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Methods = nil @@ -212,30 +156,6 @@ func NewFuncType(pos src.XPos, rcvr *Field, args, results []*Field) *FuncType { return n } -func (n *FuncType) String() string { return fmt.Sprint(n) } -func (n *FuncType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *FuncType) copy() Node { - c := *n - if c.Recv != nil { - c.Recv = c.Recv.copy() - } - c.Params = copyFields(c.Params) - c.Results = copyFields(c.Results) - return &c -} -func (n *FuncType) doChildren(do func(Node) error) error { - var err error - err = maybeDoField(n.Recv, err, do) - err = maybeDoFields(n.Params, err, do) - err = maybeDoFields(n.Results, err, do) - return err -} -func (n *FuncType) editChildren(edit func(Node) Node) { - editField(n.Recv, edit) - editFields(n.Params, edit) - editFields(n.Results, edit) -} - func (n *FuncType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Recv = nil @@ -365,17 +285,6 @@ func NewSliceType(pos src.XPos, elem Node) *SliceType { return n } -func (n *SliceType) String() string { return fmt.Sprint(n) } -func (n *SliceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *SliceType) copy() Node { c := *n; return &c } -func (n *SliceType) doChildren(do func(Node) error) error { - var err error - err = maybeDo(n.Elem, err, do) - return err -} -func (n *SliceType) editChildren(edit func(Node) Node) { - n.Elem = maybeEdit(n.Elem, edit) -} func (n *SliceType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Elem = nil @@ -396,20 +305,6 @@ func NewArrayType(pos src.XPos, size Node, elem Node) *ArrayType { return n } -func (n *ArrayType) String() string { return fmt.Sprint(n) } -func (n *ArrayType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ArrayType) copy() Node { c := *n; return &c } -func (n *ArrayType) doChildren(do func(Node) error) error { - var err error - err = maybeDo(n.Len, err, do) - err = maybeDo(n.Elem, err, do) - return err -} -func (n *ArrayType) editChildren(edit func(Node) Node) { - n.Len = maybeEdit(n.Len, edit) - n.Elem = maybeEdit(n.Elem, edit) -} - func (n *ArrayType) SetOTYPE(t *types.Type) { n.setOTYPE(t, n) n.Len = nil @@ -429,14 +324,6 @@ func newTypeNode(pos src.XPos, typ *types.Type) *typeNode { return n } -func (n *typeNode) String() string { return fmt.Sprint(n) } -func (n *typeNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *typeNode) copy() Node { c := *n; return &c } -func (n *typeNode) doChildren(do func(Node) error) error { - return nil -} -func (n *typeNode) editChildren(edit func(Node) Node) {} - func (n *typeNode) Type() *types.Type { return n.typ } func (n *typeNode) Sym() *types.Sym { return n.typ.Sym() } func (n *typeNode) CanBeNtype() {} From dcc640e8391d6d022b595a3b53124bbcbd985c76 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 4 Dec 2020 12:40:39 -0500 Subject: [PATCH 164/212] [dev.regabi] test: add exhaustive test of evaluated but not used Change-Id: I49db03c88b7595f1ea593df568244ad6aad3b024 Reviewed-on: https://go-review.googlesource.com/c/go/+/275443 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- test/used.go | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 test/used.go diff --git a/test/used.go b/test/used.go new file mode 100644 index 0000000000..adf2bfcb95 --- /dev/null +++ b/test/used.go @@ -0,0 +1,142 @@ +// errorcheck + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +const C = 1 + +var x1, x int +var b bool +var s string +var c chan int +var cp complex128 +var slice []int +var array [2]int +var bytes []byte +var runes []rune +var r rune + +func f0() {} +func f1() int { return 1 } +func f2() (int, int) { return 1, 1 } + +type T struct{ X int } + +func (T) M1() int { return 1 } +func (T) M0() {} +func (T) M() {} + +var t T +var tp *T + +type I interface{ M() } + +var i I + +var m map[int]int + +func _() { + // Note: if the next line changes to x, the error silences the x+x etc below! + x1 // ERROR "x1 evaluated but not used" + + nil // ERROR "nil evaluated but not used" + C // ERROR "C evaluated but not used" + 1 // ERROR "1 evaluated but not used" + x + x // ERROR "x \+ x evaluated but not used" + x - x // ERROR "x - x evaluated but not used" + x | x // ERROR "x \| x evaluated but not used" + "a" + s // ERROR ".a. \+ s evaluated but not used" + &x // ERROR "&x evaluated but not used" + b && b // ERROR "b && b evaluated but not used" + append(slice, 1) // ERROR "append\(slice, 1\) evaluated but not used" + string(bytes) // ERROR "string\(bytes\) evaluated but not used" + string(runes) // ERROR "string\(runes\) evaluated but not used" + f0() // ok + f1() // ok + f2() // ok + _ = f0() // ERROR "f0\(\) used as value" + _ = f1() // ok + _, _ = f2() // ok + _ = f2() // ERROR "assignment mismatch: 1 variable but f2 returns 2 values" + T.M0 // ERROR "T.M0 evaluated but not used" + t.M0 // ERROR "t.M0 evaluated but not used" + cap // ERROR "use of builtin cap not in function call" + cap(slice) // ERROR "cap\(slice\) evaluated but not used" + close(c) // ok + _ = close(c) // ERROR "close\(c\) used as value" + func() {} // ERROR "func literal evaluated but not used" + X{} // ERROR "undefined: X" + map[string]int{} // ERROR "map\[string\]int{} evaluated but not used" + struct{}{} // ERROR "struct ?{}{} evaluated but not used" + [1]int{} // ERROR "\[1\]int{} evaluated but not used" + []int{} // ERROR "\[\]int{} evaluated but not used" + &struct{}{} // ERROR "&struct ?{}{} evaluated but not used" + float32(x) // ERROR "float32\(x\) evaluated but not used" + I(t) // ERROR "I\(t\) evaluated but not used" + int(x) // ERROR "int\(x\) evaluated but not used" + copy(slice, slice) // ok + _ = copy(slice, slice) // ok + delete(m, 1) // ok + _ = delete(m, 1) // ERROR "delete\(m, 1\) used as value" + t.X // ERROR "t.X evaluated but not used" + tp.X // ERROR "tp.X evaluated but not used" + t.M // ERROR "t.M evaluated but not used" + I.M // ERROR "I.M evaluated but not used" + i.(T) // ERROR "i.\(T\) evaluated but not used" + x == x // ERROR "x == x evaluated but not used" + x != x // ERROR "x != x evaluated but not used" + x != x // ERROR "x != x evaluated but not used" + x < x // ERROR "x < x evaluated but not used" + x >= x // ERROR "x >= x evaluated but not used" + x > x // ERROR "x > x evaluated but not used" + *tp // ERROR "\*tp evaluated but not used" + slice[0] // ERROR "slice\[0\] evaluated but not used" + m[1] // ERROR "m\[1\] evaluated but not used" + len(slice) // ERROR "len\(slice\) evaluated but not used" + make(chan int) // ERROR "make\(chan int\) evaluated but not used" + make(map[int]int) // ERROR "make\(map\[int\]int\) evaluated but not used" + make([]int, 1) // ERROR "make\(\[\]int, 1\) evaluated but not used" + x * x // ERROR "x \* x evaluated but not used" + x / x // ERROR "x / x evaluated but not used" + x % x // ERROR "x % x evaluated but not used" + x << x // ERROR "x << x evaluated but not used" + x >> x // ERROR "x >> x evaluated but not used" + x & x // ERROR "x & x evaluated but not used" + x &^ x // ERROR "x &\^ x evaluated but not used" + new(int) // ERROR "new\(int\) evaluated but not used" + !b // ERROR "!b evaluated but not used" + ^x // ERROR "\^x evaluated but not used" + +x // ERROR "\+x evaluated but not used" + -x // ERROR "-x evaluated but not used" + b || b // ERROR "b \|\| b evaluated but not used" + panic(1) // ok + _ = panic(1) // ERROR "panic\(1\) used as value" + print(1) // ok + _ = print(1) // ERROR "print\(1\) used as value" + println(1) // ok + _ = println(1) // ERROR "println\(1\) used as value" + (x) // ERROR "x evaluated but not used" + c <- 1 // ok + slice[1:1] // ERROR "slice\[1:1\] evaluated but not used" + array[1:1] // ERROR "array\[1:1\] evaluated but not used" + s[1:1] // ERROR "s\[1:1\] evaluated but not used" + slice[1:1:1] // ERROR "slice\[1:1:1\] evaluated but not used" + array[1:1:1] // ERROR "array\[1:1:1\] evaluated but not used" + recover() // ok + <-c // ok + string(r) // ERROR "string\(r\) evaluated but not used" + iota // ERROR "undefined: iota" + real(cp) // ERROR "real\(cp\) evaluated but not used" + imag(cp) // ERROR "imag\(cp\) evaluated but not used" + complex(1, 2) // ERROR "complex\(1, 2\) evaluated but not used" + unsafe.Alignof(t.X) // ERROR "unsafe.Alignof\(t.X\) evaluated but not used" + unsafe.Offsetof(t.X) // ERROR "unsafe.Offsetof\(t.X\) evaluated but not used" + unsafe.Sizeof(t) // ERROR "unsafe.Sizeof\(t\) evaluated but not used" + _ = new(x) // ERROR "x is not a type" + _ = int // ERROR "type int is not an expression" +} From ef5964dd6b092f7e0d9bd4332a5d258eb80ecef8 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 4 Dec 2020 11:37:54 -0500 Subject: [PATCH 165/212] [dev.regabi] cmd/compile: arrange for typecheck1 to end in switch Ending typecheck1 in the switch makes it safe for each case to do an appropriate type assertion. The main change is dropping the computation of "ok" and using the syntax nodes themselves to decide what's OK. Passes buildall w/ toolstash -cmp. Change-Id: I2a1873a51e3f1194d74bb87a6653cb9857a02a1b Reviewed-on: https://go-review.googlesource.com/c/go/+/275444 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/typecheck.go | 336 +++++++++++------------ src/cmd/compile/internal/ir/expr.go | 12 +- src/cmd/compile/internal/ir/func.go | 2 + src/cmd/compile/internal/ir/name.go | 2 + src/cmd/compile/internal/ir/stmt.go | 11 + test/used.go | 7 +- 6 files changed, 195 insertions(+), 175 deletions(-) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index c22786f148..dc9e23069e 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -307,17 +307,91 @@ func typecheck(n ir.Node, top int) (res ir.Node) { return n } - n.SetTypecheck(2) - typecheck_tcstack = append(typecheck_tcstack, n) - n = typecheck1(n, top) + n.SetTypecheck(2) + n = typecheck1(n, top) n.SetTypecheck(1) last := len(typecheck_tcstack) - 1 typecheck_tcstack[last] = nil typecheck_tcstack = typecheck_tcstack[:last] + _, isExpr := n.(ir.Expr) + _, isStmt := n.(ir.Stmt) + isMulti := false + switch n.Op() { + case ir.OCALLFUNC, ir.OCALLINTER, ir.OCALLMETH: + if t := n.Left().Type(); t != nil && t.Kind() == types.TFUNC { + nr := t.NumResults() + isMulti = nr > 1 + if nr == 0 { + isExpr = false + } + } + case ir.OAPPEND: + // Must be used (and not BinaryExpr/UnaryExpr). + isStmt = false + case ir.OCLOSE, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.OVARKILL, ir.OVARLIVE: + // Must not be used. + isExpr = false + isStmt = true + case ir.OCOPY, ir.ORECOVER, ir.ORECV: + // Can be used or not. + isStmt = true + } + + t := n.Type() + if t != nil && !t.IsFuncArgStruct() && n.Op() != ir.OTYPE { + switch t.Kind() { + case types.TFUNC, // might have TANY; wait until it's called + types.TANY, types.TFORW, types.TIDEAL, types.TNIL, types.TBLANK: + break + + default: + checkwidth(t) + } + } + if t != nil { + n = evalConst(n) + t = n.Type() + } + + // TODO(rsc): Lots of the complexity here is because typecheck can + // see OTYPE, ONAME, and OLITERAL nodes multiple times. + // Once we make the IR a proper tree, we should be able to simplify + // this code a bit, especially the final case. + switch { + case top&(ctxStmt|ctxExpr) == ctxExpr && !isExpr && n.Op() != ir.OTYPE && !isMulti: + if !n.Diag() { + base.Errorf("%v used as value", n) + n.SetDiag(true) + } + if t != nil { + n.SetType(nil) + } + + case top&ctxType == 0 && n.Op() == ir.OTYPE && t != nil: + if !n.Type().Broke() { + base.Errorf("type %v is not an expression", n.Type()) + } + n.SetType(nil) + + case top&(ctxStmt|ctxExpr) == ctxStmt && !isStmt && t != nil: + if !n.Diag() { + base.Errorf("%v evaluated but not used", n) + n.SetDiag(true) + } + n.SetType(nil) + + case top&(ctxType|ctxExpr) == ctxType && n.Op() != ir.OTYPE && n.Op() != ir.ONONAME && (t != nil || n.Op() == ir.ONAME): + base.Errorf("%v is not a type", n) + if t != nil { + n.SetType(nil) + } + + } + base.Pos = lno return n } @@ -335,8 +409,7 @@ func indexlit(n ir.Node) ir.Node { return n } -// The result of typecheck1 MUST be assigned back to n, e.g. -// n.Left = typecheck1(n.Left, top) +// typecheck1 should ONLY be called from typecheck. func typecheck1(n ir.Node, top int) (res ir.Node) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheck1", n)(&res) @@ -345,7 +418,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { switch n.Op() { case ir.OLITERAL, ir.ONAME, ir.ONONAME, ir.OTYPE: if n.Sym() == nil { - break + return n } if n.Op() == ir.ONAME && n.SubOp() != 0 && top&ctxCallee == 0 { @@ -361,34 +434,29 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } } - ok := 0 switch n.Op() { - // until typecheck is complete, do nothing. default: ir.Dump("typecheck", n) - base.Fatalf("typecheck %v", n.Op()) + panic("unreachable") // names case ir.OLITERAL: - ok |= ctxExpr - if n.Type() == nil && n.Val().Kind() == constant.String { base.Fatalf("string literal missing type") } + return n case ir.ONIL, ir.ONONAME: - ok |= ctxExpr + return n case ir.ONAME: if n.Name().Decldepth == 0 { n.Name().Decldepth = decldepth } if n.SubOp() != 0 { - ok |= ctxCallee - break + return n } - if top&ctxAssign == 0 { // not a write to the variable if ir.IsBlank(n) { @@ -396,11 +464,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } - n.Name().SetUsed(true) } - - ok |= ctxExpr + return n case ir.OPACK: base.Errorf("use of package %v without selector", n.Sym()) @@ -409,14 +475,12 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // types (ODEREF is with exprs) case ir.OTYPE: - ok |= ctxType - if n.Type() == nil { return n } + return n case ir.OTSLICE: - ok |= ctxType n := n.(*ir.SliceType) n.Elem = typecheck(n.Elem, ctxType) if n.Elem.Type() == nil { @@ -425,9 +489,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { t := types.NewSlice(n.Elem.Type()) n.SetOTYPE(t) checkwidth(t) + return n case ir.OTARRAY: - ok |= ctxType n := n.(*ir.ArrayType) n.Elem = typecheck(n.Elem, ctxType) if n.Elem.Type() == nil { @@ -469,9 +533,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { t := types.NewArray(n.Elem.Type(), bound) n.SetOTYPE(t) checkwidth(t) + return n case ir.OTMAP: - ok |= ctxType n := n.(*ir.MapType) n.Key = typecheck(n.Key, ctxType) n.Elem = typecheck(n.Elem, ctxType) @@ -488,9 +552,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } n.SetOTYPE(types.NewMap(l.Type(), r.Type())) mapqueue = append(mapqueue, n) // check map keys when all types are settled + return n case ir.OTCHAN: - ok |= ctxType n := n.(*ir.ChanType) n.Elem = typecheck(n.Elem, ctxType) l := n.Elem @@ -501,21 +565,22 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { base.Errorf("chan of incomplete (or unallocatable) type not allowed") } n.SetOTYPE(types.NewChan(l.Type(), n.Dir)) + return n case ir.OTSTRUCT: - ok |= ctxType n := n.(*ir.StructType) n.SetOTYPE(tostruct(n.Fields)) + return n case ir.OTINTER: - ok |= ctxType n := n.(*ir.InterfaceType) n.SetOTYPE(tointerface(n.Methods)) + return n case ir.OTFUNC: - ok |= ctxType n := n.(*ir.FuncType) n.SetOTYPE(functype(n.Recv, n.Params, n.Results)) + return n // type or expr case ir.ODEREF: @@ -528,11 +593,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n } if l.Op() == ir.OTYPE { - ok |= ctxType n.SetOTYPE(types.NewPtr(l.Type())) // Ensure l.Type gets dowidth'd for the backend. Issue 20174. checkwidth(l.Type()) - break + return n } if !t.IsPtr() { @@ -541,12 +605,12 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } - - break + base.Errorf("%v is not a type", l) + return n } - ok |= ctxExpr n.SetType(t.Elem()) + return n // arithmetic exprs case ir.OASOP, @@ -573,7 +637,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { var op ir.Op var r ir.Node if n.Op() == ir.OASOP { - ok |= ctxStmt n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetRight(typecheck(n.Right(), ctxExpr)) l = n.Left() @@ -591,7 +654,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // TODO(marvin): Fix Node.EType type union. op = n.SubOp() } else { - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetRight(typecheck(n.Right(), ctxExpr)) l = n.Left() @@ -629,8 +691,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { if (l.Type() == types.UntypedFloat || l.Type() == types.UntypedComplex) && r.Op() == ir.OLITERAL { n.SetType(types.UntypedInt) } - - break + return n } // For "x == x && len(s)", it's better to report that "len(s)" (type int) @@ -815,9 +876,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } n.SetType(t) + return n case ir.OBITNOT, ir.ONEG, ir.ONOT, ir.OPLUS: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) l := n.Left() t := l.Type() @@ -832,11 +893,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } n.SetType(t) + return n // exprs case ir.OADDR: - ok |= ctxExpr - n.SetLeft(typecheck(n.Left(), ctxExpr)) if n.Left().Type() == nil { n.SetType(nil) @@ -871,13 +931,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } n.SetType(types.NewPtr(n.Left().Type())) + return n case ir.OCOMPLIT: - ok |= ctxExpr - n = typecheckcomplit(n) - if n.Type() == nil { - return n - } + return typecheckcomplit(n) case ir.OXDOT, ir.ODOT: if n.Op() == ir.OXDOT { @@ -903,12 +960,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { s := n.Sym() if n.Left().Op() == ir.OTYPE { - n = typecheckMethodExpr(n) - if n.Type() == nil { - return n - } - ok = ctxExpr - break + return typecheckMethodExpr(n) } if t.IsPtr() && !t.Elem().IsInterface() { @@ -952,21 +1004,12 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n } - switch n.Op() { - case ir.ODOTINTER, ir.ODOTMETH: - if top&ctxCallee != 0 { - ok |= ctxCallee - } else { - n = typecheckpartialcall(n, s) - ok |= ctxExpr - } - - default: - ok |= ctxExpr + if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && top&ctxCallee == 0 { + n = typecheckpartialcall(n, s) } + return n case ir.ODOTTYPE: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) l := n.Left() @@ -1009,9 +1052,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n } } + return n case ir.OINDEX: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) n.SetLeft(implicitstar(n.Left())) @@ -1045,7 +1088,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { if n.Right().Type() != nil && !n.Right().Type().IsInteger() { base.Errorf("non-integer %s index %v", why, n.Right()) - break + return n } if !n.Bounded() && ir.IsConst(n.Right(), constant.Int) { @@ -1067,9 +1110,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetOp(ir.OINDEXMAP) n.SetIndexMapLValue(false) } + return n case ir.ORECV: - ok |= ctxStmt | ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) l := n.Left() @@ -1091,9 +1134,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } n.SetType(t.Elem()) + return n case ir.OSEND: - ok |= ctxStmt n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetRight(typecheck(n.Right(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) @@ -1115,14 +1158,13 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { if n.Right().Type() == nil { return n } + return n case ir.OSLICEHEADER: // Errors here are Fatalf instead of Errorf because only the compiler // can construct an OSLICEHEADER node. // Components used in OSLICEHEADER that are supplied by parsed source code // have already been typechecked in e.g. OMAKESLICE earlier. - ok |= ctxExpr - t := n.Type() if t == nil { base.Fatalf("no type specified for OSLICEHEADER") @@ -1160,14 +1202,13 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.List().SetFirst(l) n.List().SetSecond(c) + return n case ir.OMAKESLICECOPY: // Errors here are Fatalf instead of Errorf because only the compiler // can construct an OMAKESLICECOPY node. // Components used in OMAKESCLICECOPY that are supplied by parsed source code // have already been typechecked in OMAKE and OCOPY earlier. - ok |= ctxExpr - t := n.Type() if t == nil { @@ -1203,9 +1244,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { base.Fatalf("len for OMAKESLICECOPY must be non-negative") } } + return n case ir.OSLICE, ir.OSLICE3: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) low, high, max := n.SliceBounds() hasmax := n.Op().IsSlice3() @@ -1277,6 +1318,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } + return n // call and call like case ir.OCALL: @@ -1306,6 +1348,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: n.SetOp(l.SubOp()) n.SetLeft(nil) + n.SetTypecheck(0) // re-typechecking new op is OK, not a loop case ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL: typecheckargs(n) @@ -1331,8 +1374,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n = ir.NodAt(n.Pos(), l.SubOp(), arg1, arg2) n = initExpr(old.Init().Slice(), n) // typecheckargs can add to old.Init } - n = typecheck1(n, top) - return n + return typecheck(n, top) } n.SetLeft(defaultlit(n.Left(), nil)) @@ -1346,8 +1388,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } // pick off before type-checking arguments - ok |= ctxExpr - arg, ok := needOneArg(n, "conversion to %v", l.Type()) if !ok { n.SetType(nil) @@ -1356,8 +1396,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n = ir.NodAt(n.Pos(), ir.OCONV, arg, nil) n.SetType(l.Type()) - n = typecheck1(n, top) - return n + return typecheck1(n, top) } typecheckargs(n) @@ -1403,11 +1442,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } typecheckaste(ir.OCALL, n.Left(), n.IsDDD(), t.Params(), n.List(), func() string { return fmt.Sprintf("argument to %v", n.Left()) }) - ok |= ctxStmt if t.NumResults() == 0 { - break + return n } - ok |= ctxExpr if t.NumResults() == 1 { n.SetType(l.Type().Results().Field(0).Type) @@ -1420,24 +1457,23 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // and we want to avoid the temporaries, so we do the rewrite earlier than is typical. n.SetOp(ir.OGETG) } - - break + return n } // multiple return if top&(ctxMultiOK|ctxStmt) == 0 { base.Errorf("multiple-value %v() in single-value context", l) - break + return n } n.SetType(l.Type().Results()) + return n case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: - ok |= ctxExpr n.SetType(types.Types[types.TUINTPTR]) + return n case ir.OCAP, ir.OLEN: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) n.SetLeft(implicitstar(n.Left())) @@ -1461,9 +1497,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } n.SetType(types.Types[types.TINT]) + return n case ir.OREAL, ir.OIMAG: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) l := n.Left() t := l.Type() @@ -1485,9 +1521,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } + return n case ir.OCOMPLEX: - ok |= ctxExpr l := typecheck(n.Left(), ctxExpr) r := typecheck(n.Right(), ctxExpr) if l.Type() == nil || r.Type() == nil { @@ -1525,6 +1561,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { t = types.Types[types.TCOMPLEX128] } n.SetType(t) + return n case ir.OCLOSE: n.SetLeft(typecheck(n.Left(), ctxExpr)) @@ -1546,11 +1583,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } - - ok |= ctxStmt + return n case ir.ODELETE: - ok |= ctxStmt typecheckargs(n) args := n.List() if args.Len() == 0 { @@ -1580,9 +1615,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } args.SetSecond(assignconv(r, l.Type().Key(), "delete")) + return n case ir.OAPPEND: - ok |= ctxExpr typecheckargs(n) args := n.List() if args.Len() == 0 { @@ -1625,11 +1660,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { if t.Elem().IsKind(types.TUINT8) && args.Second().Type().IsString() { args.SetSecond(defaultlit(args.Second(), types.Types[types.TSTRING])) - break + return n } args.SetSecond(assignconv(args.Second(), t.Underlying(), "append")) - break + return n } as := args.Slice()[1:] @@ -1640,9 +1675,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { as[i] = assignconv(n, t.Elem(), "append") checkwidth(as[i].Type()) // ensure width is calculated for backend } + return n case ir.OCOPY: - ok |= ctxStmt | ctxExpr n.SetType(types.Types[types.TINT]) n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) @@ -1656,7 +1691,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // copy([]byte, string) if n.Left().Type().IsSlice() && n.Right().Type().IsString() { if types.Identical(n.Left().Type().Elem(), types.ByteType) { - break + return n } base.Errorf("arguments to copy have different element types: %L and string", n.Left().Type()) n.SetType(nil) @@ -1680,9 +1715,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { n.SetType(nil) return n } + return n case ir.OCONV: - ok |= ctxExpr checkwidth(n.Type()) // ensure width is calculated for backend n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(convlit1(n.Left(), n.Type(), true, nil)) @@ -1717,16 +1752,16 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // do not convert to []byte literal. See CL 125796. // generated code and compiler memory footprint is better without it. case ir.OSTR2BYTES: - break + // ok case ir.OSTR2RUNES: if n.Left().Op() == ir.OLITERAL { n = stringtoruneslit(n) } } + return n case ir.OMAKE: - ok |= ctxExpr args := n.List().Slice() if len(args) == 0 { base.Errorf("missing argument to make") @@ -1832,9 +1867,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { nn.SetType(t) n = nn + return n case ir.ONEW: - ok |= ctxExpr if n.Left() == nil { // Fatalf because the OCALL above checked for us, // so this must be an internally-generated mistake. @@ -1849,9 +1884,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } n.SetLeft(l) n.SetType(types.NewPtr(t)) + return n case ir.OPRINT, ir.OPRINTN: - ok |= ctxStmt typecheckargs(n) ls := n.List().Slice() for i1, n1 := range ls { @@ -1862,18 +1897,18 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { ls[i1] = defaultlit(ls[i1], nil) } } + return n case ir.OPANIC: - ok |= ctxStmt n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), types.Types[types.TINTER])) if n.Left().Type() == nil { n.SetType(nil) return n } + return n case ir.ORECOVER: - ok |= ctxExpr | ctxStmt if n.List().Len() != 0 { base.Errorf("too many arguments to recover") n.SetType(nil) @@ -1881,16 +1916,16 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } n.SetType(types.Types[types.TINTER]) + return n case ir.OCLOSURE: - ok |= ctxExpr typecheckclosure(n, top) if n.Type() == nil { return n } + return n case ir.OITAB: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) t := n.Left().Type() if t == nil { @@ -1901,14 +1936,15 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { base.Fatalf("OITAB of %v", t) } n.SetType(types.NewPtr(types.Types[types.TUINTPTR])) + return n case ir.OIDATA: // Whoever creates the OIDATA node must know a priori the concrete type at that moment, // usually by just having checked the OITAB. base.Fatalf("cannot typecheck interface data %v", n) + panic("unreachable") case ir.OSPTR: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) t := n.Left().Type() if t == nil { @@ -1923,33 +1959,33 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } else { n.SetType(types.NewPtr(t.Elem())) } + return n case ir.OCLOSUREREAD: - ok |= ctxExpr + return n case ir.OCFUNC: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetType(types.Types[types.TUINTPTR]) + return n case ir.OCONVNOP: - ok |= ctxExpr n.SetLeft(typecheck(n.Left(), ctxExpr)) + return n // statements case ir.OAS: - ok |= ctxStmt - typecheckas(n) // Code that creates temps does not bother to set defn, so do it here. if n.Left().Op() == ir.ONAME && ir.IsAutoTmp(n.Left()) { n.Left().Name().Defn = n } + return n case ir.OAS2: - ok |= ctxStmt typecheckas2(n) + return n case ir.OBREAK, ir.OCONTINUE, @@ -1958,14 +1994,13 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { ir.OFALL, ir.OVARKILL, ir.OVARLIVE: - ok |= ctxStmt + return n case ir.OBLOCK: - ok |= ctxStmt typecheckslice(n.List().Slice(), ctxStmt) + return n case ir.OLABEL: - ok |= ctxStmt decldepth++ if n.Sym().IsBlank() { // Empty identifier is valid but useless. @@ -1973,21 +2008,21 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { // See issues 7538, 11589, 11593. n = ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil) } + return n case ir.ODEFER: - ok |= ctxStmt n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr)) if !n.Left().Diag() { checkdefergo(n) } + return n case ir.OGO: - ok |= ctxStmt n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr)) checkdefergo(n) + return n case ir.OFOR, ir.OFORUNTIL: - ok |= ctxStmt typecheckslice(n.Init().Slice(), ctxStmt) decldepth++ n.SetLeft(typecheck(n.Left(), ctxExpr)) @@ -2004,9 +2039,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } typecheckslice(n.Body().Slice(), ctxStmt) decldepth-- + return n case ir.OIF: - ok |= ctxStmt typecheckslice(n.Init().Slice(), ctxStmt) n.SetLeft(typecheck(n.Left(), ctxExpr)) n.SetLeft(defaultlit(n.Left(), nil)) @@ -2018,9 +2053,9 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } typecheckslice(n.Body().Slice(), ctxStmt) typecheckslice(n.Rlist().Slice(), ctxStmt) + return n case ir.ORETURN: - ok |= ctxStmt typecheckargs(n) if Curfn == nil { base.Errorf("return outside function") @@ -2029,24 +2064,25 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } if hasNamedResults(Curfn) && n.List().Len() == 0 { - break + return n } typecheckaste(ir.ORETURN, nil, false, Curfn.Type().Results(), n.List(), func() string { return "return argument" }) + return n case ir.ORETJMP: - ok |= ctxStmt + return n case ir.OSELECT: - ok |= ctxStmt typecheckselect(n) + return n case ir.OSWITCH: - ok |= ctxStmt typecheckswitch(n) + return n case ir.ORANGE: - ok |= ctxStmt typecheckrange(n) + return n case ir.OTYPESW: base.Errorf("use of .(type) outside type switch") @@ -2054,64 +2090,22 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { return n case ir.ODCLFUNC: - ok |= ctxStmt typecheckfunc(n.(*ir.Func)) + return n case ir.ODCLCONST: - ok |= ctxStmt n.SetLeft(typecheck(n.Left(), ctxExpr)) + return n case ir.ODCLTYPE: - ok |= ctxStmt n.SetLeft(typecheck(n.Left(), ctxType)) checkwidth(n.Left().Type()) - } - - t := n.Type() - if t != nil && !t.IsFuncArgStruct() && n.Op() != ir.OTYPE { - switch t.Kind() { - case types.TFUNC, // might have TANY; wait until it's called - types.TANY, types.TFORW, types.TIDEAL, types.TNIL, types.TBLANK: - break - - default: - checkwidth(t) - } - } - - n = evalConst(n) - if n.Op() == ir.OTYPE && top&ctxType == 0 { - if !n.Type().Broke() { - base.Errorf("type %v is not an expression", n.Type()) - } - n.SetType(nil) return n } - if top&(ctxExpr|ctxType) == ctxType && n.Op() != ir.OTYPE { - base.Errorf("%v is not a type", n) - n.SetType(nil) - return n - } - - // TODO(rsc): simplify - if (top&(ctxCallee|ctxExpr|ctxType) != 0) && top&ctxStmt == 0 && ok&(ctxExpr|ctxType|ctxCallee) == 0 { - base.Errorf("%v used as value", n) - n.SetType(nil) - return n - } - - if (top&ctxStmt != 0) && top&(ctxCallee|ctxExpr|ctxType) == 0 && ok&ctxStmt == 0 { - if !n.Diag() { - base.Errorf("%v evaluated but not used", n) - n.SetDiag(true) - } - - n.SetType(nil) - return n - } - - return n + // No return n here! + // Individual cases can type-assert n, introducing a new one. + // Each must execute its own return n. } func typecheckargs(n ir.Node) { diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 7b1aeedcdf..7165a06b25 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -32,7 +32,13 @@ func maybeEdit(x Node, edit func(Node) Node) Node { return edit(x) } -// A miniStmt is a miniNode with extra fields common to expressions. +// An Expr is a Node that can appear as an expression. +type Expr interface { + Node + isExpr() +} + +// A miniExpr is a miniNode with extra fields common to expressions. // TODO(rsc): Once we are sure about the contents, compact the bools // into a bit field and leave extra bits available for implementations // embedding miniExpr. Right now there are ~60 unused bits sitting here. @@ -52,6 +58,8 @@ const ( miniExprBounded ) +func (*miniExpr) isExpr() {} + func (n *miniExpr) Type() *types.Type { return n.typ } func (n *miniExpr) SetType(x *types.Type) { n.typ = x } func (n *miniExpr) Opt() interface{} { return n.opt } @@ -192,6 +200,8 @@ func NewCallExpr(pos src.XPos, fun Node, args []Node) *CallExpr { return n } +func (*CallExpr) isStmt() {} + func (n *CallExpr) Orig() Node { return n.orig } func (n *CallExpr) SetOrig(x Node) { n.orig = x } func (n *CallExpr) Left() Node { return n.X } diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 38e00da7da..3bca25b504 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -114,6 +114,8 @@ func NewFunc(pos src.XPos) *Func { return f } +func (f *Func) isStmt() {} + func (f *Func) Func() *Func { return f } func (f *Func) Body() Nodes { return f.body } func (f *Func) PtrBody() *Nodes { return &f.body } diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 06cffe0325..c527ba281d 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -121,6 +121,8 @@ type Name struct { Outer *Name } +func (n *Name) isExpr() {} + // NewNameAt returns a new ONAME Node associated with symbol s at position pos. // The caller is responsible for setting Curfn. func NewNameAt(pos src.XPos, sym *types.Sym) *Name { diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 19f90ce1fa..836bbcb453 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -27,15 +27,26 @@ func NewDecl(pos src.XPos, op Op, x Node) *Decl { return n } +func (*Decl) isStmt() {} + func (n *Decl) Left() Node { return n.X } func (n *Decl) SetLeft(x Node) { n.X = x } +// A Stmt is a Node that can appear as a statement. +// This includes statement-like expressions such as <-c and f(). +type Stmt interface { + Node + isStmt() +} + // A miniStmt is a miniNode with extra fields common to statements. type miniStmt struct { miniNode init Nodes } +func (*miniStmt) isStmt() {} + func (n *miniStmt) Init() Nodes { return n.init } func (n *miniStmt) SetInit(x Nodes) { n.init = x } func (n *miniStmt) PtrInit() *Nodes { return &n.init } diff --git a/test/used.go b/test/used.go index adf2bfcb95..5c7aad24a6 100644 --- a/test/used.go +++ b/test/used.go @@ -10,7 +10,7 @@ import "unsafe" const C = 1 -var x1, x int +var x, x1, x2 int var b bool var s string var c chan int @@ -120,7 +120,6 @@ func _() { _ = print(1) // ERROR "print\(1\) used as value" println(1) // ok _ = println(1) // ERROR "println\(1\) used as value" - (x) // ERROR "x evaluated but not used" c <- 1 // ok slice[1:1] // ERROR "slice\[1:1\] evaluated but not used" array[1:1] // ERROR "array\[1:1\] evaluated but not used" @@ -137,6 +136,8 @@ func _() { unsafe.Alignof(t.X) // ERROR "unsafe.Alignof\(t.X\) evaluated but not used" unsafe.Offsetof(t.X) // ERROR "unsafe.Offsetof\(t.X\) evaluated but not used" unsafe.Sizeof(t) // ERROR "unsafe.Sizeof\(t\) evaluated but not used" - _ = new(x) // ERROR "x is not a type" _ = int // ERROR "type int is not an expression" + (x) // ERROR "x evaluated but not used" + _ = new(x2) // ERROR "x2 is not a type" + _ = new(1 + 1) // ERROR "1 \+ 1 is not a type" } From a79742f39a906a52fce4873895599298c0699743 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 4 Dec 2020 18:40:24 -0500 Subject: [PATCH 166/212] [dev.regabi] cmd/compile: remove "short" node header mode This is unreachable code - the only way short can be true is if verb == 'S', but jconv is only called when verb == 'j'. Simplify by removing. Passes buildall w/ toolstash -cmp. Change-Id: I27bd38319f72215069e940b320b5c82608e2651a Reviewed-on: https://go-review.googlesource.com/c/go/+/275772 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/escape.go | 6 ++---- src/cmd/compile/internal/ir/fmt.go | 18 ++++++++---------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 32bc7b297b..a7458ab733 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -148,7 +148,7 @@ func init() { } // escFmt is called from node printing to print information about escape analysis results. -func escFmt(n ir.Node, short bool) string { +func escFmt(n ir.Node) string { text := "" switch n.Esc() { case EscUnknown: @@ -161,9 +161,7 @@ func escFmt(n ir.Node, short bool) string { text = "esc(no)" case EscNever: - if !short { - text = "esc(N)" - } + text = "esc(N)" default: text = fmt.Sprintf("esc(%d)", n.Esc()) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index bc5536241e..593e77880d 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -339,21 +339,19 @@ func nodeFormat(n Node, s fmt.State, verb rune, mode FmtMode) { } // EscFmt is set by the escape analysis code to add escape analysis details to the node print. -var EscFmt func(n Node, short bool) string +var EscFmt func(n Node) string // *Node details func jconvFmt(n Node, s fmt.State, flag FmtFlag) { - short := flag&FmtShort != 0 - // Useful to see which nodes in an AST printout are actually identical if base.Debug.DumpPtrs != 0 { fmt.Fprintf(s, " p(%p)", n) } - if !short && n.Name() != nil && n.Name().Vargen != 0 { + if n.Name() != nil && n.Name().Vargen != 0 { fmt.Fprintf(s, " g(%d)", n.Name().Vargen) } - if base.Debug.DumpPtrs != 0 && !short && n.Name() != nil && n.Name().Defn != nil { + if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Defn != nil { // Useful to see where Defn is set and what node it points to fmt.Fprintf(s, " defn(%p)", n.Name().Defn) } @@ -369,7 +367,7 @@ func jconvFmt(n Node, s fmt.State, flag FmtFlag) { fmt.Fprintf(s, " l(%s%d)", pfx, n.Pos().Line()) } - if !short && n.Offset() != types.BADWIDTH { + if n.Offset() != types.BADWIDTH { fmt.Fprintf(s, " x(%d)", n.Offset()) } @@ -382,12 +380,12 @@ func jconvFmt(n Node, s fmt.State, flag FmtFlag) { } if EscFmt != nil { - if esc := EscFmt(n, short); esc != "" { + if esc := EscFmt(n); esc != "" { fmt.Fprintf(s, " %s", esc) } } - if !short && n.Typecheck() != 0 { + if n.Typecheck() != 0 { fmt.Fprintf(s, " tc(%d)", n.Typecheck()) } @@ -423,11 +421,11 @@ func jconvFmt(n Node, s fmt.State, flag FmtFlag) { fmt.Fprint(s, " nonnil") } - if !short && n.HasCall() { + if n.HasCall() { fmt.Fprint(s, " hascall") } - if !short && n.Name() != nil && n.Name().Used() { + if n.Name() != nil && n.Name().Used() { fmt.Fprint(s, " used") } } From 158c9dd131db86a381535a902b54bc7f610a8c97 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 5 Dec 2020 00:02:46 -0500 Subject: [PATCH 167/212] [dev.regabi] cmd/compile: reorganize ir/fmt.go This code is a few layer of abstraction stacked up on top of each other, and they're hard to see all at the same time because the file is pretty mixed up. As much as I try to avoid code rearrangement to keep history, this one is long overdue. A followup CL will cut out some of the layers, and the diff will be much clearer what's going on with the code ordered with callers near callees, as it is now. Passes buildall w/ toolstash -cmp. Change-Id: Iffc49d43cf4be9fab47e2dd59a5f98930573350f Reviewed-on: https://go-review.googlesource.com/c/go/+/275773 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/fmt.go | 1274 +++++++++++++-------------- src/cmd/compile/internal/ir/node.go | 6 + 2 files changed, 641 insertions(+), 639 deletions(-) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 593e77880d..ae33dcddd7 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -19,6 +19,74 @@ import ( "cmd/internal/src" ) +// Format conversions: +// TODO(gri) verify these; eliminate those not used anymore +// +// %v Op Node opcodes +// Flags: #: print Go syntax (automatic unless mode == FDbg) +// +// %j *Node Node details +// Flags: 0: suppresses things not relevant until walk +// +// %v *Val Constant values +// +// %v *types.Sym Symbols +// %S unqualified identifier in any mode +// Flags: +,- #: mode (see below) +// 0: in export mode: unqualified identifier if exported, qualified if not +// +// %v *types.Type Types +// %S omit "func" and receiver in function types +// %L definition instead of name. +// Flags: +,- #: mode (see below) +// ' ' (only in -/Sym mode) print type identifiers wit package name instead of prefix. +// +// %v *Node Nodes +// %S (only in +/debug mode) suppress recursion +// %L (only in Error mode) print "foo (type Bar)" +// Flags: +,- #: mode (see below) +// +// %v Nodes Node lists +// Flags: those of *Node +// .: separate items with ',' instead of ';' + +// *types.Sym, *types.Type, and *Node types use the flags below to set the format mode + +// The mode flags '+', '-', and '#' are sticky; they persist through +// recursions of *Node, *types.Type, and *types.Sym values. The ' ' flag is +// sticky only on *types.Type recursions and only used in %-/*types.Sym mode. +// +// Example: given a *types.Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode + +// Useful format combinations: +// TODO(gri): verify these +// +// *Node, Nodes: +// %+v multiline recursive debug dump of *Node/Nodes +// %+S non-recursive debug dump +// +// *Node: +// %#v Go format +// %L "foo (type Bar)" for error messages +// +// *types.Type: +// %#v Go format +// %#L type definition instead of name +// %#S omit "func" and receiver in function signature +// +// %-v type identifiers +// %-S type identifiers without "func" and arg names in type signatures (methodsym) +// %- v type identifiers with package name instead of prefix (typesym, dcommontype, typehash) + +type FmtMode int + +const ( + FErr FmtMode = iota + FDbg + FTypeId + FTypeIdName // same as FTypeId, but use package name instead of prefix +) + // A FmtFlag value is a set of flags (or 0). // They control how the Xconv functions format their values. // See the respective function's documentation for details. @@ -66,71 +134,6 @@ func fmtFlag(s fmt.State, verb rune) FmtFlag { return flag } -// Format conversions: -// TODO(gri) verify these; eliminate those not used anymore -// -// %v Op Node opcodes -// Flags: #: print Go syntax (automatic unless mode == FDbg) -// -// %j *Node Node details -// Flags: 0: suppresses things not relevant until walk -// -// %v *Val Constant values -// -// %v *types.Sym Symbols -// %S unqualified identifier in any mode -// Flags: +,- #: mode (see below) -// 0: in export mode: unqualified identifier if exported, qualified if not -// -// %v *types.Type Types -// %S omit "func" and receiver in function types -// %L definition instead of name. -// Flags: +,- #: mode (see below) -// ' ' (only in -/Sym mode) print type identifiers wit package name instead of prefix. -// -// %v *Node Nodes -// %S (only in +/debug mode) suppress recursion -// %L (only in Error mode) print "foo (type Bar)" -// Flags: +,- #: mode (see below) -// -// %v Nodes Node lists -// Flags: those of *Node -// .: separate items with ',' instead of ';' - -// *types.Sym, *types.Type, and *Node types use the flags below to set the format mode -const ( - FErr FmtMode = iota - FDbg - FTypeId - FTypeIdName // same as FTypeId, but use package name instead of prefix -) - -// The mode flags '+', '-', and '#' are sticky; they persist through -// recursions of *Node, *types.Type, and *types.Sym values. The ' ' flag is -// sticky only on *types.Type recursions and only used in %-/*types.Sym mode. -// -// Example: given a *types.Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode - -// Useful format combinations: -// TODO(gri): verify these -// -// *Node, Nodes: -// %+v multiline recursive debug dump of *Node/Nodes -// %+S non-recursive debug dump -// -// *Node: -// %#v Go format -// %L "foo (type Bar)" for error messages -// -// *types.Type: -// %#v Go format -// %#L type definition instead of name -// %#S omit "func" and receiver in function signature -// -// %-v type identifiers -// %-S type identifiers without "func" and arg names in type signatures (methodsym) -// %- v type identifiers with package name instead of prefix (typesym, dcommontype, typehash) - // update returns the results of applying f to mode. func (f FmtFlag) update(mode FmtMode) (FmtFlag, FmtMode) { switch { @@ -148,6 +151,46 @@ func (f FmtFlag) update(mode FmtMode) (FmtFlag, FmtMode) { return f, mode } +func (m FmtMode) Fprintf(s fmt.State, format string, args ...interface{}) { + m.prepareArgs(args) + fmt.Fprintf(s, format, args...) +} + +func (m FmtMode) Sprintf(format string, args ...interface{}) string { + m.prepareArgs(args) + return fmt.Sprintf(format, args...) +} + +func (m FmtMode) Sprint(args ...interface{}) string { + m.prepareArgs(args) + return fmt.Sprint(args...) +} + +func (m FmtMode) prepareArgs(args []interface{}) { + for i, arg := range args { + switch arg := arg.(type) { + case Op: + args[i] = &fmtOp{arg, m} + case Node: + args[i] = &fmtNode{arg, m} + case nil: + args[i] = &fmtNode{nil, m} // assume this was a node interface + case *types.Type: + args[i] = &fmtType{arg, m} + case *types.Sym: + args[i] = &fmtSym{arg, m} + case Nodes: + args[i] = &fmtNodes{arg, m} + case int32, int64, string, types.Kind, constant.Value: + // OK: printing these types doesn't depend on mode + default: + base.Fatalf("mode.prepareArgs type %T", arg) + } + } +} + +// Op + var OpNames = []string{ OADDR: "&", OADD: "+", @@ -218,6 +261,15 @@ func (o Op) GoString() string { return fmt.Sprintf("%#v", o) } +type fmtOp struct { + x Op + m FmtMode +} + +func (f *fmtOp) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } + +func (o Op) Format(s fmt.State, verb rune) { o.format(s, verb, FErr) } + func (o Op) format(s fmt.State, verb rune, mode FmtMode) { switch verb { case 'v': @@ -240,195 +292,7 @@ func (o Op) oconv(s fmt.State, flag FmtFlag, mode FmtMode) { fmt.Fprint(s, o.String()) } -type FmtMode int - -type fmtNode struct { - x Node - m FmtMode -} - -func (f *fmtNode) Format(s fmt.State, verb rune) { nodeFormat(f.x, s, verb, f.m) } - -type fmtOp struct { - x Op - m FmtMode -} - -func (f *fmtOp) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } - -type fmtType struct { - x *types.Type - m FmtMode -} - -func (f *fmtType) Format(s fmt.State, verb rune) { typeFormat(f.x, s, verb, f.m) } - -type fmtSym struct { - x *types.Sym - m FmtMode -} - -func (f *fmtSym) Format(s fmt.State, verb rune) { symFormat(f.x, s, verb, f.m) } - -type fmtNodes struct { - x Nodes - m FmtMode -} - -func (f *fmtNodes) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } - -func FmtNode(n Node, s fmt.State, verb rune) { - nodeFormat(n, s, verb, FErr) -} - -func (o Op) Format(s fmt.State, verb rune) { o.format(s, verb, FErr) } - -// func (t *types.Type) Format(s fmt.State, verb rune) // in package types -// func (y *types.Sym) Format(s fmt.State, verb rune) // in package types { y.format(s, verb, FErr) } -func (n Nodes) Format(s fmt.State, verb rune) { n.format(s, verb, FErr) } - -func (m FmtMode) Fprintf(s fmt.State, format string, args ...interface{}) { - m.prepareArgs(args) - fmt.Fprintf(s, format, args...) -} - -func (m FmtMode) Sprintf(format string, args ...interface{}) string { - m.prepareArgs(args) - return fmt.Sprintf(format, args...) -} - -func (m FmtMode) Sprint(args ...interface{}) string { - m.prepareArgs(args) - return fmt.Sprint(args...) -} - -func (m FmtMode) prepareArgs(args []interface{}) { - for i, arg := range args { - switch arg := arg.(type) { - case Op: - args[i] = &fmtOp{arg, m} - case Node: - args[i] = &fmtNode{arg, m} - case nil: - args[i] = &fmtNode{nil, m} // assume this was a node interface - case *types.Type: - args[i] = &fmtType{arg, m} - case *types.Sym: - args[i] = &fmtSym{arg, m} - case Nodes: - args[i] = &fmtNodes{arg, m} - case int32, int64, string, types.Kind, constant.Value: - // OK: printing these types doesn't depend on mode - default: - base.Fatalf("mode.prepareArgs type %T", arg) - } - } -} - -func nodeFormat(n Node, s fmt.State, verb rune, mode FmtMode) { - switch verb { - case 'v', 'S', 'L': - nconvFmt(n, s, fmtFlag(s, verb), mode) - - case 'j': - jconvFmt(n, s, fmtFlag(s, verb)) - - default: - fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n) - } -} - -// EscFmt is set by the escape analysis code to add escape analysis details to the node print. -var EscFmt func(n Node) string - -// *Node details -func jconvFmt(n Node, s fmt.State, flag FmtFlag) { - // Useful to see which nodes in an AST printout are actually identical - if base.Debug.DumpPtrs != 0 { - fmt.Fprintf(s, " p(%p)", n) - } - if n.Name() != nil && n.Name().Vargen != 0 { - fmt.Fprintf(s, " g(%d)", n.Name().Vargen) - } - - if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Defn != nil { - // Useful to see where Defn is set and what node it points to - fmt.Fprintf(s, " defn(%p)", n.Name().Defn) - } - - if n.Pos().IsKnown() { - pfx := "" - switch n.Pos().IsStmt() { - case src.PosNotStmt: - pfx = "_" // "-" would be confusing - case src.PosIsStmt: - pfx = "+" - } - fmt.Fprintf(s, " l(%s%d)", pfx, n.Pos().Line()) - } - - if n.Offset() != types.BADWIDTH { - fmt.Fprintf(s, " x(%d)", n.Offset()) - } - - if n.Class() != 0 { - fmt.Fprintf(s, " class(%v)", n.Class()) - } - - if n.Colas() { - fmt.Fprintf(s, " colas(%v)", n.Colas()) - } - - if EscFmt != nil { - if esc := EscFmt(n); esc != "" { - fmt.Fprintf(s, " %s", esc) - } - } - - if n.Typecheck() != 0 { - fmt.Fprintf(s, " tc(%d)", n.Typecheck()) - } - - if n.IsDDD() { - fmt.Fprintf(s, " isddd(%v)", n.IsDDD()) - } - - if n.Implicit() { - fmt.Fprintf(s, " implicit(%v)", n.Implicit()) - } - - if n.Op() == ONAME { - if n.Name().Addrtaken() { - fmt.Fprint(s, " addrtaken") - } - if n.Name().Assigned() { - fmt.Fprint(s, " assigned") - } - if n.Name().IsClosureVar() { - fmt.Fprint(s, " closurevar") - } - if n.Name().Captured() { - fmt.Fprint(s, " captured") - } - if n.Name().IsOutputParamHeapAddr() { - fmt.Fprint(s, " outputparamheapaddr") - } - } - if n.Bounded() { - fmt.Fprint(s, " bounded") - } - if n.NonNil() { - fmt.Fprint(s, " nonnil") - } - - if n.HasCall() { - fmt.Fprint(s, " hascall") - } - - if n.Name() != nil && n.Name().Used() { - fmt.Fprint(s, " used") - } -} +// Val func FmtConst(v constant.Value, flag FmtFlag) string { if flag&FmtSharp == 0 && v.Kind() == constant.Complex { @@ -463,15 +327,72 @@ func FmtConst(v constant.Value, flag FmtFlag) string { return v.String() } -/* -s%,%,\n%g -s%\n+%\n%g -s%^[ ]*T%%g -s%,.*%%g -s%.+% [T&] = "&",%g -s%^ ........*\]%&~%g -s%~ %%g -*/ +// Sym + +// numImport tracks how often a package with a given name is imported. +// It is used to provide a better error message (by using the package +// path to disambiguate) if a package that appears multiple times with +// the same name appears in an error message. +var NumImport = make(map[string]int) + +type fmtSym struct { + x *types.Sym + m FmtMode +} + +func (f *fmtSym) Format(s fmt.State, verb rune) { symFormat(f.x, s, verb, f.m) } + +// "%S" suppresses qualifying with package +func symFormat(s *types.Sym, f fmt.State, verb rune, mode FmtMode) { + switch verb { + case 'v', 'S': + fmt.Fprint(f, sconv(s, fmtFlag(f, verb), mode)) + + default: + fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s) + } +} + +func smodeString(s *types.Sym, mode FmtMode) string { return sconv(s, 0, mode) } + +// See #16897 before changing the implementation of sconv. +func sconv(s *types.Sym, flag FmtFlag, mode FmtMode) string { + if flag&FmtLong != 0 { + panic("linksymfmt") + } + + if s == nil { + return "" + } + + if s.Name == "_" { + return "_" + } + buf := fmtBufferPool.Get().(*bytes.Buffer) + buf.Reset() + defer fmtBufferPool.Put(buf) + + flag, mode = flag.update(mode) + symfmt(buf, s, flag, mode) + return types.InternString(buf.Bytes()) +} + +func sconv2(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { + if flag&FmtLong != 0 { + panic("linksymfmt") + } + if s == nil { + b.WriteString("") + return + } + if s.Name == "_" { + b.WriteString("_") + return + } + + flag, mode = flag.update(mode) + symfmt(b, s, flag, mode) +} func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { if flag&FmtShort == 0 { @@ -534,6 +455,8 @@ func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { b.WriteString(s.Name) } +// Type + var BasicTypeNames = []string{ types.TINT: "int", types.TUINT: "uint", @@ -564,6 +487,39 @@ var fmtBufferPool = sync.Pool{ }, } +func InstallTypeFormats() { + types.Sconv = func(s *types.Sym, flag, mode int) string { + return sconv(s, FmtFlag(flag), FmtMode(mode)) + } + types.Tconv = func(t *types.Type, flag, mode int) string { + return tconv(t, FmtFlag(flag), FmtMode(mode)) + } + types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) { + symFormat(sym, s, verb, FmtMode(mode)) + } + types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) { + typeFormat(t, s, verb, FmtMode(mode)) + } +} + +type fmtType struct { + x *types.Type + m FmtMode +} + +func (f *fmtType) Format(s fmt.State, verb rune) { typeFormat(f.x, s, verb, f.m) } + +// "%L" print definition, not name +// "%S" omit 'func' and receiver from function types, short type names +func typeFormat(t *types.Type, s fmt.State, verb rune, mode FmtMode) { + switch verb { + case 'v', 'S', 'L': + fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode)) + default: + fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t) + } +} + func tconv(t *types.Type, flag FmtFlag, mode FmtMode) string { buf := fmtBufferPool.Get().(*bytes.Buffer) buf.Reset() @@ -874,13 +830,263 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited } } +func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visited map[*types.Type]int, funarg types.Funarg) { + if f == nil { + b.WriteString("") + return + } + flag, mode = flag.update(mode) + if mode == FTypeIdName { + flag |= FmtUnsigned + } + + var name string + if flag&FmtShort == 0 { + s := f.Sym + + // Take the name from the original. + if mode == FErr { + s = OrigSym(s) + } + + if s != nil && f.Embedded == 0 { + if funarg != types.FunargNone { + name = modeString(AsNode(f.Nname), mode) + } else if flag&FmtLong != 0 { + name = mode.Sprintf("%0S", s) + if !types.IsExported(name) && flag&FmtUnsigned == 0 { + name = smodeString(s, mode) // qualify non-exported names (used on structs, not on funarg) + } + } else { + name = smodeString(s, mode) + } + } + } + + if name != "" { + b.WriteString(name) + b.WriteString(" ") + } + + if f.IsDDD() { + var et *types.Type + if f.Type != nil { + et = f.Type.Elem() + } + b.WriteString("...") + tconv2(b, et, 0, mode, visited) + } else { + tconv2(b, f.Type, 0, mode, visited) + } + + if flag&FmtShort == 0 && funarg == types.FunargNone && f.Note != "" { + b.WriteString(" ") + b.WriteString(strconv.Quote(f.Note)) + } +} + +// Node + +func modeString(n Node, mode FmtMode) string { return mode.Sprint(n) } + +type fmtNode struct { + x Node + m FmtMode +} + +func (f *fmtNode) Format(s fmt.State, verb rune) { nodeFormat(f.x, s, verb, f.m) } + +func FmtNode(n Node, s fmt.State, verb rune) { + nodeFormat(n, s, verb, FErr) +} + +func nodeFormat(n Node, s fmt.State, verb rune, mode FmtMode) { + switch verb { + case 'v', 'S', 'L': + nconvFmt(n, s, fmtFlag(s, verb), mode) + + case 'j': + jconvFmt(n, s, fmtFlag(s, verb)) + + default: + fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n) + } +} + +// "%L" suffix with "(type %T)" where possible +// "%+S" in debug mode, don't recurse, no multiline output +func nconvFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { + if n == nil { + fmt.Fprint(s, "") + return + } + + flag, mode = flag.update(mode) + + switch mode { + case FErr: + nodeFmt(n, s, flag, mode) + + case FDbg: + dumpdepth++ + nodeDumpFmt(n, s, flag, mode) + dumpdepth-- + + default: + base.Fatalf("unhandled %%N mode: %d", mode) + } +} + +func nodeFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { + t := n.Type() + if flag&FmtLong != 0 && t != nil { + if t.Kind() == types.TNIL { + fmt.Fprint(s, "nil") + } else if n.Op() == ONAME && n.Name().AutoTemp() { + mode.Fprintf(s, "%v value", t) + } else { + mode.Fprintf(s, "%v (type %v)", n, t) + } + return + } + + // TODO inlining produces expressions with ninits. we can't print these yet. + + if OpPrec[n.Op()] < 0 { + stmtFmt(n, s, mode) + return + } + + exprFmt(n, s, 0, mode) +} + +var OpPrec = []int{ + OALIGNOF: 8, + OAPPEND: 8, + OBYTES2STR: 8, + OARRAYLIT: 8, + OSLICELIT: 8, + ORUNES2STR: 8, + OCALLFUNC: 8, + OCALLINTER: 8, + OCALLMETH: 8, + OCALL: 8, + OCAP: 8, + OCLOSE: 8, + OCOMPLIT: 8, + OCONVIFACE: 8, + OCONVNOP: 8, + OCONV: 8, + OCOPY: 8, + ODELETE: 8, + OGETG: 8, + OLEN: 8, + OLITERAL: 8, + OMAKESLICE: 8, + OMAKESLICECOPY: 8, + OMAKE: 8, + OMAPLIT: 8, + ONAME: 8, + ONEW: 8, + ONIL: 8, + ONONAME: 8, + OOFFSETOF: 8, + OPACK: 8, + OPANIC: 8, + OPAREN: 8, + OPRINTN: 8, + OPRINT: 8, + ORUNESTR: 8, + OSIZEOF: 8, + OSTR2BYTES: 8, + OSTR2RUNES: 8, + OSTRUCTLIT: 8, + OTARRAY: 8, + OTSLICE: 8, + OTCHAN: 8, + OTFUNC: 8, + OTINTER: 8, + OTMAP: 8, + OTSTRUCT: 8, + OINDEXMAP: 8, + OINDEX: 8, + OSLICE: 8, + OSLICESTR: 8, + OSLICEARR: 8, + OSLICE3: 8, + OSLICE3ARR: 8, + OSLICEHEADER: 8, + ODOTINTER: 8, + ODOTMETH: 8, + ODOTPTR: 8, + ODOTTYPE2: 8, + ODOTTYPE: 8, + ODOT: 8, + OXDOT: 8, + OCALLPART: 8, + OPLUS: 7, + ONOT: 7, + OBITNOT: 7, + ONEG: 7, + OADDR: 7, + ODEREF: 7, + ORECV: 7, + OMUL: 6, + ODIV: 6, + OMOD: 6, + OLSH: 6, + ORSH: 6, + OAND: 6, + OANDNOT: 6, + OADD: 5, + OSUB: 5, + OOR: 5, + OXOR: 5, + OEQ: 4, + OLT: 4, + OLE: 4, + OGE: 4, + OGT: 4, + ONE: 4, + OSEND: 3, + OANDAND: 2, + OOROR: 1, + + // Statements handled by stmtfmt + OAS: -1, + OAS2: -1, + OAS2DOTTYPE: -1, + OAS2FUNC: -1, + OAS2MAPR: -1, + OAS2RECV: -1, + OASOP: -1, + OBLOCK: -1, + OBREAK: -1, + OCASE: -1, + OCONTINUE: -1, + ODCL: -1, + ODEFER: -1, + OFALL: -1, + OFOR: -1, + OFORUNTIL: -1, + OGOTO: -1, + OIF: -1, + OLABEL: -1, + OGO: -1, + ORANGE: -1, + ORETURN: -1, + OSELECT: -1, + OSWITCH: -1, + + OEND: 0, +} + // Statements which may be rendered with a simplestmt as init. func StmtWithInit(op Op) bool { switch op { case OIF, OFOR, OFORUNTIL, OSWITCH: return true } - return false } @@ -1056,127 +1262,6 @@ func stmtFmt(n Node, s fmt.State, mode FmtMode) { } } -var OpPrec = []int{ - OALIGNOF: 8, - OAPPEND: 8, - OBYTES2STR: 8, - OARRAYLIT: 8, - OSLICELIT: 8, - ORUNES2STR: 8, - OCALLFUNC: 8, - OCALLINTER: 8, - OCALLMETH: 8, - OCALL: 8, - OCAP: 8, - OCLOSE: 8, - OCOMPLIT: 8, - OCONVIFACE: 8, - OCONVNOP: 8, - OCONV: 8, - OCOPY: 8, - ODELETE: 8, - OGETG: 8, - OLEN: 8, - OLITERAL: 8, - OMAKESLICE: 8, - OMAKESLICECOPY: 8, - OMAKE: 8, - OMAPLIT: 8, - ONAME: 8, - ONEW: 8, - ONIL: 8, - ONONAME: 8, - OOFFSETOF: 8, - OPACK: 8, - OPANIC: 8, - OPAREN: 8, - OPRINTN: 8, - OPRINT: 8, - ORUNESTR: 8, - OSIZEOF: 8, - OSTR2BYTES: 8, - OSTR2RUNES: 8, - OSTRUCTLIT: 8, - OTARRAY: 8, - OTSLICE: 8, - OTCHAN: 8, - OTFUNC: 8, - OTINTER: 8, - OTMAP: 8, - OTSTRUCT: 8, - OINDEXMAP: 8, - OINDEX: 8, - OSLICE: 8, - OSLICESTR: 8, - OSLICEARR: 8, - OSLICE3: 8, - OSLICE3ARR: 8, - OSLICEHEADER: 8, - ODOTINTER: 8, - ODOTMETH: 8, - ODOTPTR: 8, - ODOTTYPE2: 8, - ODOTTYPE: 8, - ODOT: 8, - OXDOT: 8, - OCALLPART: 8, - OPLUS: 7, - ONOT: 7, - OBITNOT: 7, - ONEG: 7, - OADDR: 7, - ODEREF: 7, - ORECV: 7, - OMUL: 6, - ODIV: 6, - OMOD: 6, - OLSH: 6, - ORSH: 6, - OAND: 6, - OANDNOT: 6, - OADD: 5, - OSUB: 5, - OOR: 5, - OXOR: 5, - OEQ: 4, - OLT: 4, - OLE: 4, - OGE: 4, - OGT: 4, - ONE: 4, - OSEND: 3, - OANDAND: 2, - OOROR: 1, - - // Statements handled by stmtfmt - OAS: -1, - OAS2: -1, - OAS2DOTTYPE: -1, - OAS2FUNC: -1, - OAS2MAPR: -1, - OAS2RECV: -1, - OASOP: -1, - OBLOCK: -1, - OBREAK: -1, - OCASE: -1, - OCONTINUE: -1, - ODCL: -1, - ODEFER: -1, - OFALL: -1, - OFOR: -1, - OFORUNTIL: -1, - OGOTO: -1, - OIF: -1, - OLABEL: -1, - OGO: -1, - ORANGE: -1, - ORETURN: -1, - OSELECT: -1, - OSWITCH: -1, - - OEND: 0, -} - func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { for { if n == nil { @@ -1564,27 +1649,176 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { } } -func nodeFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { - t := n.Type() - if flag&FmtLong != 0 && t != nil { - if t.Kind() == types.TNIL { - fmt.Fprint(s, "nil") - } else if n.Op() == ONAME && n.Name().AutoTemp() { - mode.Fprintf(s, "%v value", t) - } else { - mode.Fprintf(s, "%v (type %v)", n, t) +func ellipsisIf(b bool) string { + if b { + return "..." + } + return "" +} + +// Nodes + +type fmtNodes struct { + x Nodes + m FmtMode +} + +func (f *fmtNodes) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } + +func (l Nodes) Format(s fmt.State, verb rune) { l.format(s, verb, FErr) } + +func (l Nodes) format(s fmt.State, verb rune, mode FmtMode) { + switch verb { + case 'v': + l.hconv(s, fmtFlag(s, verb), mode) + + default: + fmt.Fprintf(s, "%%!%c(Nodes)", verb) + } +} + +func (n Nodes) String() string { + return fmt.Sprint(n) +} + +// Flags: all those of %N plus '.': separate with comma's instead of semicolons. +func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode FmtMode) { + if l.Len() == 0 && mode == FDbg { + fmt.Fprint(s, "") + return + } + + flag, mode = flag.update(mode) + sep := "; " + if mode == FDbg { + sep = "\n" + } else if flag&FmtComma != 0 { + sep = ", " + } + + for i, n := range l.Slice() { + fmt.Fprint(s, modeString(n, mode)) + if i+1 < l.Len() { + fmt.Fprint(s, sep) } - return + } +} + +// Dump + +func Dump(s string, n Node) { + fmt.Printf("%s [%p]%+v\n", s, n, n) +} + +func DumpList(s string, l Nodes) { + fmt.Printf("%s%+v\n", s, l) +} + +func FDumpList(w io.Writer, s string, l Nodes) { + fmt.Fprintf(w, "%s%+v\n", s, l) +} + +// TODO(gri) make variable local somehow +var dumpdepth int + +// indent prints indentation to s. +func indent(s fmt.State) { + fmt.Fprint(s, "\n") + for i := 0; i < dumpdepth; i++ { + fmt.Fprint(s, ". ") + } +} + +// EscFmt is set by the escape analysis code to add escape analysis details to the node print. +var EscFmt func(n Node) string + +// *Node details +func jconvFmt(n Node, s fmt.State, flag FmtFlag) { + // Useful to see which nodes in an AST printout are actually identical + if base.Debug.DumpPtrs != 0 { + fmt.Fprintf(s, " p(%p)", n) + } + if n.Name() != nil && n.Name().Vargen != 0 { + fmt.Fprintf(s, " g(%d)", n.Name().Vargen) } - // TODO inlining produces expressions with ninits. we can't print these yet. - - if OpPrec[n.Op()] < 0 { - stmtFmt(n, s, mode) - return + if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Defn != nil { + // Useful to see where Defn is set and what node it points to + fmt.Fprintf(s, " defn(%p)", n.Name().Defn) } - exprFmt(n, s, 0, mode) + if n.Pos().IsKnown() { + pfx := "" + switch n.Pos().IsStmt() { + case src.PosNotStmt: + pfx = "_" // "-" would be confusing + case src.PosIsStmt: + pfx = "+" + } + fmt.Fprintf(s, " l(%s%d)", pfx, n.Pos().Line()) + } + + if n.Offset() != types.BADWIDTH { + fmt.Fprintf(s, " x(%d)", n.Offset()) + } + + if n.Class() != 0 { + fmt.Fprintf(s, " class(%v)", n.Class()) + } + + if n.Colas() { + fmt.Fprintf(s, " colas(%v)", n.Colas()) + } + + if EscFmt != nil { + if esc := EscFmt(n); esc != "" { + fmt.Fprintf(s, " %s", esc) + } + } + + if n.Typecheck() != 0 { + fmt.Fprintf(s, " tc(%d)", n.Typecheck()) + } + + if n.IsDDD() { + fmt.Fprintf(s, " isddd(%v)", n.IsDDD()) + } + + if n.Implicit() { + fmt.Fprintf(s, " implicit(%v)", n.Implicit()) + } + + if n.Op() == ONAME { + if n.Name().Addrtaken() { + fmt.Fprint(s, " addrtaken") + } + if n.Name().Assigned() { + fmt.Fprint(s, " assigned") + } + if n.Name().IsClosureVar() { + fmt.Fprint(s, " closurevar") + } + if n.Name().Captured() { + fmt.Fprint(s, " captured") + } + if n.Name().IsOutputParamHeapAddr() { + fmt.Fprint(s, " outputparamheapaddr") + } + } + if n.Bounded() { + fmt.Fprint(s, " bounded") + } + if n.NonNil() { + fmt.Fprint(s, " nonnil") + } + + if n.HasCall() { + fmt.Fprint(s, " hascall") + } + + if n.Name() != nil && n.Name().Used() { + fmt.Fprint(s, " used") + } } func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { @@ -1686,241 +1920,3 @@ func asNameNodes(list []*Name) Nodes { } return ns } - -// "%S" suppresses qualifying with package -func symFormat(s *types.Sym, f fmt.State, verb rune, mode FmtMode) { - switch verb { - case 'v', 'S': - fmt.Fprint(f, sconv(s, fmtFlag(f, verb), mode)) - - default: - fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s) - } -} - -func smodeString(s *types.Sym, mode FmtMode) string { return sconv(s, 0, mode) } - -// See #16897 before changing the implementation of sconv. -func sconv(s *types.Sym, flag FmtFlag, mode FmtMode) string { - if flag&FmtLong != 0 { - panic("linksymfmt") - } - - if s == nil { - return "" - } - - if s.Name == "_" { - return "_" - } - buf := fmtBufferPool.Get().(*bytes.Buffer) - buf.Reset() - defer fmtBufferPool.Put(buf) - - flag, mode = flag.update(mode) - symfmt(buf, s, flag, mode) - return types.InternString(buf.Bytes()) -} - -func sconv2(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { - if flag&FmtLong != 0 { - panic("linksymfmt") - } - if s == nil { - b.WriteString("") - return - } - if s.Name == "_" { - b.WriteString("_") - return - } - - flag, mode = flag.update(mode) - symfmt(b, s, flag, mode) -} - -func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visited map[*types.Type]int, funarg types.Funarg) { - if f == nil { - b.WriteString("") - return - } - flag, mode = flag.update(mode) - if mode == FTypeIdName { - flag |= FmtUnsigned - } - - var name string - if flag&FmtShort == 0 { - s := f.Sym - - // Take the name from the original. - if mode == FErr { - s = OrigSym(s) - } - - if s != nil && f.Embedded == 0 { - if funarg != types.FunargNone { - name = modeString(AsNode(f.Nname), mode) - } else if flag&FmtLong != 0 { - name = mode.Sprintf("%0S", s) - if !types.IsExported(name) && flag&FmtUnsigned == 0 { - name = smodeString(s, mode) // qualify non-exported names (used on structs, not on funarg) - } - } else { - name = smodeString(s, mode) - } - } - } - - if name != "" { - b.WriteString(name) - b.WriteString(" ") - } - - if f.IsDDD() { - var et *types.Type - if f.Type != nil { - et = f.Type.Elem() - } - b.WriteString("...") - tconv2(b, et, 0, mode, visited) - } else { - tconv2(b, f.Type, 0, mode, visited) - } - - if flag&FmtShort == 0 && funarg == types.FunargNone && f.Note != "" { - b.WriteString(" ") - b.WriteString(strconv.Quote(f.Note)) - } -} - -// "%L" print definition, not name -// "%S" omit 'func' and receiver from function types, short type names -func typeFormat(t *types.Type, s fmt.State, verb rune, mode FmtMode) { - switch verb { - case 'v', 'S', 'L': - fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode)) - default: - fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t) - } -} - -func modeString(n Node, mode FmtMode) string { return mode.Sprint(n) } - -// "%L" suffix with "(type %T)" where possible -// "%+S" in debug mode, don't recurse, no multiline output -func nconvFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { - if n == nil { - fmt.Fprint(s, "") - return - } - - flag, mode = flag.update(mode) - - switch mode { - case FErr: - nodeFmt(n, s, flag, mode) - - case FDbg: - dumpdepth++ - nodeDumpFmt(n, s, flag, mode) - dumpdepth-- - - default: - base.Fatalf("unhandled %%N mode: %d", mode) - } -} - -func (l Nodes) format(s fmt.State, verb rune, mode FmtMode) { - switch verb { - case 'v': - l.hconv(s, fmtFlag(s, verb), mode) - - default: - fmt.Fprintf(s, "%%!%c(Nodes)", verb) - } -} - -func (n Nodes) String() string { - return fmt.Sprint(n) -} - -// Flags: all those of %N plus '.': separate with comma's instead of semicolons. -func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode FmtMode) { - if l.Len() == 0 && mode == FDbg { - fmt.Fprint(s, "") - return - } - - flag, mode = flag.update(mode) - sep := "; " - if mode == FDbg { - sep = "\n" - } else if flag&FmtComma != 0 { - sep = ", " - } - - for i, n := range l.Slice() { - fmt.Fprint(s, modeString(n, mode)) - if i+1 < l.Len() { - fmt.Fprint(s, sep) - } - } -} - -func DumpList(s string, l Nodes) { - fmt.Printf("%s%+v\n", s, l) -} - -func FDumpList(w io.Writer, s string, l Nodes) { - fmt.Fprintf(w, "%s%+v\n", s, l) -} - -func Dump(s string, n Node) { - fmt.Printf("%s [%p]%+v\n", s, n, n) -} - -// TODO(gri) make variable local somehow -var dumpdepth int - -// indent prints indentation to s. -func indent(s fmt.State) { - fmt.Fprint(s, "\n") - for i := 0; i < dumpdepth; i++ { - fmt.Fprint(s, ". ") - } -} - -func ellipsisIf(b bool) string { - if b { - return "..." - } - return "" -} - -// numImport tracks how often a package with a given name is imported. -// It is used to provide a better error message (by using the package -// path to disambiguate) if a package that appears multiple times with -// the same name appears in an error message. -var NumImport = make(map[string]int) - -func InstallTypeFormats() { - types.Sconv = func(s *types.Sym, flag, mode int) string { - return sconv(s, FmtFlag(flag), FmtMode(mode)) - } - types.Tconv = func(t *types.Type, flag, mode int) string { - return tconv(t, FmtFlag(flag), FmtMode(mode)) - } - types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) { - symFormat(sym, s, verb, FmtMode(mode)) - } - types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) { - typeFormat(t, s, verb, FmtMode(mode)) - } -} - -// Line returns n's position as a string. If n has been inlined, -// it uses the outermost position where n has been inlined. -func Line(n Node) string { - return base.FmtPos(n.Pos()) -} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 7fd02925ba..83f5b0cf78 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -116,6 +116,12 @@ type Node interface { CanBeAnSSASym() } +// Line returns n's position as a string. If n has been inlined, +// it uses the outermost position where n has been inlined. +func Line(n Node) string { + return base.FmtPos(n.Pos()) +} + func IsSynthetic(n Node) bool { name := n.Sym().Name return name[0] == '.' || name[0] == '~' From 8ce2605c5b4bc64432e1711a1273f91eee3a41fc Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 5 Dec 2020 00:02:46 -0500 Subject: [PATCH 168/212] [dev.regabi] cmd/compile: untangle ir.Dump printing The Node printing code is tangled up due to the multiple printing modes. Split out the Dump mode into its own code, which clarifies it considerably. We are going to have to change the code for the new Node representations, so it is nice to have it in an understandable form first. The output of Dump is unchanged except for the removal of spurious mid-Dump blank lines that have been printed for a while but don't really make sense and appear to be a bug. The %+v verb on Op prints the name ("ADD" not "+"), matching %+v on Node and %+v on Nodes to get Dump and DumpList formats. Passes buildall w/ toolstash -cmp. Change-Id: I07f0f245859f1f785e10bdd671855ca43c51b545 Reviewed-on: https://go-review.googlesource.com/c/go/+/275774 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/fmtmap_test.go | 4 +- src/cmd/compile/internal/ir/fmt.go | 272 +++++++++++++++-------------- 2 files changed, 144 insertions(+), 132 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index fde9c51b27..bf81cc07db 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -42,12 +42,14 @@ var knownFormats = map[string]string{ "*cmd/compile/internal/ssa.sparseTreeMapEntry %v": "", "*cmd/compile/internal/types.Field %p": "", "*cmd/compile/internal/types.Field %v": "", + "*cmd/compile/internal/types.Sym %+v": "", "*cmd/compile/internal/types.Sym %0S": "", "*cmd/compile/internal/types.Sym %S": "", "*cmd/compile/internal/types.Sym %p": "", "*cmd/compile/internal/types.Sym %v": "", "*cmd/compile/internal/types.Type %#L": "", "*cmd/compile/internal/types.Type %#v": "", + "*cmd/compile/internal/types.Type %+v": "", "*cmd/compile/internal/types.Type %-S": "", "*cmd/compile/internal/types.Type %0S": "", "*cmd/compile/internal/types.Type %L": "", @@ -88,7 +90,6 @@ var knownFormats = map[string]string{ "cmd/compile/internal/ir.Node %+v": "", "cmd/compile/internal/ir.Node %L": "", "cmd/compile/internal/ir.Node %S": "", - "cmd/compile/internal/ir.Node %j": "", "cmd/compile/internal/ir.Node %p": "", "cmd/compile/internal/ir.Node %v": "", "cmd/compile/internal/ir.Nodes %#v": "", @@ -97,6 +98,7 @@ var knownFormats = map[string]string{ "cmd/compile/internal/ir.Nodes %v": "", "cmd/compile/internal/ir.Ntype %v": "", "cmd/compile/internal/ir.Op %#v": "", + "cmd/compile/internal/ir.Op %+v": "", "cmd/compile/internal/ir.Op %v": "", "cmd/compile/internal/ssa.BranchPrediction %d": "", "cmd/compile/internal/ssa.Edge %v": "", diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index ae33dcddd7..b5bf036d5e 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -9,6 +9,7 @@ import ( "fmt" "go/constant" "io" + "os" "strconv" "strings" "sync" @@ -258,7 +259,10 @@ var OpNames = []string{ } func (o Op) GoString() string { - return fmt.Sprintf("%#v", o) + if int(o) < len(OpNames) && OpNames[o] != "" { + return OpNames[o] + } + return o.String() } type fmtOp struct { @@ -266,30 +270,20 @@ type fmtOp struct { m FmtMode } -func (f *fmtOp) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } +func (f *fmtOp) Format(s fmt.State, verb rune) { f.x.Format(s, verb) } -func (o Op) Format(s fmt.State, verb rune) { o.format(s, verb, FErr) } - -func (o Op) format(s fmt.State, verb rune, mode FmtMode) { +func (o Op) Format(s fmt.State, verb rune) { switch verb { - case 'v': - o.oconv(s, fmtFlag(s, verb), mode) - default: fmt.Fprintf(s, "%%!%c(Op=%d)", verb, int(o)) - } -} - -func (o Op) oconv(s fmt.State, flag FmtFlag, mode FmtMode) { - if flag&FmtSharp != 0 || mode != FDbg { - if int(o) < len(OpNames) && OpNames[o] != "" { - fmt.Fprint(s, OpNames[o]) + case 'v': + if s.Flag('+') { + // %+v is OMUL instead of "*" + io.WriteString(s, o.String()) return } + io.WriteString(s, o.GoString()) } - - // 'o.String()' instead of just 'o' to avoid infinite recursion - fmt.Fprint(s, o.String()) } // Val @@ -346,6 +340,9 @@ func (f *fmtSym) Format(s fmt.State, verb rune) { symFormat(f.x, s, verb, f.m) } func symFormat(s *types.Sym, f fmt.State, verb rune, mode FmtMode) { switch verb { case 'v', 'S': + if verb == 'v' && f.Flag('+') { + mode = FDbg + } fmt.Fprint(f, sconv(s, fmtFlag(f, verb), mode)) default: @@ -514,6 +511,9 @@ func (f *fmtType) Format(s fmt.State, verb rune) { typeFormat(f.x, s, verb, f.m) func typeFormat(t *types.Type, s fmt.State, verb rune, mode FmtMode) { switch verb { case 'v', 'S', 'L': + if verb == 'v' && s.Flag('+') { // %+v is debug format + mode = FDbg + } fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode)) default: fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t) @@ -897,6 +897,13 @@ type fmtNode struct { func (f *fmtNode) Format(s fmt.State, verb rune) { nodeFormat(f.x, s, verb, f.m) } func FmtNode(n Node, s fmt.State, verb rune) { + // %+v prints Dump. + if s.Flag('+') && verb == 'v' { + dumpNode(s, n, 1) + return + } + + // Otherwise print Go syntax. nodeFormat(n, s, verb, FErr) } @@ -905,9 +912,6 @@ func nodeFormat(n Node, s fmt.State, verb rune, mode FmtMode) { case 'v', 'S', 'L': nconvFmt(n, s, fmtFlag(s, verb), mode) - case 'j': - jconvFmt(n, s, fmtFlag(s, verb)) - default: fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n) } @@ -927,11 +931,6 @@ func nconvFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { case FErr: nodeFmt(n, s, flag, mode) - case FDbg: - dumpdepth++ - nodeDumpFmt(n, s, flag, mode) - dumpdepth-- - default: base.Fatalf("unhandled %%N mode: %d", mode) } @@ -1663,11 +1662,17 @@ type fmtNodes struct { m FmtMode } -func (f *fmtNodes) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } +func (f *fmtNodes) Format(s fmt.State, verb rune) { f.x.format(s, verb, FErr) } func (l Nodes) Format(s fmt.State, verb rune) { l.format(s, verb, FErr) } func (l Nodes) format(s fmt.State, verb rune, mode FmtMode) { + if s.Flag('+') && verb == 'v' { + // %+v is DumpList output + dumpNodes(s, l, 1) + return + } + switch verb { case 'v': l.hconv(s, fmtFlag(s, verb), mode) @@ -1683,16 +1688,9 @@ func (n Nodes) String() string { // Flags: all those of %N plus '.': separate with comma's instead of semicolons. func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode FmtMode) { - if l.Len() == 0 && mode == FDbg { - fmt.Fprint(s, "") - return - } - flag, mode = flag.update(mode) sep := "; " - if mode == FDbg { - sep = "\n" - } else if flag&FmtComma != 0 { + if flag&FmtComma != 0 { sep = ", " } @@ -1707,44 +1705,45 @@ func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode FmtMode) { // Dump func Dump(s string, n Node) { - fmt.Printf("%s [%p]%+v\n", s, n, n) + fmt.Printf("%s [%p]%+v", s, n, n) } func DumpList(s string, l Nodes) { - fmt.Printf("%s%+v\n", s, l) + var buf bytes.Buffer + FDumpList(&buf, s, l) + os.Stdout.Write(buf.Bytes()) } func FDumpList(w io.Writer, s string, l Nodes) { - fmt.Fprintf(w, "%s%+v\n", s, l) + io.WriteString(w, s) + dumpNodes(w, l, 1) + io.WriteString(w, "\n") } -// TODO(gri) make variable local somehow -var dumpdepth int - -// indent prints indentation to s. -func indent(s fmt.State) { - fmt.Fprint(s, "\n") - for i := 0; i < dumpdepth; i++ { - fmt.Fprint(s, ". ") +// indent prints indentation to w. +func indent(w io.Writer, depth int) { + fmt.Fprint(w, "\n") + for i := 0; i < depth; i++ { + fmt.Fprint(w, ". ") } } // EscFmt is set by the escape analysis code to add escape analysis details to the node print. var EscFmt func(n Node) string -// *Node details -func jconvFmt(n Node, s fmt.State, flag FmtFlag) { +// dumpNodeHeader prints the debug-format node header line to w. +func dumpNodeHeader(w io.Writer, n Node) { // Useful to see which nodes in an AST printout are actually identical if base.Debug.DumpPtrs != 0 { - fmt.Fprintf(s, " p(%p)", n) + fmt.Fprintf(w, " p(%p)", n) } if n.Name() != nil && n.Name().Vargen != 0 { - fmt.Fprintf(s, " g(%d)", n.Name().Vargen) + fmt.Fprintf(w, " g(%d)", n.Name().Vargen) } if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Defn != nil { // Useful to see where Defn is set and what node it points to - fmt.Fprintf(s, " defn(%p)", n.Name().Defn) + fmt.Fprintf(w, " defn(%p)", n.Name().Defn) } if n.Pos().IsKnown() { @@ -1755,168 +1754,179 @@ func jconvFmt(n Node, s fmt.State, flag FmtFlag) { case src.PosIsStmt: pfx = "+" } - fmt.Fprintf(s, " l(%s%d)", pfx, n.Pos().Line()) + fmt.Fprintf(w, " l(%s%d)", pfx, n.Pos().Line()) } if n.Offset() != types.BADWIDTH { - fmt.Fprintf(s, " x(%d)", n.Offset()) + fmt.Fprintf(w, " x(%d)", n.Offset()) } if n.Class() != 0 { - fmt.Fprintf(s, " class(%v)", n.Class()) + fmt.Fprintf(w, " class(%v)", n.Class()) } if n.Colas() { - fmt.Fprintf(s, " colas(%v)", n.Colas()) + fmt.Fprintf(w, " colas(%v)", n.Colas()) } if EscFmt != nil { if esc := EscFmt(n); esc != "" { - fmt.Fprintf(s, " %s", esc) + fmt.Fprintf(w, " %s", esc) } } if n.Typecheck() != 0 { - fmt.Fprintf(s, " tc(%d)", n.Typecheck()) + fmt.Fprintf(w, " tc(%d)", n.Typecheck()) } if n.IsDDD() { - fmt.Fprintf(s, " isddd(%v)", n.IsDDD()) + fmt.Fprintf(w, " isddd(%v)", n.IsDDD()) } if n.Implicit() { - fmt.Fprintf(s, " implicit(%v)", n.Implicit()) + fmt.Fprintf(w, " implicit(%v)", n.Implicit()) } if n.Op() == ONAME { if n.Name().Addrtaken() { - fmt.Fprint(s, " addrtaken") + fmt.Fprint(w, " addrtaken") } if n.Name().Assigned() { - fmt.Fprint(s, " assigned") + fmt.Fprint(w, " assigned") } if n.Name().IsClosureVar() { - fmt.Fprint(s, " closurevar") + fmt.Fprint(w, " closurevar") } if n.Name().Captured() { - fmt.Fprint(s, " captured") + fmt.Fprint(w, " captured") } if n.Name().IsOutputParamHeapAddr() { - fmt.Fprint(s, " outputparamheapaddr") + fmt.Fprint(w, " outputparamheapaddr") } } if n.Bounded() { - fmt.Fprint(s, " bounded") + fmt.Fprint(w, " bounded") } if n.NonNil() { - fmt.Fprint(s, " nonnil") + fmt.Fprint(w, " nonnil") } if n.HasCall() { - fmt.Fprint(s, " hascall") + fmt.Fprint(w, " hascall") } if n.Name() != nil && n.Name().Used() { - fmt.Fprint(s, " used") + fmt.Fprint(w, " used") } } -func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { - recur := flag&FmtShort == 0 +func dumpNode(w io.Writer, n Node, depth int) { + indent(w, depth) + if depth > 40 { + fmt.Fprint(w, "...") + return + } - if recur { - indent(s) - if dumpdepth > 40 { - fmt.Fprint(s, "...") - return - } - - if n.Init().Len() != 0 { - mode.Fprintf(s, "%v-init%v", n.Op(), n.Init()) - indent(s) - } + if n.Init().Len() != 0 { + fmt.Fprintf(w, "%+v-init", n.Op()) + dumpNodes(w, n.Init(), depth+1) + indent(w, depth) } switch n.Op() { default: - mode.Fprintf(s, "%v%j", n.Op(), n) + fmt.Fprintf(w, "%+v", n.Op()) + dumpNodeHeader(w, n) case OLITERAL: - mode.Fprintf(s, "%v-%v%j", n.Op(), n.Val(), n) + fmt.Fprintf(w, "%+v-%v", n.Op(), n.Val()) + dumpNodeHeader(w, n) case ONAME, ONONAME, OMETHEXPR: if n.Sym() != nil { - mode.Fprintf(s, "%v-%v%j", n.Op(), n.Sym(), n) + fmt.Fprintf(w, "%+v-%+v", n.Op(), n.Sym()) } else { - mode.Fprintf(s, "%v%j", n.Op(), n) + fmt.Fprintf(w, "%+v", n.Op()) } - if recur && n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil { - indent(s) - mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Ntype) + dumpNodeHeader(w, n) + if n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil { + indent(w, depth) + fmt.Fprintf(w, "%+v-ntype", n.Op()) + dumpNode(w, n.Name().Ntype, depth+1) } case OASOP: - mode.Fprintf(s, "%v-%v%j", n.Op(), n.SubOp(), n) + fmt.Fprintf(w, "%+v-%+v", n.Op(), n.SubOp()) + dumpNodeHeader(w, n) case OTYPE: - mode.Fprintf(s, "%v %v%j type=%v", n.Op(), n.Sym(), n, n.Type()) - if recur && n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil { - indent(s) - mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Ntype) + fmt.Fprintf(w, "%+v %+v", n.Op(), n.Sym()) + dumpNodeHeader(w, n) + fmt.Fprintf(w, " type=%+v", n.Type()) + if n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil { + indent(w, depth) + fmt.Fprintf(w, "%+v-ntype", n.Op()) + dumpNode(w, n.Name().Ntype, depth+1) } } if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Nname.Sym() != nil { - mode.Fprintf(s, " fnName %v", n.Func().Nname.Sym()) + fmt.Fprintf(w, " fnName %+v", n.Func().Nname.Sym()) } if n.Sym() != nil && n.Op() != ONAME { - mode.Fprintf(s, " %v", n.Sym()) + fmt.Fprintf(w, " %+v", n.Sym()) } if n.Type() != nil { - mode.Fprintf(s, " %v", n.Type()) + fmt.Fprintf(w, " %+v", n.Type()) } - if recur { - if n.Left() != nil { - mode.Fprintf(s, "%v", n.Left()) - } - if n.Right() != nil { - mode.Fprintf(s, "%v", n.Right()) - } - if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Body().Len() != 0 { - indent(s) - // The function associated with a closure - mode.Fprintf(s, "%v-clofunc%v", n.Op(), n.Func()) - } - if n.Op() == ODCLFUNC && n.Func() != nil && n.Func().Dcl != nil && len(n.Func().Dcl) != 0 { - indent(s) - // The dcls for a func or closure - mode.Fprintf(s, "%v-dcl%v", n.Op(), asNameNodes(n.Func().Dcl)) - } - if n.List().Len() != 0 { - indent(s) - mode.Fprintf(s, "%v-list%v", n.Op(), n.List()) + if n.Left() != nil { + dumpNode(w, n.Left(), depth+1) + } + if n.Right() != nil { + dumpNode(w, n.Right(), depth+1) + } + if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Body().Len() != 0 { + indent(w, depth) + // The function associated with a closure + fmt.Fprintf(w, "%+v-clofunc", n.Op()) + dumpNode(w, n.Func(), depth+1) + } + if n.Op() == ODCLFUNC && n.Func() != nil && n.Func().Dcl != nil && len(n.Func().Dcl) != 0 { + indent(w, depth) + // The dcls for a func or closure + fmt.Fprintf(w, "%+v-dcl", n.Op()) + for _, dcl := range n.Func().Dcl { + dumpNode(w, dcl, depth+1) } + } + if n.List().Len() != 0 { + indent(w, depth) + fmt.Fprintf(w, "%+v-list", n.Op()) + dumpNodes(w, n.List(), depth+1) + } - if n.Rlist().Len() != 0 { - indent(s) - mode.Fprintf(s, "%v-rlist%v", n.Op(), n.Rlist()) - } + if n.Rlist().Len() != 0 { + indent(w, depth) + fmt.Fprintf(w, "%+v-rlist", n.Op()) + dumpNodes(w, n.Rlist(), depth+1) + } - if n.Body().Len() != 0 { - indent(s) - mode.Fprintf(s, "%v-body%v", n.Op(), n.Body()) - } + if n.Body().Len() != 0 { + indent(w, depth) + fmt.Fprintf(w, "%+v-body", n.Op()) + dumpNodes(w, n.Body(), depth+1) } } -// asNameNodes copies list to a new Nodes. -// It should only be called in debug formatting and other low-performance contexts. -func asNameNodes(list []*Name) Nodes { - var ns Nodes - for _, n := range list { - ns.Append(n) +func dumpNodes(w io.Writer, list Nodes, depth int) { + if list.Len() == 0 { + fmt.Fprintf(w, " ") + return + } + + for _, n := range list.Slice() { + dumpNode(w, n, depth) } - return ns } From 3b25f3c1504cdc8f2263d68436df42042251b290 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 5 Dec 2020 14:46:19 -0500 Subject: [PATCH 169/212] [dev.regabi] cmd/compile: simplify Op, Node, Nodes printing nconvFmt calls base.Fatalf if mode is anything but FErr, proving that the only formats that matter for nodes are plain %v, %S, and %L. And the nodes formatter can only get to %v. (%S and %v are the same; we'll clean that up separately.) Node and Nodes can therefore ignore mode, and all the mode code can be removed from those implementations, removing quite a few layers of abstraction. Op similarly only runs in one mode and can be simplified. Passes buildall w/ toolstash -cmp. Change-Id: Ibfd845033e9c68181a20fb81c8f3dd428463920a Reviewed-on: https://go-review.googlesource.com/c/go/+/275775 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/fmtmap_test.go | 2 - src/cmd/compile/internal/gc/walk.go | 2 +- src/cmd/compile/internal/ir/fmt.go | 351 ++++++++++++---------------- 3 files changed, 155 insertions(+), 200 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index bf81cc07db..60b772e932 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -85,8 +85,6 @@ var knownFormats = map[string]string{ "cmd/compile/internal/gc.itag %v": "", "cmd/compile/internal/ir.Class %d": "", "cmd/compile/internal/ir.Class %v": "", - "cmd/compile/internal/ir.FmtMode %d": "", - "cmd/compile/internal/ir.Node %+S": "", "cmd/compile/internal/ir.Node %+v": "", "cmd/compile/internal/ir.Node %L": "", "cmd/compile/internal/ir.Node %S": "", diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index bbc08ab953..574c7c4709 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -481,7 +481,7 @@ opswitch: switch n.Op() { default: ir.Dump("walk", n) - base.Fatalf("walkexpr: switch 1 unknown op %+S", n) + base.Fatalf("walkexpr: switch 1 unknown op %+v", n.Op()) case ir.ONONAME, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR: diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index b5bf036d5e..b0c732ae56 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -170,19 +170,13 @@ func (m FmtMode) Sprint(args ...interface{}) string { func (m FmtMode) prepareArgs(args []interface{}) { for i, arg := range args { switch arg := arg.(type) { - case Op: - args[i] = &fmtOp{arg, m} - case Node: - args[i] = &fmtNode{arg, m} case nil: - args[i] = &fmtNode{nil, m} // assume this was a node interface + args[i] = "" // assume this was a node interface case *types.Type: args[i] = &fmtType{arg, m} case *types.Sym: args[i] = &fmtSym{arg, m} - case Nodes: - args[i] = &fmtNodes{arg, m} - case int32, int64, string, types.Kind, constant.Value: + case int32, int64, string, Op, Node, Nodes, types.Kind, constant.Value: // OK: printing these types doesn't depend on mode default: base.Fatalf("mode.prepareArgs type %T", arg) @@ -265,13 +259,6 @@ func (o Op) GoString() string { return o.String() } -type fmtOp struct { - x Op - m FmtMode -} - -func (f *fmtOp) Format(s fmt.State, verb rune) { f.x.Format(s, verb) } - func (o Op) Format(s fmt.State, verb rune) { switch verb { default: @@ -851,7 +838,7 @@ func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visite if s != nil && f.Embedded == 0 { if funarg != types.FunargNone { - name = modeString(AsNode(f.Nname), mode) + name = fmt.Sprint(f.Nname) } else if flag&FmtLong != 0 { name = mode.Sprintf("%0S", s) if !types.IsExported(name) && flag&FmtUnsigned == 0 { @@ -887,64 +874,38 @@ func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visite // Node -func modeString(n Node, mode FmtMode) string { return mode.Sprint(n) } - -type fmtNode struct { - x Node - m FmtMode -} - -func (f *fmtNode) Format(s fmt.State, verb rune) { nodeFormat(f.x, s, verb, f.m) } - func FmtNode(n Node, s fmt.State, verb rune) { + // TODO(rsc): Remove uses of %#v, which behaves just like %v. + // TODO(rsc): Remove uses of %S, which behaves just like %v. + if verb == 'S' { + verb = 'v' + } + // %+v prints Dump. + // Otherwise we print Go syntax. if s.Flag('+') && verb == 'v' { dumpNode(s, n, 1) return } - // Otherwise print Go syntax. - nodeFormat(n, s, verb, FErr) -} - -func nodeFormat(n Node, s fmt.State, verb rune, mode FmtMode) { - switch verb { - case 'v', 'S', 'L': - nconvFmt(n, s, fmtFlag(s, verb), mode) - - default: + if verb != 'v' && verb != 'S' && verb != 'L' { fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n) + return } -} -// "%L" suffix with "(type %T)" where possible -// "%+S" in debug mode, don't recurse, no multiline output -func nconvFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { if n == nil { fmt.Fprint(s, "") return } - flag, mode = flag.update(mode) - - switch mode { - case FErr: - nodeFmt(n, s, flag, mode) - - default: - base.Fatalf("unhandled %%N mode: %d", mode) - } -} - -func nodeFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { t := n.Type() - if flag&FmtLong != 0 && t != nil { + if verb == 'L' && t != nil { if t.Kind() == types.TNIL { fmt.Fprint(s, "nil") } else if n.Op() == ONAME && n.Name().AutoTemp() { - mode.Fprintf(s, "%v value", t) + fmt.Fprintf(s, "%v value", t) } else { - mode.Fprintf(s, "%v (type %v)", n, t) + fmt.Fprintf(s, "%v (type %v)", n, t) } return } @@ -952,11 +913,11 @@ func nodeFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) { // TODO inlining produces expressions with ninits. we can't print these yet. if OpPrec[n.Op()] < 0 { - stmtFmt(n, s, mode) + stmtFmt(n, s) return } - exprFmt(n, s, 0, mode) + exprFmt(n, s, 0) } var OpPrec = []int{ @@ -1089,7 +1050,15 @@ func StmtWithInit(op Op) bool { return false } -func stmtFmt(n Node, s fmt.State, mode FmtMode) { +func stmtFmt(n Node, s fmt.State) { + // NOTE(rsc): This code used to support the text-based + // which was more aggressive about printing full Go syntax + // (for example, an actual loop instead of "for loop"). + // The code is preserved for now in case we want to expand + // any of those shortenings later. Or maybe we will delete + // the code. But for now, keep it. + const exportFormat = false + // some statements allow for an init, but at most one, // but we may have an arbitrary number added, eg by typecheck // and inlining. If it doesn't fit the syntax, emit an enclosing @@ -1099,7 +1068,7 @@ func stmtFmt(n Node, s fmt.State, mode FmtMode) { simpleinit := n.Init().Len() == 1 && n.Init().First().Init().Len() == 0 && StmtWithInit(n.Op()) // otherwise, print the inits as separate statements - complexinit := n.Init().Len() != 0 && !simpleinit && (mode != FErr) + complexinit := n.Init().Len() != 0 && !simpleinit && exportFormat // but if it was for if/for/switch, put in an extra surrounding block to limit the scope extrablock := complexinit && StmtWithInit(n.Op()) @@ -1109,70 +1078,70 @@ func stmtFmt(n Node, s fmt.State, mode FmtMode) { } if complexinit { - mode.Fprintf(s, " %v; ", n.Init()) + fmt.Fprintf(s, " %v; ", n.Init()) } switch n.Op() { case ODCL: - mode.Fprintf(s, "var %v %v", n.Left().Sym(), n.Left().Type()) + fmt.Fprintf(s, "var %v %v", n.Left().Sym(), n.Left().Type()) // Don't export "v = " initializing statements, hope they're always // preceded by the DCL which will be re-parsed and typechecked to reproduce // the "v = " again. case OAS: if n.Colas() && !complexinit { - mode.Fprintf(s, "%v := %v", n.Left(), n.Right()) + fmt.Fprintf(s, "%v := %v", n.Left(), n.Right()) } else { - mode.Fprintf(s, "%v = %v", n.Left(), n.Right()) + fmt.Fprintf(s, "%v = %v", n.Left(), n.Right()) } case OASOP: if n.Implicit() { if n.SubOp() == OADD { - mode.Fprintf(s, "%v++", n.Left()) + fmt.Fprintf(s, "%v++", n.Left()) } else { - mode.Fprintf(s, "%v--", n.Left()) + fmt.Fprintf(s, "%v--", n.Left()) } break } - mode.Fprintf(s, "%v %#v= %v", n.Left(), n.SubOp(), n.Right()) + fmt.Fprintf(s, "%v %#v= %v", n.Left(), n.SubOp(), n.Right()) case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: if n.Colas() && !complexinit { - mode.Fprintf(s, "%.v := %.v", n.List(), n.Rlist()) + fmt.Fprintf(s, "%.v := %.v", n.List(), n.Rlist()) } else { - mode.Fprintf(s, "%.v = %.v", n.List(), n.Rlist()) + fmt.Fprintf(s, "%.v = %.v", n.List(), n.Rlist()) } case OBLOCK: if n.List().Len() != 0 { - mode.Fprintf(s, "%v", n.List()) + fmt.Fprintf(s, "%v", n.List()) } case ORETURN: - mode.Fprintf(s, "return %.v", n.List()) + fmt.Fprintf(s, "return %.v", n.List()) case ORETJMP: - mode.Fprintf(s, "retjmp %v", n.Sym()) + fmt.Fprintf(s, "retjmp %v", n.Sym()) case OINLMARK: - mode.Fprintf(s, "inlmark %d", n.Offset()) + fmt.Fprintf(s, "inlmark %d", n.Offset()) case OGO: - mode.Fprintf(s, "go %v", n.Left()) + fmt.Fprintf(s, "go %v", n.Left()) case ODEFER: - mode.Fprintf(s, "defer %v", n.Left()) + fmt.Fprintf(s, "defer %v", n.Left()) case OIF: if simpleinit { - mode.Fprintf(s, "if %v; %v { %v }", n.Init().First(), n.Left(), n.Body()) + fmt.Fprintf(s, "if %v; %v { %v }", n.Init().First(), n.Left(), n.Body()) } else { - mode.Fprintf(s, "if %v { %v }", n.Left(), n.Body()) + fmt.Fprintf(s, "if %v { %v }", n.Left(), n.Body()) } if n.Rlist().Len() != 0 { - mode.Fprintf(s, " else { %v }", n.Rlist()) + fmt.Fprintf(s, " else { %v }", n.Rlist()) } case OFOR, OFORUNTIL: @@ -1180,80 +1149,80 @@ func stmtFmt(n Node, s fmt.State, mode FmtMode) { if n.Op() == OFORUNTIL { opname = "foruntil" } - if mode == FErr { // TODO maybe only if FmtShort, same below + if !exportFormat { // TODO maybe only if FmtShort, same below fmt.Fprintf(s, "%s loop", opname) break } fmt.Fprint(s, opname) if simpleinit { - mode.Fprintf(s, " %v;", n.Init().First()) + fmt.Fprintf(s, " %v;", n.Init().First()) } else if n.Right() != nil { fmt.Fprint(s, " ;") } if n.Left() != nil { - mode.Fprintf(s, " %v", n.Left()) + fmt.Fprintf(s, " %v", n.Left()) } if n.Right() != nil { - mode.Fprintf(s, "; %v", n.Right()) + fmt.Fprintf(s, "; %v", n.Right()) } else if simpleinit { fmt.Fprint(s, ";") } if n.Op() == OFORUNTIL && n.List().Len() != 0 { - mode.Fprintf(s, "; %v", n.List()) + fmt.Fprintf(s, "; %v", n.List()) } - mode.Fprintf(s, " { %v }", n.Body()) + fmt.Fprintf(s, " { %v }", n.Body()) case ORANGE: - if mode == FErr { + if !exportFormat { fmt.Fprint(s, "for loop") break } if n.List().Len() == 0 { - mode.Fprintf(s, "for range %v { %v }", n.Right(), n.Body()) + fmt.Fprintf(s, "for range %v { %v }", n.Right(), n.Body()) break } - mode.Fprintf(s, "for %.v = range %v { %v }", n.List(), n.Right(), n.Body()) + fmt.Fprintf(s, "for %.v = range %v { %v }", n.List(), n.Right(), n.Body()) case OSELECT, OSWITCH: - if mode == FErr { - mode.Fprintf(s, "%v statement", n.Op()) + if !exportFormat { + fmt.Fprintf(s, "%v statement", n.Op()) break } - mode.Fprintf(s, "%#v", n.Op()) + fmt.Fprintf(s, "%#v", n.Op()) if simpleinit { - mode.Fprintf(s, " %v;", n.Init().First()) + fmt.Fprintf(s, " %v;", n.Init().First()) } if n.Left() != nil { - mode.Fprintf(s, " %v ", n.Left()) + fmt.Fprintf(s, " %v ", n.Left()) } - mode.Fprintf(s, " { %v }", n.List()) + fmt.Fprintf(s, " { %v }", n.List()) case OCASE: if n.List().Len() != 0 { - mode.Fprintf(s, "case %.v", n.List()) + fmt.Fprintf(s, "case %.v", n.List()) } else { fmt.Fprint(s, "default") } - mode.Fprintf(s, ": %v", n.Body()) + fmt.Fprintf(s, ": %v", n.Body()) case OBREAK, OCONTINUE, OGOTO, OFALL: if n.Sym() != nil { - mode.Fprintf(s, "%#v %v", n.Op(), n.Sym()) + fmt.Fprintf(s, "%#v %v", n.Op(), n.Sym()) } else { - mode.Fprintf(s, "%#v", n.Op()) + fmt.Fprintf(s, "%#v", n.Op()) } case OLABEL: - mode.Fprintf(s, "%v: ", n.Sym()) + fmt.Fprintf(s, "%v: ", n.Sym()) } if extrablock { @@ -1261,7 +1230,15 @@ func stmtFmt(n Node, s fmt.State, mode FmtMode) { } } -func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { +func exprFmt(n Node, s fmt.State, prec int) { + // NOTE(rsc): This code used to support the text-based + // which was more aggressive about printing full Go syntax + // (for example, an actual loop instead of "for loop"). + // The code is preserved for now in case we want to expand + // any of those shortenings later. Or maybe we will delete + // the code. But for now, keep it. + const exportFormat = false + for { if n == nil { fmt.Fprint(s, "") @@ -1292,20 +1269,20 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { } if prec > nprec { - mode.Fprintf(s, "(%v)", n) + fmt.Fprintf(s, "(%v)", n) return } switch n.Op() { case OPAREN: - mode.Fprintf(s, "(%v)", n.Left()) + fmt.Fprintf(s, "(%v)", n.Left()) case ONIL: fmt.Fprint(s, "nil") case OLITERAL: // this is a bit of a mess - if mode == FErr && n.Sym() != nil { - fmt.Fprint(s, smodeString(n.Sym(), mode)) + if !exportFormat && n.Sym() != nil { + fmt.Fprint(s, smodeString(n.Sym(), FErr)) return } @@ -1314,9 +1291,9 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { // Need parens when type begins with what might // be misinterpreted as a unary operator: * or <-. if n.Type().IsPtr() || (n.Type().IsChan() && n.Type().ChanDir() == types.Crecv) { - mode.Fprintf(s, "(%v)(", n.Type()) + fmt.Fprintf(s, "(%v)(", n.Type()) } else { - mode.Fprintf(s, "%v(", n.Type()) + fmt.Fprintf(s, "%v(", n.Type()) } needUnparen = true } @@ -1342,68 +1319,68 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { } if needUnparen { - mode.Fprintf(s, ")") + fmt.Fprintf(s, ")") } case ODCLFUNC: if sym := n.Sym(); sym != nil { - fmt.Fprint(s, smodeString(sym, mode)) + fmt.Fprint(s, smodeString(sym, FErr)) return } - mode.Fprintf(s, "") + fmt.Fprintf(s, "") case ONAME: // Special case: name used as local variable in export. // _ becomes ~b%d internally; print as _ for export - if mode == FErr && n.Sym() != nil && n.Sym().Name[0] == '~' && n.Sym().Name[1] == 'b' { + if !exportFormat && n.Sym() != nil && n.Sym().Name[0] == '~' && n.Sym().Name[1] == 'b' { fmt.Fprint(s, "_") return } fallthrough case OPACK, ONONAME, OMETHEXPR: - fmt.Fprint(s, smodeString(n.Sym(), mode)) + fmt.Fprint(s, smodeString(n.Sym(), FErr)) case OTYPE: if n.Type() == nil && n.Sym() != nil { - fmt.Fprint(s, smodeString(n.Sym(), mode)) + fmt.Fprint(s, smodeString(n.Sym(), FErr)) return } - mode.Fprintf(s, "%v", n.Type()) + fmt.Fprintf(s, "%v", n.Type()) case OTSLICE: n := n.(*SliceType) if n.DDD { - mode.Fprintf(s, "...%v", n.Elem) + fmt.Fprintf(s, "...%v", n.Elem) } else { - mode.Fprintf(s, "[]%v", n.Elem) // happens before typecheck + fmt.Fprintf(s, "[]%v", n.Elem) // happens before typecheck } case OTARRAY: n := n.(*ArrayType) if n.Len == nil { - mode.Fprintf(s, "[...]%v", n.Elem) + fmt.Fprintf(s, "[...]%v", n.Elem) } else { - mode.Fprintf(s, "[%v]%v", n.Len, n.Elem) + fmt.Fprintf(s, "[%v]%v", n.Len, n.Elem) } case OTMAP: n := n.(*MapType) - mode.Fprintf(s, "map[%v]%v", n.Key, n.Elem) + fmt.Fprintf(s, "map[%v]%v", n.Key, n.Elem) case OTCHAN: n := n.(*ChanType) switch n.Dir { case types.Crecv: - mode.Fprintf(s, "<-chan %v", n.Elem) + fmt.Fprintf(s, "<-chan %v", n.Elem) case types.Csend: - mode.Fprintf(s, "chan<- %v", n.Elem) + fmt.Fprintf(s, "chan<- %v", n.Elem) default: if n.Elem != nil && n.Elem.Op() == OTCHAN && n.Elem.(*ChanType).Dir == types.Crecv { - mode.Fprintf(s, "chan (%v)", n.Elem) + fmt.Fprintf(s, "chan (%v)", n.Elem) } else { - mode.Fprintf(s, "chan %v", n.Elem) + fmt.Fprintf(s, "chan %v", n.Elem) } } @@ -1417,104 +1394,104 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { fmt.Fprint(s, "") case OCLOSURE: - if mode == FErr { + if !exportFormat { fmt.Fprint(s, "func literal") return } if n.Body().Len() != 0 { - mode.Fprintf(s, "%v { %v }", n.Type(), n.Body()) + fmt.Fprintf(s, "%v { %v }", n.Type(), n.Body()) return } - mode.Fprintf(s, "%v { %v }", n.Type(), n.Func().Body()) + fmt.Fprintf(s, "%v { %v }", n.Type(), n.Func().Body()) case OCOMPLIT: - if mode == FErr { + if !exportFormat { if n.Implicit() { - mode.Fprintf(s, "... argument") + fmt.Fprintf(s, "... argument") return } if n.Right() != nil { - mode.Fprintf(s, "%v{%s}", n.Right(), ellipsisIf(n.List().Len() != 0)) + fmt.Fprintf(s, "%v{%s}", n.Right(), ellipsisIf(n.List().Len() != 0)) return } fmt.Fprint(s, "composite literal") return } - mode.Fprintf(s, "(%v{ %.v })", n.Right(), n.List()) + fmt.Fprintf(s, "(%v{ %.v })", n.Right(), n.List()) case OPTRLIT: - mode.Fprintf(s, "&%v", n.Left()) + fmt.Fprintf(s, "&%v", n.Left()) case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT: - if mode == FErr { - mode.Fprintf(s, "%v{%s}", n.Type(), ellipsisIf(n.List().Len() != 0)) + if !exportFormat { + fmt.Fprintf(s, "%v{%s}", n.Type(), ellipsisIf(n.List().Len() != 0)) return } - mode.Fprintf(s, "(%v{ %.v })", n.Type(), n.List()) + fmt.Fprintf(s, "(%v{ %.v })", n.Type(), n.List()) case OKEY: if n.Left() != nil && n.Right() != nil { - mode.Fprintf(s, "%v:%v", n.Left(), n.Right()) + fmt.Fprintf(s, "%v:%v", n.Left(), n.Right()) return } if n.Left() == nil && n.Right() != nil { - mode.Fprintf(s, ":%v", n.Right()) + fmt.Fprintf(s, ":%v", n.Right()) return } if n.Left() != nil && n.Right() == nil { - mode.Fprintf(s, "%v:", n.Left()) + fmt.Fprintf(s, "%v:", n.Left()) return } fmt.Fprint(s, ":") case OSTRUCTKEY: - mode.Fprintf(s, "%v:%v", n.Sym(), n.Left()) + fmt.Fprintf(s, "%v:%v", n.Sym(), n.Left()) case OCALLPART: - exprFmt(n.Left(), s, nprec, mode) + exprFmt(n.Left(), s, nprec) if n.Sym() == nil { fmt.Fprint(s, ".") return } - mode.Fprintf(s, ".%0S", n.Sym()) + fmt.Fprintf(s, ".%0S", n.Sym()) case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: - exprFmt(n.Left(), s, nprec, mode) + exprFmt(n.Left(), s, nprec) if n.Sym() == nil { fmt.Fprint(s, ".") return } - mode.Fprintf(s, ".%0S", n.Sym()) + fmt.Fprintf(s, ".%0S", n.Sym()) case ODOTTYPE, ODOTTYPE2: - exprFmt(n.Left(), s, nprec, mode) + exprFmt(n.Left(), s, nprec) if n.Right() != nil { - mode.Fprintf(s, ".(%v)", n.Right()) + fmt.Fprintf(s, ".(%v)", n.Right()) return } - mode.Fprintf(s, ".(%v)", n.Type()) + fmt.Fprintf(s, ".(%v)", n.Type()) case OINDEX, OINDEXMAP: - exprFmt(n.Left(), s, nprec, mode) - mode.Fprintf(s, "[%v]", n.Right()) + exprFmt(n.Left(), s, nprec) + fmt.Fprintf(s, "[%v]", n.Right()) case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: - exprFmt(n.Left(), s, nprec, mode) + exprFmt(n.Left(), s, nprec) fmt.Fprint(s, "[") low, high, max := n.SliceBounds() if low != nil { - fmt.Fprint(s, modeString(low, mode)) + fmt.Fprint(s, low) } fmt.Fprint(s, ":") if high != nil { - fmt.Fprint(s, modeString(high, mode)) + fmt.Fprint(s, high) } if n.Op().IsSlice3() { fmt.Fprint(s, ":") if max != nil { - fmt.Fprint(s, modeString(max, mode)) + fmt.Fprint(s, max) } } fmt.Fprint(s, "]") @@ -1523,13 +1500,13 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { if n.List().Len() != 2 { base.Fatalf("bad OSLICEHEADER list length %d", n.List().Len()) } - mode.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left(), n.List().First(), n.List().Second()) + fmt.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left(), n.List().First(), n.List().Second()) case OCOMPLEX, OCOPY: if n.Left() != nil { - mode.Fprintf(s, "%#v(%v, %v)", n.Op(), n.Left(), n.Right()) + fmt.Fprintf(s, "%#v(%v, %v)", n.Op(), n.Left(), n.Right()) } else { - mode.Fprintf(s, "%#v(%.v)", n.Op(), n.List()) + fmt.Fprintf(s, "%#v(%.v)", n.Op(), n.List()) } case OCONV, @@ -1541,14 +1518,14 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { OSTR2RUNES, ORUNESTR: if n.Type() == nil || n.Type().Sym() == nil { - mode.Fprintf(s, "(%v)", n.Type()) + fmt.Fprintf(s, "(%v)", n.Type()) } else { - mode.Fprintf(s, "%v", n.Type()) + fmt.Fprintf(s, "%v", n.Type()) } if n.Left() != nil { - mode.Fprintf(s, "(%v)", n.Left()) + fmt.Fprintf(s, "(%v)", n.Left()) } else { - mode.Fprintf(s, "(%.v)", n.List()) + fmt.Fprintf(s, "(%.v)", n.List()) } case OREAL, @@ -1568,48 +1545,48 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { OPRINT, OPRINTN: if n.Left() != nil { - mode.Fprintf(s, "%#v(%v)", n.Op(), n.Left()) + fmt.Fprintf(s, "%#v(%v)", n.Op(), n.Left()) return } if n.IsDDD() { - mode.Fprintf(s, "%#v(%.v...)", n.Op(), n.List()) + fmt.Fprintf(s, "%#v(%.v...)", n.Op(), n.List()) return } - mode.Fprintf(s, "%#v(%.v)", n.Op(), n.List()) + fmt.Fprintf(s, "%#v(%.v)", n.Op(), n.List()) case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG: - exprFmt(n.Left(), s, nprec, mode) + exprFmt(n.Left(), s, nprec) if n.IsDDD() { - mode.Fprintf(s, "(%.v...)", n.List()) + fmt.Fprintf(s, "(%.v...)", n.List()) return } - mode.Fprintf(s, "(%.v)", n.List()) + fmt.Fprintf(s, "(%.v)", n.List()) case OMAKEMAP, OMAKECHAN, OMAKESLICE: if n.List().Len() != 0 { // pre-typecheck - mode.Fprintf(s, "make(%v, %.v)", n.Type(), n.List()) + fmt.Fprintf(s, "make(%v, %.v)", n.Type(), n.List()) return } if n.Right() != nil { - mode.Fprintf(s, "make(%v, %v, %v)", n.Type(), n.Left(), n.Right()) + fmt.Fprintf(s, "make(%v, %v, %v)", n.Type(), n.Left(), n.Right()) return } if n.Left() != nil && (n.Op() == OMAKESLICE || !n.Left().Type().IsUntyped()) { - mode.Fprintf(s, "make(%v, %v)", n.Type(), n.Left()) + fmt.Fprintf(s, "make(%v, %v)", n.Type(), n.Left()) return } - mode.Fprintf(s, "make(%v)", n.Type()) + fmt.Fprintf(s, "make(%v)", n.Type()) case OMAKESLICECOPY: - mode.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type(), n.Left(), n.Right()) + fmt.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type(), n.Left(), n.Right()) case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV: // Unary - mode.Fprintf(s, "%#v", n.Op()) + fmt.Fprintf(s, "%#v", n.Op()) if n.Left() != nil && n.Left().Op() == n.Op() { fmt.Fprint(s, " ") } - exprFmt(n.Left(), s, nprec+1, mode) + exprFmt(n.Left(), s, nprec+1) // Binary case OADD, @@ -1632,19 +1609,19 @@ func exprFmt(n Node, s fmt.State, prec int, mode FmtMode) { OSEND, OSUB, OXOR: - exprFmt(n.Left(), s, nprec, mode) - mode.Fprintf(s, " %#v ", n.Op()) - exprFmt(n.Right(), s, nprec+1, mode) + exprFmt(n.Left(), s, nprec) + fmt.Fprintf(s, " %#v ", n.Op()) + exprFmt(n.Right(), s, nprec+1) case OADDSTR: for i, n1 := range n.List().Slice() { if i != 0 { fmt.Fprint(s, " + ") } - exprFmt(n1, s, nprec, mode) + exprFmt(n1, s, nprec) } default: - mode.Fprintf(s, "", n.Op()) + fmt.Fprintf(s, "", n.Op()) } } @@ -1657,45 +1634,25 @@ func ellipsisIf(b bool) string { // Nodes -type fmtNodes struct { - x Nodes - m FmtMode -} - -func (f *fmtNodes) Format(s fmt.State, verb rune) { f.x.format(s, verb, FErr) } - -func (l Nodes) Format(s fmt.State, verb rune) { l.format(s, verb, FErr) } - -func (l Nodes) format(s fmt.State, verb rune, mode FmtMode) { +func (l Nodes) Format(s fmt.State, verb rune) { if s.Flag('+') && verb == 'v' { // %+v is DumpList output dumpNodes(s, l, 1) return } - switch verb { - case 'v': - l.hconv(s, fmtFlag(s, verb), mode) - - default: + if verb != 'v' { fmt.Fprintf(s, "%%!%c(Nodes)", verb) + return } -} -func (n Nodes) String() string { - return fmt.Sprint(n) -} - -// Flags: all those of %N plus '.': separate with comma's instead of semicolons. -func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode FmtMode) { - flag, mode = flag.update(mode) sep := "; " - if flag&FmtComma != 0 { + if _, ok := s.Precision(); ok { // %.v is expr list sep = ", " } for i, n := range l.Slice() { - fmt.Fprint(s, modeString(n, mode)) + fmt.Fprint(s, n) if i+1 < l.Len() { fmt.Fprint(s, sep) } From fb17dfa43d1c8e08d08f380ea082195d1c4f89f4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 5 Dec 2020 15:20:51 -0500 Subject: [PATCH 170/212] [dev.regabi] cmd/compile: narrow interface between ir and types Narrow the interface between package ir and package types to make it easier to clean up the type formatting code all in one place. Also introduce ir.BlankSym for use by OrigSym, so that later OrigSym can move to package types without needing to reference a variable of type ir.Node. Passes buildall w/ toolstash -cmp. Change-Id: I39fa419a1c8fb3318203e31cacc8d06399deeff9 Reviewed-on: https://go-review.googlesource.com/c/go/+/275776 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/main.go | 5 --- src/cmd/compile/internal/gc/universe.go | 1 + src/cmd/compile/internal/ir/fmt.go | 25 ++++++++------ src/cmd/compile/internal/ir/node.go | 4 ++- src/cmd/compile/internal/ssa/export_test.go | 15 +-------- src/cmd/compile/internal/types/scope.go | 7 ++-- src/cmd/compile/internal/types/sym.go | 5 +-- src/cmd/compile/internal/types/type.go | 28 ++++++++-------- src/cmd/compile/internal/types/utils.go | 36 +++++++++------------ 9 files changed, 59 insertions(+), 67 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 96031fe511..a40671bccf 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -212,15 +212,10 @@ func Main(archInit func(*Arch)) { // would lead to import cycles) types.Widthptr = Widthptr types.Dowidth = dowidth - types.Fatalf = base.Fatalf ir.InstallTypeFormats() types.TypeLinkSym = func(t *types.Type) *obj.LSym { return typenamesym(t).Linksym() } - types.FmtLeft = int(ir.FmtLeft) - types.FmtUnsigned = int(ir.FmtUnsigned) - types.FErr = int(ir.FErr) - types.Ctxt = base.Ctxt initUniverse() diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index f9984cbe94..cd68719a99 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -182,6 +182,7 @@ func initUniverse() { ir.AsNode(s.Def).SetSym(lookup("false")) s = lookup("_") + ir.BlankSym = s s.Block = -100 s.Def = NewName(s) types.Types[types.TBLANK] = types.New(types.TBLANK) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index b0c732ae56..88534864a9 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -339,7 +339,8 @@ func symFormat(s *types.Sym, f fmt.State, verb rune, mode FmtMode) { func smodeString(s *types.Sym, mode FmtMode) string { return sconv(s, 0, mode) } -// See #16897 before changing the implementation of sconv. +// See #16897 for details about performance implications +// before changing the implementation of sconv. func sconv(s *types.Sym, flag FmtFlag, mode FmtMode) string { if flag&FmtLong != 0 { panic("linksymfmt") @@ -472,17 +473,23 @@ var fmtBufferPool = sync.Pool{ } func InstallTypeFormats() { - types.Sconv = func(s *types.Sym, flag, mode int) string { - return sconv(s, FmtFlag(flag), FmtMode(mode)) + types.SymString = func(s *types.Sym) string { + return sconv(s, 0, FErr) } - types.Tconv = func(t *types.Type, flag, mode int) string { - return tconv(t, FmtFlag(flag), FmtMode(mode)) + types.TypeString = func(t *types.Type) string { + return tconv(t, 0, FErr) } - types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) { - symFormat(sym, s, verb, FmtMode(mode)) + types.TypeShortString = func(t *types.Type) string { + return tconv(t, FmtLeft, FErr) } - types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) { - typeFormat(t, s, verb, FmtMode(mode)) + types.TypeLongString = func(t *types.Type) string { + return tconv(t, FmtLeft|FmtUnsigned, FErr) + } + types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune) { + symFormat(sym, s, verb, FErr) + } + types.FormatType = func(t *types.Type, s fmt.State, verb rune) { + typeFormat(t, s, verb, FErr) } } diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 83f5b0cf78..56b320e726 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -654,6 +654,8 @@ func AsNode(n types.Object) Node { var BlankNode Node +var BlankSym *types.Sym + // origSym returns the original symbol written by the user. func OrigSym(s *types.Sym) *types.Sym { if s == nil { @@ -666,7 +668,7 @@ func OrigSym(s *types.Sym) *types.Sym { return nil case 'b': // originally the blank identifier _ // TODO(mdempsky): Does s.Pkg matter here? - return BlankNode.Sym() + return BlankSym } return s } diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index 5a81f76ceb..cb3b9c0e2a 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -12,7 +12,6 @@ import ( "cmd/internal/obj/s390x" "cmd/internal/obj/x86" "cmd/internal/src" - "fmt" "testing" ) @@ -138,19 +137,7 @@ func init() { // Initialize just enough of the universe and the types package to make our tests function. // TODO(josharian): move universe initialization to the types package, // so this test setup can share it. - - types.Tconv = func(t *types.Type, flag, mode int) string { - return t.Kind().String() - } - types.Sconv = func(s *types.Sym, flag, mode int) string { - return "sym" - } - types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) { - fmt.Fprintf(s, "sym") - } - types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) { - fmt.Fprintf(s, "%v", t.Kind()) - } + ir.InstallTypeFormats() types.Dowidth = func(t *types.Type) {} for _, typ := range [...]struct { diff --git a/src/cmd/compile/internal/types/scope.go b/src/cmd/compile/internal/types/scope.go index 37ac90a025..04ea3c325f 100644 --- a/src/cmd/compile/internal/types/scope.go +++ b/src/cmd/compile/internal/types/scope.go @@ -4,7 +4,10 @@ package types -import "cmd/internal/src" +import ( + "cmd/compile/internal/base" + "cmd/internal/src" +) // Declaration stack & operations @@ -56,7 +59,7 @@ func Popdcl() { d.sym = nil d.def = nil } - Fatalf("popdcl: no stack mark") + base.Fatalf("popdcl: no stack mark") } // Markdcl records the start of a new block scope for declarations. diff --git a/src/cmd/compile/internal/types/sym.go b/src/cmd/compile/internal/types/sym.go index 490222d843..fcb095c53c 100644 --- a/src/cmd/compile/internal/types/sym.go +++ b/src/cmd/compile/internal/types/sym.go @@ -5,6 +5,7 @@ package types import ( + "cmd/compile/internal/base" "cmd/internal/obj" "cmd/internal/src" "unicode" @@ -88,9 +89,9 @@ func (sym *Sym) Linksym() *obj.LSym { } if sym.Func() { // This is a function symbol. Mark it as "internal ABI". - return Ctxt.LookupABIInit(sym.LinksymName(), obj.ABIInternal, initPkg) + return base.Ctxt.LookupABIInit(sym.LinksymName(), obj.ABIInternal, initPkg) } - return Ctxt.LookupInit(sym.LinksymName(), initPkg) + return base.Ctxt.LookupInit(sym.LinksymName(), initPkg) } // Less reports whether symbol a is ordered before symbol b. diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 2c42e5579d..c5807af199 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -231,7 +231,7 @@ func (t *Type) Pkg() *Pkg { case TINTER: return t.Extra.(*Interface).pkg default: - Fatalf("Pkg: unexpected kind: %v", t) + base.Fatalf("Pkg: unexpected kind: %v", t) return nil } } @@ -501,7 +501,7 @@ func New(et Kind) *Type { // NewArray returns a new fixed-length array Type. func NewArray(elem *Type, bound int64) *Type { if bound < 0 { - Fatalf("NewArray: invalid bound %v", bound) + base.Fatalf("NewArray: invalid bound %v", bound) } t := New(TARRAY) t.Extra = &Array{Elem: elem, Bound: bound} @@ -513,7 +513,7 @@ func NewArray(elem *Type, bound int64) *Type { func NewSlice(elem *Type) *Type { if t := elem.cache.slice; t != nil { if t.Elem() != elem { - Fatalf("elem mismatch") + base.Fatalf("elem mismatch") } return t } @@ -569,12 +569,12 @@ var NewPtrCacheEnabled = true // NewPtr returns the pointer type pointing to t. func NewPtr(elem *Type) *Type { if elem == nil { - Fatalf("NewPtr: pointer to elem Type is nil") + base.Fatalf("NewPtr: pointer to elem Type is nil") } if t := elem.cache.ptr; t != nil { if t.Elem() != elem { - Fatalf("NewPtr: elem mismatch") + base.Fatalf("NewPtr: elem mismatch") } return t } @@ -629,7 +629,7 @@ func SubstAny(t *Type, types *[]*Type) *Type { case TANY: if len(*types) == 0 { - Fatalf("substArgTypes: not enough argument types") + base.Fatalf("substArgTypes: not enough argument types") } t = (*types)[0] *types = (*types)[1:] @@ -730,7 +730,7 @@ func (t *Type) copy() *Type { x := *t.Extra.(*Array) nt.Extra = &x case TTUPLE, TSSA, TRESULTS: - Fatalf("ssa types cannot be copied") + base.Fatalf("ssa types cannot be copied") } // TODO(mdempsky): Find out why this is necessary and explain. if t.underlying == t { @@ -746,7 +746,7 @@ func (f *Field) Copy() *Field { func (t *Type) wantEtype(et Kind) { if t.kind != et { - Fatalf("want %v, but have %v", et, t) + base.Fatalf("want %v, but have %v", et, t) } } @@ -811,7 +811,7 @@ func (t *Type) Elem() *Type { case TMAP: return t.Extra.(*Map).Elem } - Fatalf("Type.Elem %s", t.kind) + base.Fatalf("Type.Elem %s", t.kind) return nil } @@ -850,7 +850,7 @@ func (t *Type) Fields() *Fields { Dowidth(t) return &t.Extra.(*Interface).Fields } - Fatalf("Fields: type %v does not have fields", t) + base.Fatalf("Fields: type %v does not have fields", t) return nil } @@ -874,7 +874,7 @@ func (t *Type) SetFields(fields []*Field) { // enforce that SetFields cannot be called once // t's width has been calculated. if t.WidthCalculated() { - Fatalf("SetFields of %v: width previously calculated", t) + base.Fatalf("SetFields of %v: width previously calculated", t) } t.wantEtype(TSTRUCT) for _, f := range fields { @@ -1223,7 +1223,7 @@ var unsignedEType = [...]Kind{ // ToUnsigned returns the unsigned equivalent of integer type t. func (t *Type) ToUnsigned() *Type { if !t.IsInteger() { - Fatalf("unsignedType(%v)", t) + base.Fatalf("unsignedType(%v)", t) } return Types[unsignedEType[t.kind]] } @@ -1385,7 +1385,7 @@ func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 { switch t.kind { case TSTRUCT: if t.IsFuncArgStruct() { - Fatalf("NumComponents func arg struct") + base.Fatalf("NumComponents func arg struct") } var n int64 for _, f := range t.FieldSlice() { @@ -1408,7 +1408,7 @@ func (t *Type) SoleComponent() *Type { switch t.kind { case TSTRUCT: if t.IsFuncArgStruct() { - Fatalf("SoleComponent func arg struct") + base.Fatalf("SoleComponent func arg struct") } if t.NumFields() != 1 { return nil diff --git a/src/cmd/compile/internal/types/utils.go b/src/cmd/compile/internal/types/utils.go index e8b1073818..a1be77eef1 100644 --- a/src/cmd/compile/internal/types/utils.go +++ b/src/cmd/compile/internal/types/utils.go @@ -15,51 +15,47 @@ const BADWIDTH = -1000000000 // They are here to break import cycles. // TODO(gri) eliminate these dependencies. var ( - Widthptr int - Dowidth func(*Type) - Fatalf func(string, ...interface{}) - Sconv func(*Sym, int, int) string // orig: func sconv(s *Sym, flag FmtFlag, mode fmtMode) string - Tconv func(*Type, int, int) string // orig: func tconv(t *Type, flag FmtFlag, mode fmtMode) string - FormatSym func(*Sym, fmt.State, rune, int) // orig: func symFormat(sym *Sym, s fmt.State, verb rune, mode fmtMode) - FormatType func(*Type, fmt.State, rune, int) // orig: func typeFormat(t *Type, s fmt.State, verb rune, mode fmtMode) - TypeLinkSym func(*Type) *obj.LSym - Ctxt *obj.Link - - FmtLeft int - FmtUnsigned int - FErr int + Widthptr int + Dowidth func(*Type) + SymString func(*Sym) string + TypeString func(*Type) string + TypeShortString func(*Type) string + TypeLongString func(*Type) string + FormatSym func(*Sym, fmt.State, rune) + FormatType func(*Type, fmt.State, rune) + TypeLinkSym func(*Type) *obj.LSym ) func (s *Sym) String() string { - return Sconv(s, 0, FErr) + return SymString(s) } func (sym *Sym) Format(s fmt.State, verb rune) { - FormatSym(sym, s, verb, FErr) + FormatSym(sym, s, verb) } func (t *Type) String() string { - // The implementation of tconv (including typefmt and fldconv) + // The implementation // must handle recursive types correctly. - return Tconv(t, 0, FErr) + return TypeString(t) } // ShortString generates a short description of t. // It is used in autogenerated method names, reflection, // and itab names. func (t *Type) ShortString() string { - return Tconv(t, FmtLeft, FErr) + return TypeShortString(t) } // LongString generates a complete description of t. // It is useful for reflection, // or when a unique fingerprint or hash of a type is required. func (t *Type) LongString() string { - return Tconv(t, FmtLeft|FmtUnsigned, FErr) + return TypeLongString(t) } func (t *Type) Format(s fmt.State, verb rune) { - FormatType(t, s, verb, FErr) + FormatType(t, s, verb) } type bitset8 uint8 From 3904a6282945276ec72683920c278b2e3141a1fe Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 6 Dec 2020 12:38:11 -0500 Subject: [PATCH 171/212] [dev.regabi] cmd/compile: remove mode.Sprintf etc in printer This code is now hardly used and not worth the complexity. It also tangles together Nodes and Types in a way that keeps this code in package ir instead of package types. Passes buildall w/ toolstash -cmp. Change-Id: I2e829c1f6b602acbdc8ab4aac3b798f9ded762ef Reviewed-on: https://go-review.googlesource.com/c/go/+/275777 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/fmtmap_test.go | 1 - src/cmd/compile/internal/ir/fmt.go | 111 +++++++++-------------------- 2 files changed, 32 insertions(+), 80 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index 60b772e932..5dd30e619b 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -43,7 +43,6 @@ var knownFormats = map[string]string{ "*cmd/compile/internal/types.Field %p": "", "*cmd/compile/internal/types.Field %v": "", "*cmd/compile/internal/types.Sym %+v": "", - "*cmd/compile/internal/types.Sym %0S": "", "*cmd/compile/internal/types.Sym %S": "", "*cmd/compile/internal/types.Sym %p": "", "*cmd/compile/internal/types.Sym %v": "", diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 88534864a9..0bd0340af8 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -152,38 +152,6 @@ func (f FmtFlag) update(mode FmtMode) (FmtFlag, FmtMode) { return f, mode } -func (m FmtMode) Fprintf(s fmt.State, format string, args ...interface{}) { - m.prepareArgs(args) - fmt.Fprintf(s, format, args...) -} - -func (m FmtMode) Sprintf(format string, args ...interface{}) string { - m.prepareArgs(args) - return fmt.Sprintf(format, args...) -} - -func (m FmtMode) Sprint(args ...interface{}) string { - m.prepareArgs(args) - return fmt.Sprint(args...) -} - -func (m FmtMode) prepareArgs(args []interface{}) { - for i, arg := range args { - switch arg := arg.(type) { - case nil: - args[i] = "" // assume this was a node interface - case *types.Type: - args[i] = &fmtType{arg, m} - case *types.Sym: - args[i] = &fmtSym{arg, m} - case int32, int64, string, Op, Node, Nodes, types.Kind, constant.Value: - // OK: printing these types doesn't depend on mode - default: - base.Fatalf("mode.prepareArgs type %T", arg) - } - } -} - // Op var OpNames = []string{ @@ -316,15 +284,9 @@ func FmtConst(v constant.Value, flag FmtFlag) string { // the same name appears in an error message. var NumImport = make(map[string]int) -type fmtSym struct { - x *types.Sym - m FmtMode -} - -func (f *fmtSym) Format(s fmt.State, verb rune) { symFormat(f.x, s, verb, f.m) } - // "%S" suppresses qualifying with package -func symFormat(s *types.Sym, f fmt.State, verb rune, mode FmtMode) { +func symFormat(s *types.Sym, f fmt.State, verb rune) { + mode := FErr switch verb { case 'v', 'S': if verb == 'v' && f.Flag('+') { @@ -337,8 +299,6 @@ func symFormat(s *types.Sym, f fmt.State, verb rune, mode FmtMode) { } } -func smodeString(s *types.Sym, mode FmtMode) string { return sconv(s, 0, mode) } - // See #16897 for details about performance implications // before changing the implementation of sconv. func sconv(s *types.Sym, flag FmtFlag, mode FmtMode) string { @@ -421,25 +381,22 @@ func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { } if flag&FmtByte != 0 { - // FmtByte (hh) implies FmtShort (h) - // skip leading "type." in method name - name := s.Name - if i := strings.LastIndex(name, "."); i >= 0 { - name = name[i+1:] - } - - if mode == FDbg { - fmt.Fprintf(b, "@%q.%s", s.Pkg.Path, name) - return - } - - b.WriteString(name) + b.WriteString(methodSymName(s)) return } b.WriteString(s.Name) } +func methodSymName(s *types.Sym) string { + // Skip leading "type." in method name + name := s.Name + if i := strings.LastIndex(name, "."); i >= 0 { + name = name[i+1:] + } + return name +} + // Type var BasicTypeNames = []string{ @@ -485,24 +442,14 @@ func InstallTypeFormats() { types.TypeLongString = func(t *types.Type) string { return tconv(t, FmtLeft|FmtUnsigned, FErr) } - types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune) { - symFormat(sym, s, verb, FErr) - } - types.FormatType = func(t *types.Type, s fmt.State, verb rune) { - typeFormat(t, s, verb, FErr) - } + types.FormatSym = symFormat + types.FormatType = typeFormat } -type fmtType struct { - x *types.Type - m FmtMode -} - -func (f *fmtType) Format(s fmt.State, verb rune) { typeFormat(f.x, s, verb, f.m) } - // "%L" print definition, not name // "%S" omit 'func' and receiver from function types, short type names -func typeFormat(t *types.Type, s fmt.State, verb rune, mode FmtMode) { +func typeFormat(t *types.Type, s fmt.State, verb rune) { + mode := FErr switch verb { case 'v', 'S', 'L': if verb == 'v' && s.Flag('+') { // %+v is debug format @@ -599,7 +546,8 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited } if t.Sym().Pkg == LocalPkg && t.Vargen != 0 { - b.WriteString(mode.Sprintf("%v·%d", t.Sym(), t.Vargen)) + sconv2(b, t.Sym(), 0, mode) + fmt.Fprintf(b, "·%d", t.Vargen) return } } @@ -818,9 +766,14 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited case types.Txxx: b.WriteString("Txxx") + default: - // Don't know how to handle - fall back to detailed prints. - b.WriteString(mode.Sprintf("%v <%v>", t.Kind(), t.Sym())) + // Don't know how to handle - fall back to detailed prints + b.WriteString(t.Kind().String()) + b.WriteString(" <") + sconv2(b, t.Sym(), 0, mode) + b.WriteString(">") + } } @@ -847,12 +800,12 @@ func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visite if funarg != types.FunargNone { name = fmt.Sprint(f.Nname) } else if flag&FmtLong != 0 { - name = mode.Sprintf("%0S", s) + name = methodSymName(s) if !types.IsExported(name) && flag&FmtUnsigned == 0 { - name = smodeString(s, mode) // qualify non-exported names (used on structs, not on funarg) + name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg) } } else { - name = smodeString(s, mode) + name = sconv(s, 0, mode) } } } @@ -1289,7 +1242,7 @@ func exprFmt(n Node, s fmt.State, prec int) { case OLITERAL: // this is a bit of a mess if !exportFormat && n.Sym() != nil { - fmt.Fprint(s, smodeString(n.Sym(), FErr)) + fmt.Fprint(s, n.Sym()) return } @@ -1331,7 +1284,7 @@ func exprFmt(n Node, s fmt.State, prec int) { case ODCLFUNC: if sym := n.Sym(); sym != nil { - fmt.Fprint(s, smodeString(sym, FErr)) + fmt.Fprint(s, sym) return } fmt.Fprintf(s, "") @@ -1345,11 +1298,11 @@ func exprFmt(n Node, s fmt.State, prec int) { } fallthrough case OPACK, ONONAME, OMETHEXPR: - fmt.Fprint(s, smodeString(n.Sym(), FErr)) + fmt.Fprint(s, n.Sym()) case OTYPE: if n.Type() == nil && n.Sym() != nil { - fmt.Fprint(s, smodeString(n.Sym(), FErr)) + fmt.Fprint(s, n.Sym()) return } fmt.Fprintf(s, "%v", n.Type()) From 70155cca81d061686d4f23b7ad59fe8213e87f9f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 6 Dec 2020 13:17:03 -0500 Subject: [PATCH 172/212] [dev.regabi] cmd/compile: untangle FmtFlag, FmtMode It turns out that the FmtFlag is really only tracking the FmtLong and FmtShort bits, and the others simply mirror the state of the FmtMode and are copied out and back in repeatedly. Simplify to FmtFlag being the verb itself ('S', 'L', or 'v'). Now there is only one formatting enumeration, making it a bit easier to understand what's going on. Passes buildall w/ toolstash -cmp. Change-Id: I85bde2183eb22228fcf46d19d003401d588d9825 Reviewed-on: https://go-review.googlesource.com/c/go/+/275778 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/const.go | 2 +- src/cmd/compile/internal/ir/fmt.go | 181 ++++++++------------------- 2 files changed, 53 insertions(+), 130 deletions(-) diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 6cd414a419..304c9aa2c3 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -384,7 +384,7 @@ func overflow(v constant.Value, t *types.Type) bool { return true } if doesoverflow(v, t) { - base.Errorf("constant %v overflows %v", ir.FmtConst(v, 0), t) + base.Errorf("constant %v overflows %v", ir.FmtConst(v, false), t) return true } return false diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 0bd0340af8..117c7417d2 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -88,70 +88,6 @@ const ( FTypeIdName // same as FTypeId, but use package name instead of prefix ) -// A FmtFlag value is a set of flags (or 0). -// They control how the Xconv functions format their values. -// See the respective function's documentation for details. -type FmtFlag int - -const ( // fmt.Format flag/prec or verb - FmtLeft FmtFlag = 1 << iota // '-' - FmtSharp // '#' - FmtSign // '+' - FmtUnsigned // internal use only (historic: u flag) - FmtShort // verb == 'S' (historic: h flag) - FmtLong // verb == 'L' (historic: l flag) - FmtComma // '.' (== hasPrec) (historic: , flag) - FmtByte // '0' (historic: hh flag) -) - -// fmtFlag computes the (internal) FmtFlag -// value given the fmt.State and format verb. -func fmtFlag(s fmt.State, verb rune) FmtFlag { - var flag FmtFlag - if s.Flag('-') { - flag |= FmtLeft - } - if s.Flag('#') { - flag |= FmtSharp - } - if s.Flag('+') { - flag |= FmtSign - } - if s.Flag(' ') { - base.Fatalf("FmtUnsigned in format string") - } - if _, ok := s.Precision(); ok { - flag |= FmtComma - } - if s.Flag('0') { - flag |= FmtByte - } - switch verb { - case 'S': - flag |= FmtShort - case 'L': - flag |= FmtLong - } - return flag -} - -// update returns the results of applying f to mode. -func (f FmtFlag) update(mode FmtMode) (FmtFlag, FmtMode) { - switch { - case f&FmtSign != 0: - mode = FDbg - case f&FmtSharp != 0: - // ignore (textual export format no longer supported) - case f&FmtUnsigned != 0: - mode = FTypeIdName - case f&FmtLeft != 0: - mode = FTypeId - } - - f &^= FmtSharp | FmtLeft | FmtSign - return f, mode -} - // Op var OpNames = []string{ @@ -243,8 +179,8 @@ func (o Op) Format(s fmt.State, verb rune) { // Val -func FmtConst(v constant.Value, flag FmtFlag) string { - if flag&FmtSharp == 0 && v.Kind() == constant.Complex { +func FmtConst(v constant.Value, sharp bool) string { + if !sharp && v.Kind() == constant.Complex { real, imag := constant.Real(v), constant.Imag(v) var re string @@ -292,7 +228,7 @@ func symFormat(s *types.Sym, f fmt.State, verb rune) { if verb == 'v' && f.Flag('+') { mode = FDbg } - fmt.Fprint(f, sconv(s, fmtFlag(f, verb), mode)) + fmt.Fprint(f, sconv(s, verb, mode)) default: fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s) @@ -301,8 +237,8 @@ func symFormat(s *types.Sym, f fmt.State, verb rune) { // See #16897 for details about performance implications // before changing the implementation of sconv. -func sconv(s *types.Sym, flag FmtFlag, mode FmtMode) string { - if flag&FmtLong != 0 { +func sconv(s *types.Sym, verb rune, mode FmtMode) string { + if verb == 'L' { panic("linksymfmt") } @@ -317,13 +253,12 @@ func sconv(s *types.Sym, flag FmtFlag, mode FmtMode) string { buf.Reset() defer fmtBufferPool.Put(buf) - flag, mode = flag.update(mode) - symfmt(buf, s, flag, mode) + symfmt(buf, s, verb, mode) return types.InternString(buf.Bytes()) } -func sconv2(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { - if flag&FmtLong != 0 { +func sconv2(b *bytes.Buffer, s *types.Sym, verb rune, mode FmtMode) { + if verb == 'L' { panic("linksymfmt") } if s == nil { @@ -335,12 +270,11 @@ func sconv2(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { return } - flag, mode = flag.update(mode) - symfmt(b, s, flag, mode) + symfmt(b, s, verb, mode) } -func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { - if flag&FmtShort == 0 { +func symfmt(b *bytes.Buffer, s *types.Sym, verb rune, mode FmtMode) { + if verb != 'S' { switch mode { case FErr: // This is for the user if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg { @@ -380,11 +314,6 @@ func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { } } - if flag&FmtByte != 0 { - b.WriteString(methodSymName(s)) - return - } - b.WriteString(s.Name) } @@ -437,10 +366,10 @@ func InstallTypeFormats() { return tconv(t, 0, FErr) } types.TypeShortString = func(t *types.Type) string { - return tconv(t, FmtLeft, FErr) + return tconv(t, 0, FTypeId) } types.TypeLongString = func(t *types.Type) string { - return tconv(t, FmtLeft|FmtUnsigned, FErr) + return tconv(t, 0, FTypeIdName) } types.FormatSym = symFormat types.FormatType = typeFormat @@ -455,18 +384,21 @@ func typeFormat(t *types.Type, s fmt.State, verb rune) { if verb == 'v' && s.Flag('+') { // %+v is debug format mode = FDbg } - fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode)) + if verb == 'S' && s.Flag('-') { // %-S is special case for receiver - short typeid format + mode = FTypeId + } + fmt.Fprint(s, tconv(t, verb, mode)) default: fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t) } } -func tconv(t *types.Type, flag FmtFlag, mode FmtMode) string { +func tconv(t *types.Type, verb rune, mode FmtMode) string { buf := fmtBufferPool.Get().(*bytes.Buffer) buf.Reset() defer fmtBufferPool.Put(buf) - tconv2(buf, t, flag, mode, nil) + tconv2(buf, t, verb, mode, nil) return types.InternString(buf.Bytes()) } @@ -474,7 +406,7 @@ func tconv(t *types.Type, flag FmtFlag, mode FmtMode) string { // flag and mode control exactly what is printed. // Any types x that are already in the visited map get printed as @%d where %d=visited[x]. // See #16897 before changing the implementation of tconv. -func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited map[*types.Type]int) { +func tconv2(b *bytes.Buffer, t *types.Type, verb rune, mode FmtMode, visited map[*types.Type]int) { if off, ok := visited[t]; ok { // We've seen this type before, so we're trying to print it recursively. // Print a reference to it instead. @@ -507,17 +439,13 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited return } - flag, mode = flag.update(mode) - if mode == FTypeIdName { - flag |= FmtUnsigned - } if t == types.ByteType || t == types.RuneType { // in %-T mode collapse rune and byte with their originals. switch mode { case FTypeIdName, FTypeId: t = types.Types[t.Kind()] default: - sconv2(b, t.Sym(), FmtShort, mode) + sconv2(b, t.Sym(), 'S', mode) return } } @@ -527,32 +455,32 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited } // Unless the 'L' flag was specified, if the type has a name, just print that name. - if flag&FmtLong == 0 && t.Sym() != nil && t != types.Types[t.Kind()] { + if verb != 'L' && t.Sym() != nil && t != types.Types[t.Kind()] { switch mode { case FTypeId, FTypeIdName: - if flag&FmtShort != 0 { + if verb == 'S' { if t.Vargen != 0 { - sconv2(b, t.Sym(), FmtShort, mode) + sconv2(b, t.Sym(), 'S', mode) fmt.Fprintf(b, "·%d", t.Vargen) return } - sconv2(b, t.Sym(), FmtShort, mode) + sconv2(b, t.Sym(), 'S', mode) return } if mode == FTypeIdName { - sconv2(b, t.Sym(), FmtUnsigned, mode) + sconv2(b, t.Sym(), 'v', FTypeIdName) return } if t.Sym().Pkg == LocalPkg && t.Vargen != 0 { - sconv2(b, t.Sym(), 0, mode) + sconv2(b, t.Sym(), 'v', mode) fmt.Fprintf(b, "·%d", t.Vargen) return } } - sconv2(b, t.Sym(), 0, mode) + sconv2(b, t.Sym(), 'v', mode) return } @@ -581,7 +509,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited if mode == FDbg { b.WriteString(t.Kind().String()) b.WriteByte('-') - tconv2(b, t, flag, FErr, visited) + tconv2(b, t, 'v', FErr, visited) return } @@ -603,12 +531,12 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited b.WriteByte('*') switch mode { case FTypeId, FTypeIdName: - if flag&FmtShort != 0 { - tconv2(b, t.Elem(), FmtShort, mode, visited) + if verb == 'S' { + tconv2(b, t.Elem(), 'S', mode, visited) return } } - tconv2(b, t.Elem(), 0, mode, visited) + tconv2(b, t.Elem(), 'v', mode, visited) case types.TARRAY: b.WriteByte('[') @@ -662,15 +590,14 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited // Wrong interface definitions may have types lacking a symbol. break case types.IsExported(f.Sym.Name): - sconv2(b, f.Sym, FmtShort, mode) + sconv2(b, f.Sym, 'S', mode) default: - flag1 := FmtLeft - if flag&FmtUnsigned != 0 { - flag1 = FmtUnsigned + if mode != FTypeIdName { + mode = FTypeId } - sconv2(b, f.Sym, flag1, mode) + sconv2(b, f.Sym, 'v', mode) } - tconv2(b, f.Type, FmtShort, mode, visited) + tconv2(b, f.Type, 'S', mode, visited) } if t.NumFields() != 0 { b.WriteByte(' ') @@ -678,7 +605,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited b.WriteByte('}') case types.TFUNC: - if flag&FmtShort != 0 { + if verb == 'S' { // no leading func } else { if t.Recv() != nil { @@ -726,17 +653,17 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited if funarg := t.StructType().Funarg; funarg != types.FunargNone { b.WriteByte('(') - var flag1 FmtFlag + fieldVerb := 'v' switch mode { case FTypeId, FTypeIdName, FErr: // no argument names on function signature, and no "noescape"/"nosplit" tags - flag1 = FmtShort + fieldVerb = 'S' } for i, f := range t.Fields().Slice() { if i != 0 { b.WriteString(", ") } - fldconv(b, f, flag1, mode, visited, funarg) + fldconv(b, f, fieldVerb, mode, visited, funarg) } b.WriteByte(')') } else { @@ -746,7 +673,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited b.WriteByte(';') } b.WriteByte(' ') - fldconv(b, f, FmtLong, mode, visited, funarg) + fldconv(b, f, 'L', mode, visited, funarg) } if t.NumFields() != 0 { b.WriteByte(' ') @@ -758,7 +685,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited b.WriteString("undefined") if t.Sym() != nil { b.WriteByte(' ') - sconv2(b, t.Sym(), 0, mode) + sconv2(b, t.Sym(), 'v', mode) } case types.TUNSAFEPTR: @@ -771,24 +698,20 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited // Don't know how to handle - fall back to detailed prints b.WriteString(t.Kind().String()) b.WriteString(" <") - sconv2(b, t.Sym(), 0, mode) + sconv2(b, t.Sym(), 'v', mode) b.WriteString(">") } } -func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visited map[*types.Type]int, funarg types.Funarg) { +func fldconv(b *bytes.Buffer, f *types.Field, verb rune, mode FmtMode, visited map[*types.Type]int, funarg types.Funarg) { if f == nil { b.WriteString("") return } - flag, mode = flag.update(mode) - if mode == FTypeIdName { - flag |= FmtUnsigned - } var name string - if flag&FmtShort == 0 { + if verb != 'S' { s := f.Sym // Take the name from the original. @@ -799,9 +722,9 @@ func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visite if s != nil && f.Embedded == 0 { if funarg != types.FunargNone { name = fmt.Sprint(f.Nname) - } else if flag&FmtLong != 0 { + } else if verb == 'L' { name = methodSymName(s) - if !types.IsExported(name) && flag&FmtUnsigned == 0 { + if !types.IsExported(name) && mode != FTypeIdName { name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg) } } else { @@ -826,7 +749,7 @@ func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visite tconv2(b, f.Type, 0, mode, visited) } - if flag&FmtShort == 0 && funarg == types.FunargNone && f.Note != "" { + if verb != 'S' && funarg == types.FunargNone && f.Note != "" { b.WriteString(" ") b.WriteString(strconv.Quote(f.Note)) } @@ -1275,7 +1198,7 @@ func exprFmt(n Node, s fmt.State, prec int) { fmt.Fprintf(s, "'\\U%08x'", uint64(x)) } } else { - fmt.Fprint(s, FmtConst(n.Val(), fmtFlag(s, 'v'))) + fmt.Fprint(s, FmtConst(n.Val(), s.Flag('#'))) } if needUnparen { @@ -1415,7 +1338,7 @@ func exprFmt(n Node, s fmt.State, prec int) { fmt.Fprint(s, ".") return } - fmt.Fprintf(s, ".%0S", n.Sym()) + fmt.Fprintf(s, ".%s", methodSymName(n.Sym())) case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: exprFmt(n.Left(), s, nprec) @@ -1423,7 +1346,7 @@ func exprFmt(n Node, s fmt.State, prec int) { fmt.Fprint(s, ".") return } - fmt.Fprintf(s, ".%0S", n.Sym()) + fmt.Fprintf(s, ".%s", methodSymName(n.Sym())) case ODOTTYPE, ODOTTYPE2: exprFmt(n.Left(), s, nprec) From bb4a37bd9316a04c45845634a721ef44d8b5b787 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 6 Dec 2020 13:54:50 -0500 Subject: [PATCH 173/212] [dev.regabi] cmd/compile: move Type, Sym printing to package types [generated] Move the printing of types.Type and types.Sym out of ir into package types, where it properly belongs. This wasn't done originally (when the code was in gc) because the Type and Sym printing was a bit tangled up with the Node printing. But now they are untangled and can move into the correct package. This CL is automatically generated. A followup CL will clean up a little bit more by hand. Passes buildall w/ toolstash -cmp. [git-generate] cd src/cmd/compile/internal/ir rf ' mv FmtMode fmtMode mv FErr fmtGo mv FDbg fmtDebug mv FTypeId fmtTypeID mv FTypeIdName fmtTypeIDName mv methodSymName SymMethodName mv BuiltinPkg LocalPkg BlankSym OrigSym NumImport \ fmtMode fmtGo symFormat sconv sconv2 symfmt SymMethodName \ BasicTypeNames fmtBufferPool InstallTypeFormats typeFormat tconv tconv2 fldconv FmtConst \ typefmt.go mv typefmt.go cmd/compile/internal/types ' cd ../types mv typefmt.go fmt.go Change-Id: I6f3fd818323733ab8446f00594937c1628760b27 Reviewed-on: https://go-review.googlesource.com/c/go/+/275779 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/align.go | 2 +- src/cmd/compile/internal/gc/bimport.go | 3 +- src/cmd/compile/internal/gc/const.go | 2 +- src/cmd/compile/internal/gc/dcl.go | 14 +- src/cmd/compile/internal/gc/embed.go | 8 +- src/cmd/compile/internal/gc/export.go | 4 +- src/cmd/compile/internal/gc/gen.go | 2 +- src/cmd/compile/internal/gc/go.go | 4 +- src/cmd/compile/internal/gc/iexport.go | 10 +- src/cmd/compile/internal/gc/iimport.go | 4 +- src/cmd/compile/internal/gc/init.go | 2 +- src/cmd/compile/internal/gc/inl.go | 2 +- src/cmd/compile/internal/gc/main.go | 28 +- src/cmd/compile/internal/gc/noder.go | 10 +- src/cmd/compile/internal/gc/obj.go | 10 +- src/cmd/compile/internal/gc/reflect.go | 12 +- src/cmd/compile/internal/gc/sinit.go | 2 +- src/cmd/compile/internal/gc/ssa.go | 4 +- src/cmd/compile/internal/gc/subr.go | 8 +- src/cmd/compile/internal/gc/typecheck.go | 12 +- src/cmd/compile/internal/gc/universe.go | 28 +- src/cmd/compile/internal/gc/walk.go | 2 +- src/cmd/compile/internal/ir/fmt.go | 656 +----------------- src/cmd/compile/internal/ir/ir.go | 7 - src/cmd/compile/internal/ir/node.go | 28 - src/cmd/compile/internal/ssa/export_test.go | 2 +- src/cmd/compile/internal/types/fmt.go | 694 ++++++++++++++++++++ 27 files changed, 786 insertions(+), 774 deletions(-) create mode 100644 src/cmd/compile/internal/types/fmt.go diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index af426f5b24..212e4c46ae 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -193,7 +193,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { // Type imported from package, so it can't be part of // a type loop (otherwise that package should have // failed to compile). - if t.Sym().Pkg != ir.LocalPkg { + if t.Sym().Pkg != types.LocalPkg { return false } diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go index c0c18e728e..5a7018d8e6 100644 --- a/src/cmd/compile/internal/gc/bimport.go +++ b/src/cmd/compile/internal/gc/bimport.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/ir" + "cmd/compile/internal/types" "cmd/internal/src" ) @@ -15,5 +16,5 @@ func npos(pos src.XPos, n ir.Node) ir.Node { } func builtinCall(op ir.Op) ir.Node { - return ir.Nod(ir.OCALL, mkname(ir.BuiltinPkg.Lookup(ir.OpNames[op])), nil) + return ir.Nod(ir.OCALL, mkname(types.BuiltinPkg.Lookup(ir.OpNames[op])), nil) } diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 304c9aa2c3..80799580c6 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -384,7 +384,7 @@ func overflow(v constant.Value, t *types.Type) bool { return true } if doesoverflow(v, t) { - base.Errorf("constant %v overflows %v", ir.FmtConst(v, false), t) + base.Errorf("constant %v overflows %v", types.FmtConst(v, false), t) return true } return false diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index a77c1aed45..1c23c5a92f 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -66,7 +66,7 @@ func declare(n *ir.Name, ctxt ir.Class) { s := n.Sym() // kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later. - if !inimport && !typecheckok && s.Pkg != ir.LocalPkg { + if !inimport && !typecheckok && s.Pkg != types.LocalPkg { base.ErrorfAt(n.Pos(), "cannot declare name %v", s) } @@ -253,7 +253,7 @@ func oldname(s *types.Sym) ir.Node { // but it reports an error if sym is from another package and not exported. func importName(sym *types.Sym) ir.Node { n := oldname(sym) - if !types.IsExported(sym.Name) && sym.Pkg != ir.LocalPkg { + if !types.IsExported(sym.Name) && sym.Pkg != types.LocalPkg { n.SetDiag(true) base.Errorf("cannot refer to unexported name %s.%s", sym.Pkg.Name, sym.Name) } @@ -512,7 +512,7 @@ func tostruct(l []*ir.Field) *types.Type { checkdupfields("field", fields) base.Pos = lno - return types.NewStruct(ir.LocalPkg, fields) + return types.NewStruct(types.LocalPkg, fields) } func tointerface(nmethods []*ir.Field) *types.Type { @@ -533,7 +533,7 @@ func tointerface(nmethods []*ir.Field) *types.Type { } base.Pos = lno - return types.NewInterface(ir.LocalPkg, methods) + return types.NewInterface(types.LocalPkg, methods) } func fakeRecv() *ir.Field { @@ -585,14 +585,14 @@ func functype(nrecv *ir.Field, nparams, nresults []*ir.Field) *types.Type { recv = funarg(nrecv) } - t := types.NewSignature(ir.LocalPkg, recv, funargs(nparams), funargs(nresults)) + t := types.NewSignature(types.LocalPkg, recv, funargs(nparams), funargs(nresults)) checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice()) return t } func hasNamedResults(fn *ir.Func) bool { typ := fn.Type() - return typ.NumResults() > 0 && ir.OrigSym(typ.Results().Field(0).Sym) != nil + return typ.NumResults() > 0 && types.OrigSym(typ.Results().Field(0).Sym) != nil } // methodSym returns the method symbol representing a method name @@ -703,7 +703,7 @@ func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bo return nil } - if local && mt.Sym().Pkg != ir.LocalPkg { + if local && mt.Sym().Pkg != types.LocalPkg { base.Errorf("cannot define new methods on non-local type %v", mt) return nil } diff --git a/src/cmd/compile/internal/gc/embed.go b/src/cmd/compile/internal/gc/embed.go index d6e42e4f03..7664bde1c5 100644 --- a/src/cmd/compile/internal/gc/embed.go +++ b/src/cmd/compile/internal/gc/embed.go @@ -131,18 +131,18 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds [ // can't tell whether "string" and "byte" really mean "string" and "byte". // The result must be confirmed later, after type checking, using embedKind. func embedKindApprox(typ ir.Node) int { - if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) { + if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == types.LocalPkg && base.Ctxt.Pkgpath == "embed")) { return embedFiles } // These are not guaranteed to match only string and []byte - // maybe the local package has redefined one of those words. // But it's the best we can do now during the noder. // The stricter check happens later, in initEmbed calling embedKind. - if typ.Sym() != nil && typ.Sym().Name == "string" && typ.Sym().Pkg == ir.LocalPkg { + if typ.Sym() != nil && typ.Sym().Name == "string" && typ.Sym().Pkg == types.LocalPkg { return embedString } if typ, ok := typ.(*ir.SliceType); ok { - if sym := typ.Elem.Sym(); sym != nil && sym.Name == "byte" && sym.Pkg == ir.LocalPkg { + if sym := typ.Elem.Sym(); sym != nil && sym.Name == "byte" && sym.Pkg == types.LocalPkg { return embedBytes } } @@ -151,7 +151,7 @@ func embedKindApprox(typ ir.Node) int { // embedKind determines the kind of embedding variable. func embedKind(typ *types.Type) int { - if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) { + if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == types.LocalPkg && base.Ctxt.Pkgpath == "embed")) { return embedFiles } if typ == types.Types[types.TSTRING] { diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index b632a15865..593dd3b2f8 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -42,7 +42,7 @@ func initname(s string) bool { } func autoexport(n *ir.Name, ctxt ir.Class) { - if n.Sym().Pkg != ir.LocalPkg { + if n.Sym().Pkg != types.LocalPkg { return } if (ctxt != ir.PEXTERN && ctxt != ir.PFUNC) || dclcontext != ir.PEXTERN { @@ -202,7 +202,7 @@ func dumpasmhdr() { if err != nil { base.Fatalf("%v", err) } - fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", ir.LocalPkg.Name) + fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", types.LocalPkg.Name) for _, n := range asmlist { if n.Sym().IsBlank() { continue diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index 0d3f9392fb..39e9425978 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -66,7 +66,7 @@ func tempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name { s := &types.Sym{ Name: autotmpname(len(curfn.Dcl)), - Pkg: ir.LocalPkg, + Pkg: types.LocalPkg, } n := ir.NewNameAt(pos, s) s.Def = n diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index c4b9c185dc..041073f117 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -37,7 +37,7 @@ var ( // isRuntimePkg reports whether p is package runtime. func isRuntimePkg(p *types.Pkg) bool { - if base.Flag.CompilingRuntime && p == ir.LocalPkg { + if base.Flag.CompilingRuntime && p == types.LocalPkg { return true } return p.Path == "runtime" @@ -45,7 +45,7 @@ func isRuntimePkg(p *types.Pkg) bool { // isReflectPkg reports whether p is package reflect. func isReflectPkg(p *types.Pkg) bool { - if p == ir.LocalPkg { + if p == types.LocalPkg { return base.Ctxt.Pkgpath == "reflect" } return p.Path == "reflect" diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 003cf3b446..b1cc9a3dd9 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -322,7 +322,7 @@ func (w *exportWriter) writeIndex(index map[*types.Sym]uint64, mainIndex bool) { // we reference, even if we're not exporting (or reexporting) // any symbols from it. if mainIndex { - pkgSyms[ir.LocalPkg] = nil + pkgSyms[types.LocalPkg] = nil for pkg := range w.p.allPkgs { pkgSyms[pkg] = nil } @@ -402,7 +402,7 @@ func (p *iexporter) pushDecl(n *ir.Name) { } // Don't export predeclared declarations. - if n.Sym().Pkg == ir.BuiltinPkg || n.Sym().Pkg == unsafepkg { + if n.Sym().Pkg == types.BuiltinPkg || n.Sym().Pkg == unsafepkg { return } @@ -596,7 +596,7 @@ func (w *exportWriter) selector(s *types.Sym) { } else { pkg := w.currPkg if types.IsExported(name) { - pkg = ir.LocalPkg + pkg = types.LocalPkg } if s.Pkg != pkg { base.Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path) @@ -637,7 +637,7 @@ func (w *exportWriter) startType(k itag) { func (w *exportWriter) doTyp(t *types.Type) { if t.Sym() != nil { - if t.Sym().Pkg == ir.BuiltinPkg || t.Sym().Pkg == unsafepkg { + if t.Sym().Pkg == types.BuiltinPkg || t.Sym().Pkg == unsafepkg { base.Fatalf("builtin type missing from typIndex: %v", t) } @@ -748,7 +748,7 @@ func (w *exportWriter) paramList(fs []*types.Field) { func (w *exportWriter) param(f *types.Field) { w.pos(f.Pos) - w.localIdent(ir.OrigSym(f.Sym), 0) + w.localIdent(types.OrigSym(f.Sym), 0) w.typ(f.Type) } diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 1d9baed5ad..859263c83f 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -148,7 +148,7 @@ func iimport(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintType) if pkg.Name == "" { pkg.Name = pkgName pkg.Height = pkgHeight - ir.NumImport[pkgName]++ + types.NumImport[pkgName]++ // TODO(mdempsky): This belongs somewhere else. pkg.Lookup("_").Def = ir.BlankNode @@ -437,7 +437,7 @@ func (r *importReader) ident() *types.Sym { } pkg := r.currPkg if types.IsExported(name) { - pkg = ir.LocalPkg + pkg = types.LocalPkg } return pkg.Lookup(name) } diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go index dc825b2421..e0907f952c 100644 --- a/src/cmd/compile/internal/gc/init.go +++ b/src/cmd/compile/internal/gc/init.go @@ -96,7 +96,7 @@ func fninit(n []ir.Node) { fns = append(fns, s.Linksym()) } - if len(deps) == 0 && len(fns) == 0 && ir.LocalPkg.Name != "main" && ir.LocalPkg.Name != "runtime" { + if len(deps) == 0 && len(fns) == 0 && types.LocalPkg.Name != "main" && types.LocalPkg.Name != "runtime" { return // nothing to initialize } diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 8402852424..77fbf7c802 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -85,7 +85,7 @@ func typecheckinl(fn *ir.Func) { // the ->inl of a local function has been typechecked before caninl copied it. pkg := fnpkg(fn.Nname) - if pkg == ir.LocalPkg || pkg == nil { + if pkg == types.LocalPkg || pkg == nil { return // typecheckinl on local function } diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index a40671bccf..15659dc7fd 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -77,17 +77,17 @@ func Main(archInit func(*Arch)) { // See bugs 31188 and 21945 (CLs 170638, 98075, 72371). base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin - ir.LocalPkg = types.NewPkg("", "") - ir.LocalPkg.Prefix = "\"\"" + types.LocalPkg = types.NewPkg("", "") + types.LocalPkg.Prefix = "\"\"" // We won't know localpkg's height until after import // processing. In the mean time, set to MaxPkgHeight to ensure // height comparisons at least work until then. - ir.LocalPkg.Height = types.MaxPkgHeight + types.LocalPkg.Height = types.MaxPkgHeight // pseudo-package, for scoping - ir.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin? - ir.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin + types.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin? + types.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin // pseudo-package, accessed by import "unsafe" unsafepkg = types.NewPkg("unsafe", "unsafe") @@ -212,7 +212,7 @@ func Main(archInit func(*Arch)) { // would lead to import cycles) types.Widthptr = Widthptr types.Dowidth = dowidth - ir.InstallTypeFormats() + types.InstallTypeFormats() types.TypeLinkSym = func(t *types.Type) *obj.LSym { return typenamesym(t).Linksym() } @@ -922,14 +922,14 @@ func pkgnotused(lineno src.XPos, path string, name string) { } func mkpackage(pkgname string) { - if ir.LocalPkg.Name == "" { + if types.LocalPkg.Name == "" { if pkgname == "_" { base.Errorf("invalid package name _") } - ir.LocalPkg.Name = pkgname + types.LocalPkg.Name = pkgname } else { - if pkgname != ir.LocalPkg.Name { - base.Errorf("package %s; expected %s", pkgname, ir.LocalPkg.Name) + if pkgname != types.LocalPkg.Name { + base.Errorf("package %s; expected %s", pkgname, types.LocalPkg.Name) } } } @@ -942,7 +942,7 @@ func clearImports() { } var unused []importedPkg - for _, s := range ir.LocalPkg.Syms { + for _, s := range types.LocalPkg.Syms { n := ir.AsNode(s.Def) if n == nil { continue @@ -1046,7 +1046,7 @@ func recordPackageName() { // together two package main archives. So allow dups. s.Set(obj.AttrDuplicateOK, true) base.Ctxt.Data = append(base.Ctxt.Data, s) - s.P = []byte(ir.LocalPkg.Name) + s.P = []byte(types.LocalPkg.Name) } // currentLang returns the current language version. @@ -1073,9 +1073,9 @@ var langWant lang func langSupported(major, minor int, pkg *types.Pkg) bool { if pkg == nil { // TODO(mdempsky): Set Pkg for local types earlier. - pkg = ir.LocalPkg + pkg = types.LocalPkg } - if pkg != ir.LocalPkg { + if pkg != types.LocalPkg { // Assume imported packages passed type-checking. return true } diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 1cd8375677..f39bf2ff3c 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -79,7 +79,7 @@ func parseFiles(filenames []string) uint { p.processPragmas() } - ir.LocalPkg.Height = myheight + types.LocalPkg.Height = myheight return lines } @@ -501,7 +501,7 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node { } nod := p.nod(decl, ir.ODCLTYPE, n, nil) - if n.Alias() && !langSupported(1, 9, ir.LocalPkg) { + if n.Alias() && !langSupported(1, 9, types.LocalPkg) { base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9") } return nod @@ -532,7 +532,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node { } } - if ir.LocalPkg.Name == "main" && name.Name == "main" { + if types.LocalPkg.Name == "main" && name.Name == "main" { if t.List().Len() > 0 || t.Rlist().Len() > 0 { base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values") } @@ -931,7 +931,7 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym { var pkg *types.Pkg if def.Op() != ir.OPACK { base.Errorf("%v is not a package", name) - pkg = ir.LocalPkg + pkg = types.LocalPkg } else { def := def.(*ir.PkgName) def.Used = true @@ -1387,7 +1387,7 @@ func (p *noder) binOp(op syntax.Operator) ir.Op { // literal is not compatible with the current language version. func checkLangCompat(lit *syntax.BasicLit) { s := lit.Value - if len(s) <= 2 || langSupported(1, 13, ir.LocalPkg) { + if len(s) <= 2 || langSupported(1, 13, types.LocalPkg) { return } // len(s) > 2 diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index b1701b30a1..c34a86d4eb 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -84,7 +84,7 @@ func printObjHeader(bout *bio.Writer) { if base.Flag.BuildID != "" { fmt.Fprintf(bout, "build id %q\n", base.Flag.BuildID) } - if ir.LocalPkg.Name == "main" { + if types.LocalPkg.Name == "main" { fmt.Fprintf(bout, "main\n") } fmt.Fprintf(bout, "\n") // header ends with blank line @@ -200,7 +200,7 @@ func dumpLinkerObj(bout *bio.Writer) { } func addptabs() { - if !base.Ctxt.Flag_dynlink || ir.LocalPkg.Name != "main" { + if !base.Ctxt.Flag_dynlink || types.LocalPkg.Name != "main" { return } for _, exportn := range exportlist { @@ -235,7 +235,7 @@ func dumpGlobal(n ir.Node) { if n.Class() == ir.PFUNC { return } - if n.Sym().Pkg != ir.LocalPkg { + if n.Sym().Pkg != types.LocalPkg { return } dowidth(n.Type()) @@ -248,7 +248,7 @@ func dumpGlobalConst(n ir.Node) { if t == nil { return } - if n.Sym().Pkg != ir.LocalPkg { + if n.Sym().Pkg != types.LocalPkg { return } // only export integer constants for now @@ -478,7 +478,7 @@ var slicedataGen int func slicedata(pos src.XPos, s string) ir.Node { slicedataGen++ symname := fmt.Sprintf(".gobytes.%d", slicedataGen) - sym := ir.LocalPkg.Lookup(symname) + sym := types.LocalPkg.Lookup(symname) symnode := NewName(sym) sym.Def = symnode diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 42139b7135..9b8f26a84b 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -301,7 +301,7 @@ func deferstruct(stksize int64) *types.Type { // Unlike the global makefield function, this one needs to set Pkg // because these types might be compared (in SSA CSE sorting). // TODO: unify this makefield and the global one above. - sym := &types.Sym{Name: name, Pkg: ir.LocalPkg} + sym := &types.Sym{Name: name, Pkg: types.LocalPkg} return types.NewField(src.NoXPos, sym, typ) } argtype := types.NewArray(types.Types[types.TUINT8], stksize) @@ -491,7 +491,7 @@ func dimportpath(p *types.Pkg) { } str := p.Path - if p == ir.LocalPkg { + if p == types.LocalPkg { // Note: myimportpath != "", or else dgopkgpath won't call dimportpath. str = base.Ctxt.Pkgpath } @@ -508,7 +508,7 @@ func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int { return duintptr(s, ot, 0) } - if pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "" { + if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" { // If we don't know the full import path of the package being compiled // (i.e. -p was not passed on the compiler command line), emit a reference to // type..importpath.""., which the linker will rewrite using the correct import path. @@ -527,7 +527,7 @@ func dgopkgpathOff(s *obj.LSym, ot int, pkg *types.Pkg) int { if pkg == nil { return duint32(s, ot, 0) } - if pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "" { + if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" { // If we don't know the full import path of the package being compiled // (i.e. -p was not passed on the compiler command line), emit a reference to // type..importpath.""., which the linker will rewrite using the correct import path. @@ -1158,7 +1158,7 @@ func dtypesym(t *types.Type) *obj.LSym { if base.Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Kind()] && tbase != types.ByteType && tbase != types.RuneType && tbase != types.ErrorType) { // int, float, etc // named types from other files are defined only by those files - if tbase.Sym() != nil && tbase.Sym().Pkg != ir.LocalPkg { + if tbase.Sym() != nil && tbase.Sym().Pkg != types.LocalPkg { if i, ok := typeSymIdx[tbase]; ok { lsym.Pkg = tbase.Sym().Pkg.Prefix if t != tbase { @@ -1568,7 +1568,7 @@ func dumptabs() { } // process ptabs - if ir.LocalPkg.Name == "main" && len(ptabs) > 0 { + if types.LocalPkg.Name == "main" && len(ptabs) > 0 { ot := 0 s := base.Ctxt.Lookup("go.plugin.tabs") for _, p := range ptabs { diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index c446c9d083..3c5f11c5ab 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -79,7 +79,7 @@ func (s *InitSchedule) staticcopy(l ir.Node, r ir.Node) bool { pfuncsym(l, r) return true } - if r.Class() != ir.PEXTERN || r.Sym().Pkg != ir.LocalPkg { + if r.Class() != ir.PEXTERN || r.Sym().Pkg != types.LocalPkg { return false } if r.Name().Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 89918e2133..add50c35d7 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -4127,7 +4127,7 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder { return nil } pkg := sym.Pkg.Path - if sym.Pkg == ir.LocalPkg { + if sym.Pkg == types.LocalPkg { pkg = base.Ctxt.Pkgpath } if base.Flag.Race && pkg == "sync/atomic" { @@ -7073,7 +7073,7 @@ func (e *ssafn) SplitSlot(parent *ssa.LocalSlot, suffix string, offset int64, t return ssa.LocalSlot{N: node, Type: t, Off: parent.Off + offset} } - s := &types.Sym{Name: node.Sym().Name + suffix, Pkg: ir.LocalPkg} + s := &types.Sym{Name: node.Sym().Name + suffix, Pkg: types.LocalPkg} n := ir.NewNameAt(parent.N.Pos(), s) s.Def = n ir.AsNode(s.Def).Name().SetUsed(true) diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 65eb61e680..dffebc58f2 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -69,7 +69,7 @@ func setlineno(n ir.Node) src.XPos { } func lookup(name string) *types.Sym { - return ir.LocalPkg.Lookup(name) + return types.LocalPkg.Lookup(name) } // lookupN looks up the symbol starting with prefix and ending with @@ -78,7 +78,7 @@ func lookupN(prefix string, n int) *types.Sym { var buf [20]byte // plenty long enough for all current users copy(buf[:], prefix) b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10) - return ir.LocalPkg.LookupBytes(b) + return types.LocalPkg.LookupBytes(b) } // autolabel generates a new Name node for use with @@ -1109,13 +1109,13 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { // Only generate (*T).M wrappers for T.M in T's own package. if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && - rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != ir.LocalPkg { + rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg { return } // Only generate I.M wrappers for I in I's own package // but keep doing it for error.Error (was issue #29304). - if rcvr.IsInterface() && rcvr.Sym() != nil && rcvr.Sym().Pkg != ir.LocalPkg && rcvr != types.ErrorType { + if rcvr.IsInterface() && rcvr.Sym() != nil && rcvr.Sym().Pkg != types.LocalPkg && rcvr != types.ErrorType { return } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index dc9e23069e..85094dbebc 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -90,7 +90,7 @@ func resolve(n ir.Node) (res ir.Node) { defer tracePrint("resolve", n)(&res) } - if n.Sym().Pkg != ir.LocalPkg { + if n.Sym().Pkg != types.LocalPkg { if inimport { base.Fatalf("recursive inimport") } @@ -2386,7 +2386,7 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) { me.(*ir.MethodExpr).Method = m // Issue 25065. Make sure that we emit the symbol for a local method. - if base.Ctxt.Flag_dynlink && !inimport && (t.Sym() == nil || t.Sym().Pkg == ir.LocalPkg) { + if base.Ctxt.Flag_dynlink && !inimport && (t.Sym() == nil || t.Sym().Pkg == types.LocalPkg) { makefuncsym(me.Sym()) } @@ -2862,7 +2862,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) { f := t.Field(i) s := f.Sym - if s != nil && !types.IsExported(s.Name) && s.Pkg != ir.LocalPkg { + if s != nil && !types.IsExported(s.Name) && s.Pkg != types.LocalPkg { base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t) } // No pushtype allowed here. Must name fields for that. @@ -2903,7 +2903,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) { // package, because of import dot. Redirect to correct sym // before we do the lookup. s := key.Sym() - if s.Pkg != ir.LocalPkg && types.IsExported(s.Name) { + if s.Pkg != types.LocalPkg && types.IsExported(s.Name) { s1 := lookup(s.Name) if s1.Origpkg == s.Pkg { s = s1 @@ -3034,7 +3034,7 @@ func typecheckarraylit(elemType *types.Type, bound int64, elts []ir.Node, ctx st // visible reports whether sym is exported or locally defined. func visible(sym *types.Sym) bool { - return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == ir.LocalPkg) + return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == types.LocalPkg) } // nonexported reports whether sym is an unexported field. @@ -3929,7 +3929,7 @@ func curpkg() *types.Pkg { fn := Curfn if fn == nil { // Initialization expressions for package-scope variables. - return ir.LocalPkg + return types.LocalPkg } return fnpkg(fn.Nname) } diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index cd68719a99..42b996d88d 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -104,7 +104,7 @@ func initUniverse() { } types.Types[types.TANY] = types.New(types.TANY) - types.Types[types.TINTER] = types.NewInterface(ir.LocalPkg, nil) + types.Types[types.TINTER] = types.NewInterface(types.LocalPkg, nil) defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type { sym := pkg.Lookup(name) @@ -120,7 +120,7 @@ func initUniverse() { } for _, s := range &basicTypes { - types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name) + types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name) } for _, s := range &typedefs { @@ -130,7 +130,7 @@ func initUniverse() { } simtype[s.etype] = sameas - types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name) + types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name) } // We create separate byte and rune types for better error messages @@ -140,11 +140,11 @@ func initUniverse() { // of less informative error messages involving bytes and runes)? // (Alternatively, we could introduce an OTALIAS node representing // type aliases, albeit at the cost of having to deal with it everywhere). - types.ByteType = defBasic(types.TUINT8, ir.BuiltinPkg, "byte") - types.RuneType = defBasic(types.TINT32, ir.BuiltinPkg, "rune") + types.ByteType = defBasic(types.TUINT8, types.BuiltinPkg, "byte") + types.RuneType = defBasic(types.TINT32, types.BuiltinPkg, "rune") // error type - s := ir.BuiltinPkg.Lookup("error") + s := types.BuiltinPkg.Lookup("error") n := ir.NewDeclNameAt(src.NoXPos, s) n.SetOp(ir.OTYPE) types.ErrorType = types.NewNamed(n) @@ -162,7 +162,7 @@ func initUniverse() { simtype[types.TUNSAFEPTR] = types.TPTR for _, s := range &builtinFuncs { - s2 := ir.BuiltinPkg.Lookup(s.name) + s2 := types.BuiltinPkg.Lookup(s.name) s2.Def = NewName(s2) ir.AsNode(s2.Def).SetSubOp(s.op) } @@ -173,16 +173,16 @@ func initUniverse() { ir.AsNode(s2.Def).SetSubOp(s.op) } - s = ir.BuiltinPkg.Lookup("true") + s = types.BuiltinPkg.Lookup("true") s.Def = nodbool(true) ir.AsNode(s.Def).SetSym(lookup("true")) - s = ir.BuiltinPkg.Lookup("false") + s = types.BuiltinPkg.Lookup("false") s.Def = nodbool(false) ir.AsNode(s.Def).SetSym(lookup("false")) s = lookup("_") - ir.BlankSym = s + types.BlankSym = s s.Block = -100 s.Def = NewName(s) types.Types[types.TBLANK] = types.New(types.TBLANK) @@ -190,18 +190,18 @@ func initUniverse() { ir.BlankNode = ir.AsNode(s.Def) ir.BlankNode.SetTypecheck(1) - s = ir.BuiltinPkg.Lookup("_") + s = types.BuiltinPkg.Lookup("_") s.Block = -100 s.Def = NewName(s) types.Types[types.TBLANK] = types.New(types.TBLANK) ir.AsNode(s.Def).SetType(types.Types[types.TBLANK]) types.Types[types.TNIL] = types.New(types.TNIL) - s = ir.BuiltinPkg.Lookup("nil") + s = types.BuiltinPkg.Lookup("nil") s.Def = nodnil() ir.AsNode(s.Def).SetSym(s) - s = ir.BuiltinPkg.Lookup("iota") + s = types.BuiltinPkg.Lookup("iota") s.Def = ir.Nod(ir.OIOTA, nil, nil) ir.AsNode(s.Def).SetSym(s) @@ -339,7 +339,7 @@ func finishUniverse() { // that we silently skip symbols that are already declared in the // package block rather than emitting a redeclared symbol error. - for _, s := range ir.BuiltinPkg.Syms { + for _, s := range types.BuiltinPkg.Syms { if s.Def == nil { continue } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 574c7c4709..346817e589 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -983,7 +983,7 @@ opswitch: if param == types.Txxx { break } - fn := ir.BasicTypeNames[param] + "to" + ir.BasicTypeNames[result] + fn := types.BasicTypeNames[param] + "to" + types.BasicTypeNames[result] n = conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type()) case ir.ODIV, ir.OMOD: diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 117c7417d2..79d85d1803 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -10,9 +10,7 @@ import ( "go/constant" "io" "os" - "strconv" - "strings" - "sync" + "unicode/utf8" "cmd/compile/internal/base" @@ -20,74 +18,6 @@ import ( "cmd/internal/src" ) -// Format conversions: -// TODO(gri) verify these; eliminate those not used anymore -// -// %v Op Node opcodes -// Flags: #: print Go syntax (automatic unless mode == FDbg) -// -// %j *Node Node details -// Flags: 0: suppresses things not relevant until walk -// -// %v *Val Constant values -// -// %v *types.Sym Symbols -// %S unqualified identifier in any mode -// Flags: +,- #: mode (see below) -// 0: in export mode: unqualified identifier if exported, qualified if not -// -// %v *types.Type Types -// %S omit "func" and receiver in function types -// %L definition instead of name. -// Flags: +,- #: mode (see below) -// ' ' (only in -/Sym mode) print type identifiers wit package name instead of prefix. -// -// %v *Node Nodes -// %S (only in +/debug mode) suppress recursion -// %L (only in Error mode) print "foo (type Bar)" -// Flags: +,- #: mode (see below) -// -// %v Nodes Node lists -// Flags: those of *Node -// .: separate items with ',' instead of ';' - -// *types.Sym, *types.Type, and *Node types use the flags below to set the format mode - -// The mode flags '+', '-', and '#' are sticky; they persist through -// recursions of *Node, *types.Type, and *types.Sym values. The ' ' flag is -// sticky only on *types.Type recursions and only used in %-/*types.Sym mode. -// -// Example: given a *types.Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode - -// Useful format combinations: -// TODO(gri): verify these -// -// *Node, Nodes: -// %+v multiline recursive debug dump of *Node/Nodes -// %+S non-recursive debug dump -// -// *Node: -// %#v Go format -// %L "foo (type Bar)" for error messages -// -// *types.Type: -// %#v Go format -// %#L type definition instead of name -// %#S omit "func" and receiver in function signature -// -// %-v type identifiers -// %-S type identifiers without "func" and arg names in type signatures (methodsym) -// %- v type identifiers with package name instead of prefix (typesym, dcommontype, typehash) - -type FmtMode int - -const ( - FErr FmtMode = iota - FDbg - FTypeId - FTypeIdName // same as FTypeId, but use package name instead of prefix -) - // Op var OpNames = []string{ @@ -177,584 +107,6 @@ func (o Op) Format(s fmt.State, verb rune) { } } -// Val - -func FmtConst(v constant.Value, sharp bool) string { - if !sharp && v.Kind() == constant.Complex { - real, imag := constant.Real(v), constant.Imag(v) - - var re string - sre := constant.Sign(real) - if sre != 0 { - re = real.String() - } - - var im string - sim := constant.Sign(imag) - if sim != 0 { - im = imag.String() - } - - switch { - case sre == 0 && sim == 0: - return "0" - case sre == 0: - return im + "i" - case sim == 0: - return re - case sim < 0: - return fmt.Sprintf("(%s%si)", re, im) - default: - return fmt.Sprintf("(%s+%si)", re, im) - } - } - - return v.String() -} - -// Sym - -// numImport tracks how often a package with a given name is imported. -// It is used to provide a better error message (by using the package -// path to disambiguate) if a package that appears multiple times with -// the same name appears in an error message. -var NumImport = make(map[string]int) - -// "%S" suppresses qualifying with package -func symFormat(s *types.Sym, f fmt.State, verb rune) { - mode := FErr - switch verb { - case 'v', 'S': - if verb == 'v' && f.Flag('+') { - mode = FDbg - } - fmt.Fprint(f, sconv(s, verb, mode)) - - default: - fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s) - } -} - -// See #16897 for details about performance implications -// before changing the implementation of sconv. -func sconv(s *types.Sym, verb rune, mode FmtMode) string { - if verb == 'L' { - panic("linksymfmt") - } - - if s == nil { - return "" - } - - if s.Name == "_" { - return "_" - } - buf := fmtBufferPool.Get().(*bytes.Buffer) - buf.Reset() - defer fmtBufferPool.Put(buf) - - symfmt(buf, s, verb, mode) - return types.InternString(buf.Bytes()) -} - -func sconv2(b *bytes.Buffer, s *types.Sym, verb rune, mode FmtMode) { - if verb == 'L' { - panic("linksymfmt") - } - if s == nil { - b.WriteString("") - return - } - if s.Name == "_" { - b.WriteString("_") - return - } - - symfmt(b, s, verb, mode) -} - -func symfmt(b *bytes.Buffer, s *types.Sym, verb rune, mode FmtMode) { - if verb != 'S' { - switch mode { - case FErr: // This is for the user - if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg { - b.WriteString(s.Name) - return - } - - // If the name was used by multiple packages, display the full path, - if s.Pkg.Name != "" && NumImport[s.Pkg.Name] > 1 { - fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name) - return - } - b.WriteString(s.Pkg.Name) - b.WriteByte('.') - b.WriteString(s.Name) - return - - case FDbg: - b.WriteString(s.Pkg.Name) - b.WriteByte('.') - b.WriteString(s.Name) - return - - case FTypeIdName: - // dcommontype, typehash - b.WriteString(s.Pkg.Name) - b.WriteByte('.') - b.WriteString(s.Name) - return - - case FTypeId: - // (methodsym), typesym, weaksym - b.WriteString(s.Pkg.Prefix) - b.WriteByte('.') - b.WriteString(s.Name) - return - } - } - - b.WriteString(s.Name) -} - -func methodSymName(s *types.Sym) string { - // Skip leading "type." in method name - name := s.Name - if i := strings.LastIndex(name, "."); i >= 0 { - name = name[i+1:] - } - return name -} - -// Type - -var BasicTypeNames = []string{ - types.TINT: "int", - types.TUINT: "uint", - types.TINT8: "int8", - types.TUINT8: "uint8", - types.TINT16: "int16", - types.TUINT16: "uint16", - types.TINT32: "int32", - types.TUINT32: "uint32", - types.TINT64: "int64", - types.TUINT64: "uint64", - types.TUINTPTR: "uintptr", - types.TFLOAT32: "float32", - types.TFLOAT64: "float64", - types.TCOMPLEX64: "complex64", - types.TCOMPLEX128: "complex128", - types.TBOOL: "bool", - types.TANY: "any", - types.TSTRING: "string", - types.TNIL: "nil", - types.TIDEAL: "untyped number", - types.TBLANK: "blank", -} - -var fmtBufferPool = sync.Pool{ - New: func() interface{} { - return new(bytes.Buffer) - }, -} - -func InstallTypeFormats() { - types.SymString = func(s *types.Sym) string { - return sconv(s, 0, FErr) - } - types.TypeString = func(t *types.Type) string { - return tconv(t, 0, FErr) - } - types.TypeShortString = func(t *types.Type) string { - return tconv(t, 0, FTypeId) - } - types.TypeLongString = func(t *types.Type) string { - return tconv(t, 0, FTypeIdName) - } - types.FormatSym = symFormat - types.FormatType = typeFormat -} - -// "%L" print definition, not name -// "%S" omit 'func' and receiver from function types, short type names -func typeFormat(t *types.Type, s fmt.State, verb rune) { - mode := FErr - switch verb { - case 'v', 'S', 'L': - if verb == 'v' && s.Flag('+') { // %+v is debug format - mode = FDbg - } - if verb == 'S' && s.Flag('-') { // %-S is special case for receiver - short typeid format - mode = FTypeId - } - fmt.Fprint(s, tconv(t, verb, mode)) - default: - fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t) - } -} - -func tconv(t *types.Type, verb rune, mode FmtMode) string { - buf := fmtBufferPool.Get().(*bytes.Buffer) - buf.Reset() - defer fmtBufferPool.Put(buf) - - tconv2(buf, t, verb, mode, nil) - return types.InternString(buf.Bytes()) -} - -// tconv2 writes a string representation of t to b. -// flag and mode control exactly what is printed. -// Any types x that are already in the visited map get printed as @%d where %d=visited[x]. -// See #16897 before changing the implementation of tconv. -func tconv2(b *bytes.Buffer, t *types.Type, verb rune, mode FmtMode, visited map[*types.Type]int) { - if off, ok := visited[t]; ok { - // We've seen this type before, so we're trying to print it recursively. - // Print a reference to it instead. - fmt.Fprintf(b, "@%d", off) - return - } - if t == nil { - b.WriteString("") - return - } - if t.Kind() == types.TSSA { - b.WriteString(t.Extra.(string)) - return - } - if t.Kind() == types.TTUPLE { - b.WriteString(t.FieldType(0).String()) - b.WriteByte(',') - b.WriteString(t.FieldType(1).String()) - return - } - - if t.Kind() == types.TRESULTS { - tys := t.Extra.(*types.Results).Types - for i, et := range tys { - if i > 0 { - b.WriteByte(',') - } - b.WriteString(et.String()) - } - return - } - - if t == types.ByteType || t == types.RuneType { - // in %-T mode collapse rune and byte with their originals. - switch mode { - case FTypeIdName, FTypeId: - t = types.Types[t.Kind()] - default: - sconv2(b, t.Sym(), 'S', mode) - return - } - } - if t == types.ErrorType { - b.WriteString("error") - return - } - - // Unless the 'L' flag was specified, if the type has a name, just print that name. - if verb != 'L' && t.Sym() != nil && t != types.Types[t.Kind()] { - switch mode { - case FTypeId, FTypeIdName: - if verb == 'S' { - if t.Vargen != 0 { - sconv2(b, t.Sym(), 'S', mode) - fmt.Fprintf(b, "·%d", t.Vargen) - return - } - sconv2(b, t.Sym(), 'S', mode) - return - } - - if mode == FTypeIdName { - sconv2(b, t.Sym(), 'v', FTypeIdName) - return - } - - if t.Sym().Pkg == LocalPkg && t.Vargen != 0 { - sconv2(b, t.Sym(), 'v', mode) - fmt.Fprintf(b, "·%d", t.Vargen) - return - } - } - - sconv2(b, t.Sym(), 'v', mode) - return - } - - if int(t.Kind()) < len(BasicTypeNames) && BasicTypeNames[t.Kind()] != "" { - var name string - switch t { - case types.UntypedBool: - name = "untyped bool" - case types.UntypedString: - name = "untyped string" - case types.UntypedInt: - name = "untyped int" - case types.UntypedRune: - name = "untyped rune" - case types.UntypedFloat: - name = "untyped float" - case types.UntypedComplex: - name = "untyped complex" - default: - name = BasicTypeNames[t.Kind()] - } - b.WriteString(name) - return - } - - if mode == FDbg { - b.WriteString(t.Kind().String()) - b.WriteByte('-') - tconv2(b, t, 'v', FErr, visited) - return - } - - // At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't - // try to print it recursively. - // We record the offset in the result buffer where the type's text starts. This offset serves as a reference - // point for any later references to the same type. - // Note that we remove the type from the visited map as soon as the recursive call is done. - // This prevents encoding types like map[*int]*int as map[*int]@4. (That encoding would work, - // but I'd like to use the @ notation only when strictly necessary.) - if visited == nil { - visited = map[*types.Type]int{} - } - visited[t] = b.Len() - defer delete(visited, t) - - switch t.Kind() { - case types.TPTR: - b.WriteByte('*') - switch mode { - case FTypeId, FTypeIdName: - if verb == 'S' { - tconv2(b, t.Elem(), 'S', mode, visited) - return - } - } - tconv2(b, t.Elem(), 'v', mode, visited) - - case types.TARRAY: - b.WriteByte('[') - b.WriteString(strconv.FormatInt(t.NumElem(), 10)) - b.WriteByte(']') - tconv2(b, t.Elem(), 0, mode, visited) - - case types.TSLICE: - b.WriteString("[]") - tconv2(b, t.Elem(), 0, mode, visited) - - case types.TCHAN: - switch t.ChanDir() { - case types.Crecv: - b.WriteString("<-chan ") - tconv2(b, t.Elem(), 0, mode, visited) - case types.Csend: - b.WriteString("chan<- ") - tconv2(b, t.Elem(), 0, mode, visited) - default: - b.WriteString("chan ") - if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym() == nil && t.Elem().ChanDir() == types.Crecv { - b.WriteByte('(') - tconv2(b, t.Elem(), 0, mode, visited) - b.WriteByte(')') - } else { - tconv2(b, t.Elem(), 0, mode, visited) - } - } - - case types.TMAP: - b.WriteString("map[") - tconv2(b, t.Key(), 0, mode, visited) - b.WriteByte(']') - tconv2(b, t.Elem(), 0, mode, visited) - - case types.TINTER: - if t.IsEmptyInterface() { - b.WriteString("interface {}") - break - } - b.WriteString("interface {") - for i, f := range t.Fields().Slice() { - if i != 0 { - b.WriteByte(';') - } - b.WriteByte(' ') - switch { - case f.Sym == nil: - // Check first that a symbol is defined for this type. - // Wrong interface definitions may have types lacking a symbol. - break - case types.IsExported(f.Sym.Name): - sconv2(b, f.Sym, 'S', mode) - default: - if mode != FTypeIdName { - mode = FTypeId - } - sconv2(b, f.Sym, 'v', mode) - } - tconv2(b, f.Type, 'S', mode, visited) - } - if t.NumFields() != 0 { - b.WriteByte(' ') - } - b.WriteByte('}') - - case types.TFUNC: - if verb == 'S' { - // no leading func - } else { - if t.Recv() != nil { - b.WriteString("method") - tconv2(b, t.Recvs(), 0, mode, visited) - b.WriteByte(' ') - } - b.WriteString("func") - } - tconv2(b, t.Params(), 0, mode, visited) - - switch t.NumResults() { - case 0: - // nothing to do - - case 1: - b.WriteByte(' ') - tconv2(b, t.Results().Field(0).Type, 0, mode, visited) // struct->field->field's type - - default: - b.WriteByte(' ') - tconv2(b, t.Results(), 0, mode, visited) - } - - case types.TSTRUCT: - if m := t.StructType().Map; m != nil { - mt := m.MapType() - // Format the bucket struct for map[x]y as map.bucket[x]y. - // This avoids a recursive print that generates very long names. - switch t { - case mt.Bucket: - b.WriteString("map.bucket[") - case mt.Hmap: - b.WriteString("map.hdr[") - case mt.Hiter: - b.WriteString("map.iter[") - default: - base.Fatalf("unknown internal map type") - } - tconv2(b, m.Key(), 0, mode, visited) - b.WriteByte(']') - tconv2(b, m.Elem(), 0, mode, visited) - break - } - - if funarg := t.StructType().Funarg; funarg != types.FunargNone { - b.WriteByte('(') - fieldVerb := 'v' - switch mode { - case FTypeId, FTypeIdName, FErr: - // no argument names on function signature, and no "noescape"/"nosplit" tags - fieldVerb = 'S' - } - for i, f := range t.Fields().Slice() { - if i != 0 { - b.WriteString(", ") - } - fldconv(b, f, fieldVerb, mode, visited, funarg) - } - b.WriteByte(')') - } else { - b.WriteString("struct {") - for i, f := range t.Fields().Slice() { - if i != 0 { - b.WriteByte(';') - } - b.WriteByte(' ') - fldconv(b, f, 'L', mode, visited, funarg) - } - if t.NumFields() != 0 { - b.WriteByte(' ') - } - b.WriteByte('}') - } - - case types.TFORW: - b.WriteString("undefined") - if t.Sym() != nil { - b.WriteByte(' ') - sconv2(b, t.Sym(), 'v', mode) - } - - case types.TUNSAFEPTR: - b.WriteString("unsafe.Pointer") - - case types.Txxx: - b.WriteString("Txxx") - - default: - // Don't know how to handle - fall back to detailed prints - b.WriteString(t.Kind().String()) - b.WriteString(" <") - sconv2(b, t.Sym(), 'v', mode) - b.WriteString(">") - - } -} - -func fldconv(b *bytes.Buffer, f *types.Field, verb rune, mode FmtMode, visited map[*types.Type]int, funarg types.Funarg) { - if f == nil { - b.WriteString("") - return - } - - var name string - if verb != 'S' { - s := f.Sym - - // Take the name from the original. - if mode == FErr { - s = OrigSym(s) - } - - if s != nil && f.Embedded == 0 { - if funarg != types.FunargNone { - name = fmt.Sprint(f.Nname) - } else if verb == 'L' { - name = methodSymName(s) - if !types.IsExported(name) && mode != FTypeIdName { - name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg) - } - } else { - name = sconv(s, 0, mode) - } - } - } - - if name != "" { - b.WriteString(name) - b.WriteString(" ") - } - - if f.IsDDD() { - var et *types.Type - if f.Type != nil { - et = f.Type.Elem() - } - b.WriteString("...") - tconv2(b, et, 0, mode, visited) - } else { - tconv2(b, f.Type, 0, mode, visited) - } - - if verb != 'S' && funarg == types.FunargNone && f.Note != "" { - b.WriteString(" ") - b.WriteString(strconv.Quote(f.Note)) - } -} - // Node func FmtNode(n Node, s fmt.State, verb rune) { @@ -1198,7 +550,7 @@ func exprFmt(n Node, s fmt.State, prec int) { fmt.Fprintf(s, "'\\U%08x'", uint64(x)) } } else { - fmt.Fprint(s, FmtConst(n.Val(), s.Flag('#'))) + fmt.Fprint(s, types.FmtConst(n.Val(), s.Flag('#'))) } if needUnparen { @@ -1338,7 +690,7 @@ func exprFmt(n Node, s fmt.State, prec int) { fmt.Fprint(s, ".") return } - fmt.Fprintf(s, ".%s", methodSymName(n.Sym())) + fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym())) case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: exprFmt(n.Left(), s, nprec) @@ -1346,7 +698,7 @@ func exprFmt(n Node, s fmt.State, prec int) { fmt.Fprint(s, ".") return } - fmt.Fprintf(s, ".%s", methodSymName(n.Sym())) + fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym())) case ODOTTYPE, ODOTTYPE2: exprFmt(n.Left(), s, nprec) diff --git a/src/cmd/compile/internal/ir/ir.go b/src/cmd/compile/internal/ir/ir.go index ad7f692b07..82224ca2ed 100644 --- a/src/cmd/compile/internal/ir/ir.go +++ b/src/cmd/compile/internal/ir/ir.go @@ -3,10 +3,3 @@ // license that can be found in the LICENSE file. package ir - -import "cmd/compile/internal/types" - -var LocalPkg *types.Pkg // package being compiled - -// builtinpkg is a fake package that declares the universe block. -var BuiltinPkg *types.Pkg diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 56b320e726..ba7eaae1b9 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -10,7 +10,6 @@ import ( "fmt" "go/constant" "sort" - "strings" "cmd/compile/internal/base" "cmd/compile/internal/types" @@ -654,33 +653,6 @@ func AsNode(n types.Object) Node { var BlankNode Node -var BlankSym *types.Sym - -// origSym returns the original symbol written by the user. -func OrigSym(s *types.Sym) *types.Sym { - if s == nil { - return nil - } - - if len(s.Name) > 1 && s.Name[0] == '~' { - switch s.Name[1] { - case 'r': // originally an unnamed result - return nil - case 'b': // originally the blank identifier _ - // TODO(mdempsky): Does s.Pkg matter here? - return BlankSym - } - return s - } - - if strings.HasPrefix(s.Name, ".anon") { - // originally an unnamed or _ name (see subr.go: structargs) - return nil - } - - return s -} - func IsConst(n Node, ct constant.Kind) bool { return ConstType(n) == ct } diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index cb3b9c0e2a..decb843465 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -137,7 +137,7 @@ func init() { // Initialize just enough of the universe and the types package to make our tests function. // TODO(josharian): move universe initialization to the types package, // so this test setup can share it. - ir.InstallTypeFormats() + types.InstallTypeFormats() types.Dowidth = func(t *types.Type) {} for _, typ := range [...]struct { diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go new file mode 100644 index 0000000000..4f36e4c393 --- /dev/null +++ b/src/cmd/compile/internal/types/fmt.go @@ -0,0 +1,694 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "bytes" + "fmt" + "go/constant" + "strconv" + "strings" + "sync" + + "cmd/compile/internal/base" +) + +// builtinpkg is a fake package that declares the universe block. +var BuiltinPkg *Pkg + +var LocalPkg *Pkg // package being compiled + +var BlankSym *Sym + +// origSym returns the original symbol written by the user. +func OrigSym(s *Sym) *Sym { + if s == nil { + return nil + } + + if len(s.Name) > 1 && s.Name[0] == '~' { + switch s.Name[1] { + case 'r': // originally an unnamed result + return nil + case 'b': // originally the blank identifier _ + // TODO(mdempsky): Does s.Pkg matter here? + return BlankSym + } + return s + } + + if strings.HasPrefix(s.Name, ".anon") { + // originally an unnamed or _ name (see subr.go: structargs) + return nil + } + + return s +} + +// Sym + +// numImport tracks how often a package with a given name is imported. +// It is used to provide a better error message (by using the package +// path to disambiguate) if a package that appears multiple times with +// the same name appears in an error message. +var NumImport = make(map[string]int) + +// Format conversions: +// TODO(gri) verify these; eliminate those not used anymore +// +// %v Op Node opcodes +// Flags: #: print Go syntax (automatic unless mode == FDbg) +// +// %j *Node Node details +// Flags: 0: suppresses things not relevant until walk +// +// %v *Val Constant values +// +// %v *types.Sym Symbols +// %S unqualified identifier in any mode +// Flags: +,- #: mode (see below) +// 0: in export mode: unqualified identifier if exported, qualified if not +// +// %v *types.Type Types +// %S omit "func" and receiver in function types +// %L definition instead of name. +// Flags: +,- #: mode (see below) +// ' ' (only in -/Sym mode) print type identifiers wit package name instead of prefix. +// +// %v *Node Nodes +// %S (only in +/debug mode) suppress recursion +// %L (only in Error mode) print "foo (type Bar)" +// Flags: +,- #: mode (see below) +// +// %v Nodes Node lists +// Flags: those of *Node +// .: separate items with ',' instead of ';' + +// *types.Sym, *types.Type, and *Node types use the flags below to set the format mode + +// The mode flags '+', '-', and '#' are sticky; they persist through +// recursions of *Node, *types.Type, and *types.Sym values. The ' ' flag is +// sticky only on *types.Type recursions and only used in %-/*types.Sym mode. +// +// Example: given a *types.Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode + +// Useful format combinations: +// TODO(gri): verify these +// +// *Node, Nodes: +// %+v multiline recursive debug dump of *Node/Nodes +// %+S non-recursive debug dump +// +// *Node: +// %#v Go format +// %L "foo (type Bar)" for error messages +// +// *types.Type: +// %#v Go format +// %#L type definition instead of name +// %#S omit "func" and receiver in function signature +// +// %-v type identifiers +// %-S type identifiers without "func" and arg names in type signatures (methodsym) +// %- v type identifiers with package name instead of prefix (typesym, dcommontype, typehash) + +type fmtMode int + +const ( + fmtGo fmtMode = iota + fmtDebug + fmtTypeID + fmtTypeIDName // same as FTypeId, but use package name instead of prefix +) + +// "%S" suppresses qualifying with package +func symFormat(s *Sym, f fmt.State, verb rune) { + mode := fmtGo + switch verb { + case 'v', 'S': + if verb == 'v' && f.Flag('+') { + mode = fmtDebug + } + fmt.Fprint(f, sconv(s, verb, mode)) + + default: + fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s) + } +} + +// See #16897 for details about performance implications +// before changing the implementation of sconv. +func sconv(s *Sym, verb rune, mode fmtMode) string { + if verb == 'L' { + panic("linksymfmt") + } + + if s == nil { + return "" + } + + if s.Name == "_" { + return "_" + } + buf := fmtBufferPool.Get().(*bytes.Buffer) + buf.Reset() + defer fmtBufferPool.Put(buf) + + symfmt(buf, s, verb, mode) + return InternString(buf.Bytes()) +} + +func sconv2(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) { + if verb == 'L' { + panic("linksymfmt") + } + if s == nil { + b.WriteString("") + return + } + if s.Name == "_" { + b.WriteString("_") + return + } + + symfmt(b, s, verb, mode) +} + +func symfmt(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) { + if verb != 'S' { + switch mode { + case fmtGo: // This is for the user + if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg { + b.WriteString(s.Name) + return + } + + // If the name was used by multiple packages, display the full path, + if s.Pkg.Name != "" && NumImport[s.Pkg.Name] > 1 { + fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name) + return + } + b.WriteString(s.Pkg.Name) + b.WriteByte('.') + b.WriteString(s.Name) + return + + case fmtDebug: + b.WriteString(s.Pkg.Name) + b.WriteByte('.') + b.WriteString(s.Name) + return + + case fmtTypeIDName: + // dcommontype, typehash + b.WriteString(s.Pkg.Name) + b.WriteByte('.') + b.WriteString(s.Name) + return + + case fmtTypeID: + // (methodsym), typesym, weaksym + b.WriteString(s.Pkg.Prefix) + b.WriteByte('.') + b.WriteString(s.Name) + return + } + } + + b.WriteString(s.Name) +} + +func SymMethodName(s *Sym) string { + // Skip leading "type." in method name + name := s.Name + if i := strings.LastIndex(name, "."); i >= 0 { + name = name[i+1:] + } + return name +} + +// Type + +var BasicTypeNames = []string{ + TINT: "int", + TUINT: "uint", + TINT8: "int8", + TUINT8: "uint8", + TINT16: "int16", + TUINT16: "uint16", + TINT32: "int32", + TUINT32: "uint32", + TINT64: "int64", + TUINT64: "uint64", + TUINTPTR: "uintptr", + TFLOAT32: "float32", + TFLOAT64: "float64", + TCOMPLEX64: "complex64", + TCOMPLEX128: "complex128", + TBOOL: "bool", + TANY: "any", + TSTRING: "string", + TNIL: "nil", + TIDEAL: "untyped number", + TBLANK: "blank", +} + +var fmtBufferPool = sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, +} + +func InstallTypeFormats() { + SymString = func(s *Sym) string { + return sconv(s, 0, fmtGo) + } + TypeString = func(t *Type) string { + return tconv(t, 0, fmtGo) + } + TypeShortString = func(t *Type) string { + return tconv(t, 0, fmtTypeID) + } + TypeLongString = func(t *Type) string { + return tconv(t, 0, fmtTypeIDName) + } + FormatSym = symFormat + FormatType = typeFormat +} + +// "%L" print definition, not name +// "%S" omit 'func' and receiver from function types, short type names +func typeFormat(t *Type, s fmt.State, verb rune) { + mode := fmtGo + switch verb { + case 'v', 'S', 'L': + if verb == 'v' && s.Flag('+') { // %+v is debug format + mode = fmtDebug + } + if verb == 'S' && s.Flag('-') { // %-S is special case for receiver - short typeid format + mode = fmtTypeID + } + fmt.Fprint(s, tconv(t, verb, mode)) + default: + fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t) + } +} + +func tconv(t *Type, verb rune, mode fmtMode) string { + buf := fmtBufferPool.Get().(*bytes.Buffer) + buf.Reset() + defer fmtBufferPool.Put(buf) + + tconv2(buf, t, verb, mode, nil) + return InternString(buf.Bytes()) +} + +// tconv2 writes a string representation of t to b. +// flag and mode control exactly what is printed. +// Any types x that are already in the visited map get printed as @%d where %d=visited[x]. +// See #16897 before changing the implementation of tconv. +func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type]int) { + if off, ok := visited[t]; ok { + // We've seen this type before, so we're trying to print it recursively. + // Print a reference to it instead. + fmt.Fprintf(b, "@%d", off) + return + } + if t == nil { + b.WriteString("") + return + } + if t.Kind() == TSSA { + b.WriteString(t.Extra.(string)) + return + } + if t.Kind() == TTUPLE { + b.WriteString(t.FieldType(0).String()) + b.WriteByte(',') + b.WriteString(t.FieldType(1).String()) + return + } + + if t.Kind() == TRESULTS { + tys := t.Extra.(*Results).Types + for i, et := range tys { + if i > 0 { + b.WriteByte(',') + } + b.WriteString(et.String()) + } + return + } + + if t == ByteType || t == RuneType { + // in %-T mode collapse rune and byte with their originals. + switch mode { + case fmtTypeIDName, fmtTypeID: + t = Types[t.Kind()] + default: + sconv2(b, t.Sym(), 'S', mode) + return + } + } + if t == ErrorType { + b.WriteString("error") + return + } + + // Unless the 'L' flag was specified, if the type has a name, just print that name. + if verb != 'L' && t.Sym() != nil && t != Types[t.Kind()] { + switch mode { + case fmtTypeID, fmtTypeIDName: + if verb == 'S' { + if t.Vargen != 0 { + sconv2(b, t.Sym(), 'S', mode) + fmt.Fprintf(b, "·%d", t.Vargen) + return + } + sconv2(b, t.Sym(), 'S', mode) + return + } + + if mode == fmtTypeIDName { + sconv2(b, t.Sym(), 'v', fmtTypeIDName) + return + } + + if t.Sym().Pkg == LocalPkg && t.Vargen != 0 { + sconv2(b, t.Sym(), 'v', mode) + fmt.Fprintf(b, "·%d", t.Vargen) + return + } + } + + sconv2(b, t.Sym(), 'v', mode) + return + } + + if int(t.Kind()) < len(BasicTypeNames) && BasicTypeNames[t.Kind()] != "" { + var name string + switch t { + case UntypedBool: + name = "untyped bool" + case UntypedString: + name = "untyped string" + case UntypedInt: + name = "untyped int" + case UntypedRune: + name = "untyped rune" + case UntypedFloat: + name = "untyped float" + case UntypedComplex: + name = "untyped complex" + default: + name = BasicTypeNames[t.Kind()] + } + b.WriteString(name) + return + } + + if mode == fmtDebug { + b.WriteString(t.Kind().String()) + b.WriteByte('-') + tconv2(b, t, 'v', fmtGo, visited) + return + } + + // At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't + // try to print it recursively. + // We record the offset in the result buffer where the type's text starts. This offset serves as a reference + // point for any later references to the same type. + // Note that we remove the type from the visited map as soon as the recursive call is done. + // This prevents encoding types like map[*int]*int as map[*int]@4. (That encoding would work, + // but I'd like to use the @ notation only when strictly necessary.) + if visited == nil { + visited = map[*Type]int{} + } + visited[t] = b.Len() + defer delete(visited, t) + + switch t.Kind() { + case TPTR: + b.WriteByte('*') + switch mode { + case fmtTypeID, fmtTypeIDName: + if verb == 'S' { + tconv2(b, t.Elem(), 'S', mode, visited) + return + } + } + tconv2(b, t.Elem(), 'v', mode, visited) + + case TARRAY: + b.WriteByte('[') + b.WriteString(strconv.FormatInt(t.NumElem(), 10)) + b.WriteByte(']') + tconv2(b, t.Elem(), 0, mode, visited) + + case TSLICE: + b.WriteString("[]") + tconv2(b, t.Elem(), 0, mode, visited) + + case TCHAN: + switch t.ChanDir() { + case Crecv: + b.WriteString("<-chan ") + tconv2(b, t.Elem(), 0, mode, visited) + case Csend: + b.WriteString("chan<- ") + tconv2(b, t.Elem(), 0, mode, visited) + default: + b.WriteString("chan ") + if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym() == nil && t.Elem().ChanDir() == Crecv { + b.WriteByte('(') + tconv2(b, t.Elem(), 0, mode, visited) + b.WriteByte(')') + } else { + tconv2(b, t.Elem(), 0, mode, visited) + } + } + + case TMAP: + b.WriteString("map[") + tconv2(b, t.Key(), 0, mode, visited) + b.WriteByte(']') + tconv2(b, t.Elem(), 0, mode, visited) + + case TINTER: + if t.IsEmptyInterface() { + b.WriteString("interface {}") + break + } + b.WriteString("interface {") + for i, f := range t.Fields().Slice() { + if i != 0 { + b.WriteByte(';') + } + b.WriteByte(' ') + switch { + case f.Sym == nil: + // Check first that a symbol is defined for this type. + // Wrong interface definitions may have types lacking a symbol. + break + case IsExported(f.Sym.Name): + sconv2(b, f.Sym, 'S', mode) + default: + if mode != fmtTypeIDName { + mode = fmtTypeID + } + sconv2(b, f.Sym, 'v', mode) + } + tconv2(b, f.Type, 'S', mode, visited) + } + if t.NumFields() != 0 { + b.WriteByte(' ') + } + b.WriteByte('}') + + case TFUNC: + if verb == 'S' { + // no leading func + } else { + if t.Recv() != nil { + b.WriteString("method") + tconv2(b, t.Recvs(), 0, mode, visited) + b.WriteByte(' ') + } + b.WriteString("func") + } + tconv2(b, t.Params(), 0, mode, visited) + + switch t.NumResults() { + case 0: + // nothing to do + + case 1: + b.WriteByte(' ') + tconv2(b, t.Results().Field(0).Type, 0, mode, visited) // struct->field->field's type + + default: + b.WriteByte(' ') + tconv2(b, t.Results(), 0, mode, visited) + } + + case TSTRUCT: + if m := t.StructType().Map; m != nil { + mt := m.MapType() + // Format the bucket struct for map[x]y as map.bucket[x]y. + // This avoids a recursive print that generates very long names. + switch t { + case mt.Bucket: + b.WriteString("map.bucket[") + case mt.Hmap: + b.WriteString("map.hdr[") + case mt.Hiter: + b.WriteString("map.iter[") + default: + base.Fatalf("unknown internal map type") + } + tconv2(b, m.Key(), 0, mode, visited) + b.WriteByte(']') + tconv2(b, m.Elem(), 0, mode, visited) + break + } + + if funarg := t.StructType().Funarg; funarg != FunargNone { + b.WriteByte('(') + fieldVerb := 'v' + switch mode { + case fmtTypeID, fmtTypeIDName, fmtGo: + // no argument names on function signature, and no "noescape"/"nosplit" tags + fieldVerb = 'S' + } + for i, f := range t.Fields().Slice() { + if i != 0 { + b.WriteString(", ") + } + fldconv(b, f, fieldVerb, mode, visited, funarg) + } + b.WriteByte(')') + } else { + b.WriteString("struct {") + for i, f := range t.Fields().Slice() { + if i != 0 { + b.WriteByte(';') + } + b.WriteByte(' ') + fldconv(b, f, 'L', mode, visited, funarg) + } + if t.NumFields() != 0 { + b.WriteByte(' ') + } + b.WriteByte('}') + } + + case TFORW: + b.WriteString("undefined") + if t.Sym() != nil { + b.WriteByte(' ') + sconv2(b, t.Sym(), 'v', mode) + } + + case TUNSAFEPTR: + b.WriteString("unsafe.Pointer") + + case Txxx: + b.WriteString("Txxx") + + default: + // Don't know how to handle - fall back to detailed prints + b.WriteString(t.Kind().String()) + b.WriteString(" <") + sconv2(b, t.Sym(), 'v', mode) + b.WriteString(">") + + } +} + +func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Type]int, funarg Funarg) { + if f == nil { + b.WriteString("") + return + } + + var name string + if verb != 'S' { + s := f.Sym + + // Take the name from the original. + if mode == fmtGo { + s = OrigSym(s) + } + + if s != nil && f.Embedded == 0 { + if funarg != FunargNone { + name = fmt.Sprint(f.Nname) + } else if verb == 'L' { + name = SymMethodName(s) + if !IsExported(name) && mode != fmtTypeIDName { + name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg) + } + } else { + name = sconv(s, 0, mode) + } + } + } + + if name != "" { + b.WriteString(name) + b.WriteString(" ") + } + + if f.IsDDD() { + var et *Type + if f.Type != nil { + et = f.Type.Elem() + } + b.WriteString("...") + tconv2(b, et, 0, mode, visited) + } else { + tconv2(b, f.Type, 0, mode, visited) + } + + if verb != 'S' && funarg == FunargNone && f.Note != "" { + b.WriteString(" ") + b.WriteString(strconv.Quote(f.Note)) + } +} + +// Val + +func FmtConst(v constant.Value, sharp bool) string { + if !sharp && v.Kind() == constant.Complex { + real, imag := constant.Real(v), constant.Imag(v) + + var re string + sre := constant.Sign(real) + if sre != 0 { + re = real.String() + } + + var im string + sim := constant.Sign(imag) + if sim != 0 { + im = imag.String() + } + + switch { + case sre == 0 && sim == 0: + return "0" + case sre == 0: + return im + "i" + case sim == 0: + return re + case sim < 0: + return fmt.Sprintf("(%s%si)", re, im) + default: + return fmt.Sprintf("(%s+%si)", re, im) + } + } + + return v.String() +} From 6ea2b8c54cbc2d3a03d5dd174bc7526d33459d37 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 6 Dec 2020 14:15:09 -0500 Subject: [PATCH 174/212] [dev.regabi] cmd/compile: clean up and document formatting Some cleanup left over from moving the Type and Sym formatting to types. And then document what the type formats are, now that it's clear. Passes buildall w/ toolstash -cmp. Change-Id: I35cb8978f1627db1056cb8ab343ce6ba6c99afad Reviewed-on: https://go-review.googlesource.com/c/go/+/275780 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/main.go | 1 - src/cmd/compile/internal/ir/fmt.go | 35 ++++- src/cmd/compile/internal/ssa/export_test.go | 1 - src/cmd/compile/internal/types/fmt.go | 141 ++++++++------------ src/cmd/compile/internal/types/utils.go | 45 +------ 5 files changed, 87 insertions(+), 136 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 15659dc7fd..503dc449d3 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -212,7 +212,6 @@ func Main(archInit func(*Arch)) { // would lead to import cycles) types.Widthptr = Widthptr types.Dowidth = dowidth - types.InstallTypeFormats() types.TypeLinkSym = func(t *types.Type) *obj.LSym { return typenamesym(t).Linksym() } diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 79d85d1803..85c6b218e2 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -86,6 +86,7 @@ var OpNames = []string{ OXOR: "^", } +// GoString returns the Go syntax for the Op, or else its name. func (o Op) GoString() string { if int(o) < len(OpNames) && OpNames[o] != "" { return OpNames[o] @@ -93,6 +94,12 @@ func (o Op) GoString() string { return o.String() } +// Format implements formatting for an Op. +// The valid formats are: +// +// %v Go syntax ("+", "<-", "print") +// %+v Debug syntax ("ADD", "RECV", "PRINT") +// func (o Op) Format(s fmt.State, verb rune) { switch verb { default: @@ -109,6 +116,14 @@ func (o Op) Format(s fmt.State, verb rune) { // Node +// FmtNode implements formatting for a Node n. +// Every Node implementation must define a Format method that calls FmtNode. +// The valid formats are: +// +// %v Go syntax +// %L Go syntax followed by " (type T)" if type is known. +// %+v Debug syntax, as in Dump. +// func FmtNode(n Node, s fmt.State, verb rune) { // TODO(rsc): Remove uses of %#v, which behaves just like %v. // TODO(rsc): Remove uses of %S, which behaves just like %v. @@ -276,7 +291,7 @@ var OpPrec = []int{ OEND: 0, } -// Statements which may be rendered with a simplestmt as init. +// StmtWithInit reports whether op is a statement with an explicit init list. func StmtWithInit(op Op) bool { switch op { case OIF, OFOR, OFORUNTIL, OSWITCH: @@ -869,6 +884,13 @@ func ellipsisIf(b bool) string { // Nodes +// Format implements formatting for a Nodes. +// The valid formats are: +// +// %v Go syntax, semicolon-separated +// %.v Go syntax, comma-separated +// %+v Debug syntax, as in DumpList. +// func (l Nodes) Format(s fmt.State, verb rune) { if s.Flag('+') && verb == 'v' { // %+v is DumpList output @@ -896,19 +918,22 @@ func (l Nodes) Format(s fmt.State, verb rune) { // Dump +// Dump prints the message s followed by a debug dump of n. func Dump(s string, n Node) { fmt.Printf("%s [%p]%+v", s, n, n) } -func DumpList(s string, l Nodes) { +// DumpList prints the message s followed by a debug dump of each node in the list. +func DumpList(s string, list Nodes) { var buf bytes.Buffer - FDumpList(&buf, s, l) + FDumpList(&buf, s, list) os.Stdout.Write(buf.Bytes()) } -func FDumpList(w io.Writer, s string, l Nodes) { +// FDumpList prints to w the message s followed by a debug dump of each node in the list. +func FDumpList(w io.Writer, s string, list Nodes) { io.WriteString(w, s) - dumpNodes(w, l, 1) + dumpNodes(w, list, 1) io.WriteString(w, "\n") } diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index decb843465..55fce31088 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -137,7 +137,6 @@ func init() { // Initialize just enough of the universe and the types package to make our tests function. // TODO(josharian): move universe initialization to the types package, // so this test setup can share it. - types.InstallTypeFormats() types.Dowidth = func(t *types.Type) {} for _, typ := range [...]struct { diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index 4f36e4c393..d63f7a4f8d 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -15,14 +15,16 @@ import ( "cmd/compile/internal/base" ) -// builtinpkg is a fake package that declares the universe block. +// BuiltinPkg is a fake package that declares the universe block. var BuiltinPkg *Pkg -var LocalPkg *Pkg // package being compiled +// LocalPkg is the package being compiled. +var LocalPkg *Pkg +// BlankSym is the blank (_) symbol. var BlankSym *Sym -// origSym returns the original symbol written by the user. +// OrigSym returns the original symbol written by the user. func OrigSym(s *Sym) *Sym { if s == nil { return nil @@ -47,84 +49,36 @@ func OrigSym(s *Sym) *Sym { return s } -// Sym - // numImport tracks how often a package with a given name is imported. // It is used to provide a better error message (by using the package // path to disambiguate) if a package that appears multiple times with // the same name appears in an error message. var NumImport = make(map[string]int) -// Format conversions: -// TODO(gri) verify these; eliminate those not used anymore -// -// %v Op Node opcodes -// Flags: #: print Go syntax (automatic unless mode == FDbg) -// -// %j *Node Node details -// Flags: 0: suppresses things not relevant until walk -// -// %v *Val Constant values -// -// %v *types.Sym Symbols -// %S unqualified identifier in any mode -// Flags: +,- #: mode (see below) -// 0: in export mode: unqualified identifier if exported, qualified if not -// -// %v *types.Type Types -// %S omit "func" and receiver in function types -// %L definition instead of name. -// Flags: +,- #: mode (see below) -// ' ' (only in -/Sym mode) print type identifiers wit package name instead of prefix. -// -// %v *Node Nodes -// %S (only in +/debug mode) suppress recursion -// %L (only in Error mode) print "foo (type Bar)" -// Flags: +,- #: mode (see below) -// -// %v Nodes Node lists -// Flags: those of *Node -// .: separate items with ',' instead of ';' - -// *types.Sym, *types.Type, and *Node types use the flags below to set the format mode - -// The mode flags '+', '-', and '#' are sticky; they persist through -// recursions of *Node, *types.Type, and *types.Sym values. The ' ' flag is -// sticky only on *types.Type recursions and only used in %-/*types.Sym mode. -// -// Example: given a *types.Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode - -// Useful format combinations: -// TODO(gri): verify these -// -// *Node, Nodes: -// %+v multiline recursive debug dump of *Node/Nodes -// %+S non-recursive debug dump -// -// *Node: -// %#v Go format -// %L "foo (type Bar)" for error messages -// -// *types.Type: -// %#v Go format -// %#L type definition instead of name -// %#S omit "func" and receiver in function signature -// -// %-v type identifiers -// %-S type identifiers without "func" and arg names in type signatures (methodsym) -// %- v type identifiers with package name instead of prefix (typesym, dcommontype, typehash) - +// fmtMode represents the kind of printing being done. +// The default is regular Go syntax (fmtGo). +// fmtDebug is like fmtGo but for debugging dumps and prints the type kind too. +// fmtTypeID and fmtTypeIDName are for generating various unique representations +// of types used in hashes and the linker. type fmtMode int const ( fmtGo fmtMode = iota fmtDebug fmtTypeID - fmtTypeIDName // same as FTypeId, but use package name instead of prefix + fmtTypeIDName ) -// "%S" suppresses qualifying with package -func symFormat(s *Sym, f fmt.State, verb rune) { +// Sym + +// Format implements formatting for a Sym. +// The valid formats are: +// +// %v Go syntax: Name for symbols in the local package, PkgName.Name for imported symbols. +// %+v Debug syntax: always include PkgName. prefix even for local names. +// %S Short syntax: Name only, no matter what. +// +func (s *Sym) Format(f fmt.State, verb rune) { mode := fmtGo switch verb { case 'v', 'S': @@ -138,6 +92,10 @@ func symFormat(s *Sym, f fmt.State, verb rune) { } } +func (s *Sym) String() string { + return sconv(s, 0, fmtGo) +} + // See #16897 for details about performance implications // before changing the implementation of sconv. func sconv(s *Sym, verb rune, mode fmtMode) string { @@ -261,26 +219,16 @@ var fmtBufferPool = sync.Pool{ }, } -func InstallTypeFormats() { - SymString = func(s *Sym) string { - return sconv(s, 0, fmtGo) - } - TypeString = func(t *Type) string { - return tconv(t, 0, fmtGo) - } - TypeShortString = func(t *Type) string { - return tconv(t, 0, fmtTypeID) - } - TypeLongString = func(t *Type) string { - return tconv(t, 0, fmtTypeIDName) - } - FormatSym = symFormat - FormatType = typeFormat -} - -// "%L" print definition, not name -// "%S" omit 'func' and receiver from function types, short type names -func typeFormat(t *Type, s fmt.State, verb rune) { +// Format implements formatting for a Type. +// The valid formats are: +// +// %v Go syntax +// %+v Debug syntax: Go syntax with a KIND- prefix for all but builtins. +// %L Go syntax for underlying type if t is named +// %S short Go syntax: drop leading "func" in function type +// %-S special case for method receiver symbol +// +func (t *Type) Format(s fmt.State, verb rune) { mode := fmtGo switch verb { case 'v', 'S', 'L': @@ -296,6 +244,25 @@ func typeFormat(t *Type, s fmt.State, verb rune) { } } +// String returns the Go syntax for the type t. +func (t *Type) String() string { + return tconv(t, 0, fmtGo) +} + +// ShortString generates a short description of t. +// It is used in autogenerated method names, reflection, +// and itab names. +func (t *Type) ShortString() string { + return tconv(t, 0, fmtTypeID) +} + +// LongString generates a complete description of t. +// It is useful for reflection, +// or when a unique fingerprint or hash of a type is required. +func (t *Type) LongString() string { + return tconv(t, 0, fmtTypeIDName) +} + func tconv(t *Type, verb rune, mode fmtMode) string { buf := fmtBufferPool.Get().(*bytes.Buffer) buf.Reset() diff --git a/src/cmd/compile/internal/types/utils.go b/src/cmd/compile/internal/types/utils.go index a1be77eef1..531f3ea1ca 100644 --- a/src/cmd/compile/internal/types/utils.go +++ b/src/cmd/compile/internal/types/utils.go @@ -6,7 +6,6 @@ package types import ( "cmd/internal/obj" - "fmt" ) const BADWIDTH = -1000000000 @@ -15,49 +14,11 @@ const BADWIDTH = -1000000000 // They are here to break import cycles. // TODO(gri) eliminate these dependencies. var ( - Widthptr int - Dowidth func(*Type) - SymString func(*Sym) string - TypeString func(*Type) string - TypeShortString func(*Type) string - TypeLongString func(*Type) string - FormatSym func(*Sym, fmt.State, rune) - FormatType func(*Type, fmt.State, rune) - TypeLinkSym func(*Type) *obj.LSym + Widthptr int + Dowidth func(*Type) + TypeLinkSym func(*Type) *obj.LSym ) -func (s *Sym) String() string { - return SymString(s) -} - -func (sym *Sym) Format(s fmt.State, verb rune) { - FormatSym(sym, s, verb) -} - -func (t *Type) String() string { - // The implementation - // must handle recursive types correctly. - return TypeString(t) -} - -// ShortString generates a short description of t. -// It is used in autogenerated method names, reflection, -// and itab names. -func (t *Type) ShortString() string { - return TypeShortString(t) -} - -// LongString generates a complete description of t. -// It is useful for reflection, -// or when a unique fingerprint or hash of a type is required. -func (t *Type) LongString() string { - return TypeLongString(t) -} - -func (t *Type) Format(s fmt.State, verb rune) { - FormatType(t, s, verb) -} - type bitset8 uint8 func (f *bitset8) set(mask uint8, b bool) { From 61889ba68098fa0e79e0b182f3b8c38b69c9b36c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 6 Dec 2020 14:33:06 -0500 Subject: [PATCH 175/212] [dev.regabi] cmd/compile: simplify fmtmap The format map is going to keep growing as we add more use of concrete node types. Stop that by reporting all Node implementations as Node. Also, there's little point to reporting uses of %v, %p, %T, nor to reporting formatting of basic types like int and []byte. Remove those too. (Vet takes care of mistakes involving basic types now.) Passes buildall w/ toolstash -cmp. Change-Id: Ia9fb39b401c29bf0c76ffebaa24836c70acd773f Reviewed-on: https://go-review.googlesource.com/c/go/+/275781 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/fmt_test.go | 18 ++- src/cmd/compile/fmtmap_test.go | 242 ++++++++------------------------- 2 files changed, 72 insertions(+), 188 deletions(-) diff --git a/src/cmd/compile/fmt_test.go b/src/cmd/compile/fmt_test.go index 6625ccf5e2..6398a84f8f 100644 --- a/src/cmd/compile/fmt_test.go +++ b/src/cmd/compile/fmt_test.go @@ -125,6 +125,12 @@ func TestFormats(t *testing.T) { typ := p.types[index] format := typ + " " + in // e.g., "*Node %n" + // Do not bother reporting basic types, nor %v, %T, %p. + // Vet handles basic types, and those three formats apply to all types. + if !strings.Contains(typ, ".") || (in == "%v" || in == "%T" || in == "%p") { + return in + } + // check if format is known out, known := knownFormats[format] @@ -413,7 +419,17 @@ func nodeString(n ast.Node) string { // typeString returns a string representation of n. func typeString(typ types.Type) string { - return filepath.ToSlash(typ.String()) + s := filepath.ToSlash(typ.String()) + + // Report all the concrete IR types as Node, to shorten fmtmap. + const ir = "cmd/compile/internal/ir." + if s == "*"+ir+"Name" || s == "*"+ir+"Func" || s == "*"+ir+"Decl" || + s == ir+"Ntype" || s == ir+"Expr" || s == ir+"Stmt" || + strings.HasPrefix(s, "*"+ir) && (strings.HasSuffix(s, "Expr") || strings.HasSuffix(s, "Stmt")) { + return "cmd/compile/internal/ir.Node" + } + + return s } // stringLit returns the unquoted string value and true if diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index 5dd30e619b..ca6f1c302e 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -20,191 +20,59 @@ package main_test // An absent entry means that the format is not recognized as valid. // An empty new format means that the format should remain unchanged. var knownFormats = map[string]string{ - "*bytes.Buffer %s": "", - "*cmd/compile/internal/gc.EscLocation %v": "", - "*cmd/compile/internal/ir.Func %+v": "", - "*cmd/compile/internal/ir.Func %L": "", - "*cmd/compile/internal/ir.Func %v": "", - "*cmd/compile/internal/ir.Name %#v": "", - "*cmd/compile/internal/ir.Name %+v": "", - "*cmd/compile/internal/ir.Name %L": "", - "*cmd/compile/internal/ir.Name %v": "", - "*cmd/compile/internal/ir.SliceExpr %v": "", - "*cmd/compile/internal/ssa.Block %s": "", - "*cmd/compile/internal/ssa.Block %v": "", - "*cmd/compile/internal/ssa.Func %s": "", - "*cmd/compile/internal/ssa.Func %v": "", - "*cmd/compile/internal/ssa.Register %s": "", - "*cmd/compile/internal/ssa.Register %v": "", - "*cmd/compile/internal/ssa.SparseTreeNode %v": "", - "*cmd/compile/internal/ssa.Value %s": "", - "*cmd/compile/internal/ssa.Value %v": "", - "*cmd/compile/internal/ssa.sparseTreeMapEntry %v": "", - "*cmd/compile/internal/types.Field %p": "", - "*cmd/compile/internal/types.Field %v": "", - "*cmd/compile/internal/types.Sym %+v": "", - "*cmd/compile/internal/types.Sym %S": "", - "*cmd/compile/internal/types.Sym %p": "", - "*cmd/compile/internal/types.Sym %v": "", - "*cmd/compile/internal/types.Type %#L": "", - "*cmd/compile/internal/types.Type %#v": "", - "*cmd/compile/internal/types.Type %+v": "", - "*cmd/compile/internal/types.Type %-S": "", - "*cmd/compile/internal/types.Type %0S": "", - "*cmd/compile/internal/types.Type %L": "", - "*cmd/compile/internal/types.Type %S": "", - "*cmd/compile/internal/types.Type %p": "", - "*cmd/compile/internal/types.Type %s": "", - "*cmd/compile/internal/types.Type %v": "", - "*cmd/internal/obj.Addr %v": "", - "*cmd/internal/obj.LSym %v": "", - "*math/big.Float %f": "", - "*math/big.Int %s": "", - "[16]byte %x": "", - "[]*cmd/compile/internal/ir.Name %v": "", - "[]*cmd/compile/internal/ssa.Block %v": "", - "[]*cmd/compile/internal/ssa.Value %v": "", - "[][]string %q": "", - "[]byte %s": "", - "[]byte %x": "", - "[]cmd/compile/internal/ssa.Edge %v": "", - "[]cmd/compile/internal/ssa.ID %v": "", - "[]cmd/compile/internal/ssa.posetNode %v": "", - "[]cmd/compile/internal/ssa.posetUndo %v": "", - "[]cmd/compile/internal/syntax.token %s": "", - "[]string %v": "", - "[]uint32 %v": "", - "bool %v": "", - "byte %08b": "", - "byte %c": "", - "byte %q": "", - "byte %v": "", - "cmd/compile/internal/arm.shift %d": "", - "cmd/compile/internal/gc.initKind %d": "", - "cmd/compile/internal/gc.itag %v": "", - "cmd/compile/internal/ir.Class %d": "", - "cmd/compile/internal/ir.Class %v": "", - "cmd/compile/internal/ir.Node %+v": "", - "cmd/compile/internal/ir.Node %L": "", - "cmd/compile/internal/ir.Node %S": "", - "cmd/compile/internal/ir.Node %p": "", - "cmd/compile/internal/ir.Node %v": "", - "cmd/compile/internal/ir.Nodes %#v": "", - "cmd/compile/internal/ir.Nodes %+v": "", - "cmd/compile/internal/ir.Nodes %.v": "", - "cmd/compile/internal/ir.Nodes %v": "", - "cmd/compile/internal/ir.Ntype %v": "", - "cmd/compile/internal/ir.Op %#v": "", - "cmd/compile/internal/ir.Op %+v": "", - "cmd/compile/internal/ir.Op %v": "", - "cmd/compile/internal/ssa.BranchPrediction %d": "", - "cmd/compile/internal/ssa.Edge %v": "", - "cmd/compile/internal/ssa.ID %d": "", - "cmd/compile/internal/ssa.ID %v": "", - "cmd/compile/internal/ssa.LocalSlot %s": "", - "cmd/compile/internal/ssa.LocalSlot %v": "", - "cmd/compile/internal/ssa.Location %s": "", - "cmd/compile/internal/ssa.Op %s": "", - "cmd/compile/internal/ssa.Op %v": "", - "cmd/compile/internal/ssa.Sym %v": "", - "cmd/compile/internal/ssa.ValAndOff %s": "", - "cmd/compile/internal/ssa.domain %v": "", - "cmd/compile/internal/ssa.flagConstant %s": "", - "cmd/compile/internal/ssa.posetNode %v": "", - "cmd/compile/internal/ssa.posetTestOp %v": "", - "cmd/compile/internal/ssa.rbrank %d": "", - "cmd/compile/internal/ssa.regMask %d": "", - "cmd/compile/internal/ssa.register %d": "", - "cmd/compile/internal/ssa.relation %s": "", - "cmd/compile/internal/syntax.Error %q": "", - "cmd/compile/internal/syntax.Expr %#v": "", - "cmd/compile/internal/syntax.LitKind %d": "", - "cmd/compile/internal/syntax.Node %T": "", - "cmd/compile/internal/syntax.Operator %s": "", - "cmd/compile/internal/syntax.Pos %s": "", - "cmd/compile/internal/syntax.Pos %v": "", - "cmd/compile/internal/syntax.position %s": "", - "cmd/compile/internal/syntax.token %q": "", - "cmd/compile/internal/syntax.token %s": "", - "cmd/compile/internal/types.Kind %d": "", - "cmd/compile/internal/types.Kind %s": "", - "cmd/compile/internal/types.Kind %v": "", - "cmd/compile/internal/types.Object %v": "", - "cmd/internal/obj.ABI %v": "", - "error %v": "", - "float64 %.2f": "", - "float64 %.3f": "", - "float64 %g": "", - "go/constant.Kind %v": "", - "go/constant.Value %#v": "", - "go/constant.Value %v": "", - "int %#x": "", - "int %-12d": "", - "int %-6d": "", - "int %-8o": "", - "int %02d": "", - "int %6d": "", - "int %c": "", - "int %d": "", - "int %v": "", - "int %x": "", - "int16 %d": "", - "int16 %x": "", - "int32 %#x": "", - "int32 %d": "", - "int32 %v": "", - "int32 %x": "", - "int64 %#x": "", - "int64 %-10d": "", - "int64 %.5d": "", - "int64 %d": "", - "int64 %v": "", - "int64 %x": "", - "int8 %d": "", - "int8 %v": "", - "int8 %x": "", - "interface{} %#v": "", - "interface{} %T": "", - "interface{} %p": "", - "interface{} %q": "", - "interface{} %s": "", - "interface{} %v": "", - "map[cmd/compile/internal/ir.Node]*cmd/compile/internal/ssa.Value %v": "", - "map[cmd/compile/internal/ir.Node][]cmd/compile/internal/ir.Node %v": "", - "map[cmd/compile/internal/ssa.ID]uint32 %v": "", - "map[int64]uint32 %v": "", - "math/big.Accuracy %s": "", - "reflect.Type %s": "", - "reflect.Type %v": "", - "rune %#U": "", - "rune %c": "", - "rune %q": "", - "string %-*s": "", - "string %-16s": "", - "string %-6s": "", - "string %q": "", - "string %s": "", - "string %v": "", - "time.Duration %d": "", - "time.Duration %v": "", - "uint %04x": "", - "uint %5d": "", - "uint %d": "", - "uint %x": "", - "uint16 %d": "", - "uint16 %x": "", - "uint32 %#U": "", - "uint32 %#x": "", - "uint32 %d": "", - "uint32 %v": "", - "uint32 %x": "", - "uint64 %08x": "", - "uint64 %b": "", - "uint64 %d": "", - "uint64 %x": "", - "uint8 %#x": "", - "uint8 %d": "", - "uint8 %v": "", - "uint8 %x": "", - "uintptr %d": "", + "*bytes.Buffer %s": "", + "*cmd/compile/internal/ssa.Block %s": "", + "*cmd/compile/internal/ssa.Func %s": "", + "*cmd/compile/internal/ssa.Register %s": "", + "*cmd/compile/internal/ssa.Value %s": "", + "*cmd/compile/internal/types.Sym %+v": "", + "*cmd/compile/internal/types.Sym %S": "", + "*cmd/compile/internal/types.Type %#L": "", + "*cmd/compile/internal/types.Type %#v": "", + "*cmd/compile/internal/types.Type %+v": "", + "*cmd/compile/internal/types.Type %-S": "", + "*cmd/compile/internal/types.Type %0S": "", + "*cmd/compile/internal/types.Type %L": "", + "*cmd/compile/internal/types.Type %S": "", + "*cmd/compile/internal/types.Type %s": "", + "*math/big.Float %f": "", + "*math/big.Int %s": "", + "[]cmd/compile/internal/syntax.token %s": "", + "cmd/compile/internal/arm.shift %d": "", + "cmd/compile/internal/gc.initKind %d": "", + "cmd/compile/internal/ir.Class %d": "", + "cmd/compile/internal/ir.Node %#v": "", + "cmd/compile/internal/ir.Node %+v": "", + "cmd/compile/internal/ir.Node %L": "", + "cmd/compile/internal/ir.Node %S": "", + "cmd/compile/internal/ir.Nodes %#v": "", + "cmd/compile/internal/ir.Nodes %+v": "", + "cmd/compile/internal/ir.Nodes %.v": "", + "cmd/compile/internal/ir.Op %#v": "", + "cmd/compile/internal/ir.Op %+v": "", + "cmd/compile/internal/ssa.BranchPrediction %d": "", + "cmd/compile/internal/ssa.ID %d": "", + "cmd/compile/internal/ssa.LocalSlot %s": "", + "cmd/compile/internal/ssa.Location %s": "", + "cmd/compile/internal/ssa.Op %s": "", + "cmd/compile/internal/ssa.ValAndOff %s": "", + "cmd/compile/internal/ssa.flagConstant %s": "", + "cmd/compile/internal/ssa.rbrank %d": "", + "cmd/compile/internal/ssa.regMask %d": "", + "cmd/compile/internal/ssa.register %d": "", + "cmd/compile/internal/ssa.relation %s": "", + "cmd/compile/internal/syntax.Error %q": "", + "cmd/compile/internal/syntax.Expr %#v": "", + "cmd/compile/internal/syntax.LitKind %d": "", + "cmd/compile/internal/syntax.Operator %s": "", + "cmd/compile/internal/syntax.Pos %s": "", + "cmd/compile/internal/syntax.position %s": "", + "cmd/compile/internal/syntax.token %q": "", + "cmd/compile/internal/syntax.token %s": "", + "cmd/compile/internal/types.Kind %d": "", + "cmd/compile/internal/types.Kind %s": "", + "go/constant.Value %#v": "", + "math/big.Accuracy %s": "", + "reflect.Type %s": "", + "time.Duration %d": "", } From 724374f85985d6ce5e5a8a32b4b9aea22ead6dc3 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 6 Dec 2020 14:53:38 -0500 Subject: [PATCH 176/212] [dev.regabi] cmd/compile: rewrite stale format strings On ir.Node, ir.Nodes, and ir.Op, # is ignored, so %#v is %v. On ir.Node, %S is the same as %v. On types.Type, # is ignored, so %#L is %L, %#v is %v. On types.Type, 0 is ignored, so %0S is %S. Rewrite all these using go test cmd/compile -r, plus a few multiline formats mentioning %0S on types updated by hand. Now the formats used in the compiler match the documentation for the format methods, a minor miracle. Passes buildall w/ toolstash -cmp. Change-Id: I3d4a3fae543145a68da13eede91166632c5b1ceb Reviewed-on: https://go-review.googlesource.com/c/go/+/275782 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/fmtmap_test.go | 7 ------ src/cmd/compile/internal/gc/closure.go | 2 +- src/cmd/compile/internal/gc/escape.go | 6 ++--- src/cmd/compile/internal/gc/iimport.go | 4 ++-- src/cmd/compile/internal/gc/inl.go | 6 ++--- src/cmd/compile/internal/gc/pgen_test.go | 4 ++-- src/cmd/compile/internal/gc/subr.go | 4 ++-- src/cmd/compile/internal/gc/typecheck.go | 6 ++--- src/cmd/compile/internal/gc/unsafe.go | 2 +- src/cmd/compile/internal/gc/walk.go | 2 +- src/cmd/compile/internal/ir/fmt.go | 28 ++++++++++-------------- 11 files changed, 29 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index ca6f1c302e..756320285c 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -27,11 +27,8 @@ var knownFormats = map[string]string{ "*cmd/compile/internal/ssa.Value %s": "", "*cmd/compile/internal/types.Sym %+v": "", "*cmd/compile/internal/types.Sym %S": "", - "*cmd/compile/internal/types.Type %#L": "", - "*cmd/compile/internal/types.Type %#v": "", "*cmd/compile/internal/types.Type %+v": "", "*cmd/compile/internal/types.Type %-S": "", - "*cmd/compile/internal/types.Type %0S": "", "*cmd/compile/internal/types.Type %L": "", "*cmd/compile/internal/types.Type %S": "", "*cmd/compile/internal/types.Type %s": "", @@ -41,14 +38,10 @@ var knownFormats = map[string]string{ "cmd/compile/internal/arm.shift %d": "", "cmd/compile/internal/gc.initKind %d": "", "cmd/compile/internal/ir.Class %d": "", - "cmd/compile/internal/ir.Node %#v": "", "cmd/compile/internal/ir.Node %+v": "", "cmd/compile/internal/ir.Node %L": "", - "cmd/compile/internal/ir.Node %S": "", - "cmd/compile/internal/ir.Nodes %#v": "", "cmd/compile/internal/ir.Nodes %+v": "", "cmd/compile/internal/ir.Nodes %.v": "", - "cmd/compile/internal/ir.Op %#v": "", "cmd/compile/internal/ir.Op %+v": "", "cmd/compile/internal/ssa.BranchPrediction %d": "", "cmd/compile/internal/ssa.ID %d": "", diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 01e5a953de..b56e255d10 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -100,7 +100,7 @@ func typecheckclosure(clo ir.Node, top int) { if !n.Name().Captured() { n.Name().SetCaptured(true) if n.Name().Decldepth == 0 { - base.Fatalf("typecheckclosure: var %S does not have decldepth assigned", n) + base.Fatalf("typecheckclosure: var %v does not have decldepth assigned", n) } // Ignore assignments to the variable in straightline code diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index a7458ab733..f317e9999c 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -757,7 +757,7 @@ func (e *Escape) assign(dst, src ir.Node, why string, where ir.Node) { // Filter out some no-op assignments for escape analysis. ignore := dst != nil && src != nil && isSelfAssign(dst, src) if ignore && base.Flag.LowerM != 0 { - base.WarnfAt(where.Pos(), "%v ignoring self-assignment in %S", funcSym(e.curfn), where) + base.WarnfAt(where.Pos(), "%v ignoring self-assignment in %v", funcSym(e.curfn), where) } k := e.addr(dst) @@ -1454,7 +1454,7 @@ func (e *Escape) finish(fns []*ir.Func) { if loc.escapes { if n.Op() != ir.ONAME { if base.Flag.LowerM != 0 { - base.WarnfAt(n.Pos(), "%S escapes to heap", n) + base.WarnfAt(n.Pos(), "%v escapes to heap", n) } if logopt.Enabled() { logopt.LogOpt(n.Pos(), "escape", "escape", ir.FuncName(e.curfn)) @@ -1464,7 +1464,7 @@ func (e *Escape) finish(fns []*ir.Func) { addrescapes(n) } else { if base.Flag.LowerM != 0 && n.Op() != ir.ONAME { - base.WarnfAt(n.Pos(), "%S does not escape", n) + base.WarnfAt(n.Pos(), "%v does not escape", n) } n.SetEsc(EscNone) if loc.transient { diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 859263c83f..1f75393b3e 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -713,9 +713,9 @@ func (r *importReader) doInline(fn *ir.Func) { if base.Flag.E > 0 && base.Flag.LowerM > 2 { if base.Flag.LowerM > 3 { - fmt.Printf("inl body for %v %#v: %+v\n", fn, fn.Type(), ir.AsNodes(fn.Inl.Body)) + fmt.Printf("inl body for %v %v: %+v\n", fn, fn.Type(), ir.AsNodes(fn.Inl.Body)) } else { - fmt.Printf("inl body for %v %#v: %v\n", fn, fn.Type(), ir.AsNodes(fn.Inl.Body)) + fmt.Printf("inl body for %v %v: %v\n", fn, fn.Type(), ir.AsNodes(fn.Inl.Body)) } } } diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 77fbf7c802..f965fa6325 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -90,7 +90,7 @@ func typecheckinl(fn *ir.Func) { } if base.Flag.LowerM > 2 || base.Debug.Export != 0 { - fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym(), fn, ir.AsNodes(fn.Inl.Body)) + fmt.Printf("typecheck import [%v] %L { %v }\n", fn.Sym(), fn, ir.AsNodes(fn.Inl.Body)) } savefn := Curfn @@ -219,7 +219,7 @@ func caninl(fn *ir.Func) { } if base.Flag.LowerM > 1 { - fmt.Printf("%v: can inline %#v with cost %d as: %#v { %#v }\n", ir.Line(fn), n, inlineMaxBudget-visitor.budget, fn.Type(), ir.AsNodes(n.Func().Inl.Body)) + fmt.Printf("%v: can inline %v with cost %d as: %v { %v }\n", ir.Line(fn), n, inlineMaxBudget-visitor.budget, fn.Type(), ir.AsNodes(n.Func().Inl.Body)) } else if base.Flag.LowerM != 0 { fmt.Printf("%v: can inline %v\n", ir.Line(fn), n) } @@ -816,7 +816,7 @@ func mkinlcall(n ir.Node, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]bool, // We have a function node, and it has an inlineable body. if base.Flag.LowerM > 1 { - fmt.Printf("%v: inlining call to %v %#v { %#v }\n", ir.Line(n), fn.Sym(), fn.Type(), ir.AsNodes(fn.Inl.Body)) + fmt.Printf("%v: inlining call to %v %v { %v }\n", ir.Line(n), fn.Sym(), fn.Type(), ir.AsNodes(fn.Inl.Body)) } else if base.Flag.LowerM != 0 { fmt.Printf("%v: inlining call to %v\n", ir.Line(n), fn) } diff --git a/src/cmd/compile/internal/gc/pgen_test.go b/src/cmd/compile/internal/gc/pgen_test.go index 473df82a0d..ad8b87c6f5 100644 --- a/src/cmd/compile/internal/gc/pgen_test.go +++ b/src/cmd/compile/internal/gc/pgen_test.go @@ -145,11 +145,11 @@ func TestCmpstackvar(t *testing.T) { for _, d := range testdata { got := cmpstackvarlt(d.a, d.b) if got != d.lt { - t.Errorf("want %#v < %#v", d.a, d.b) + t.Errorf("want %v < %v", d.a, d.b) } // If we expect a < b to be true, check that b < a is false. if d.lt && cmpstackvarlt(d.b, d.a) { - t.Errorf("unexpected %#v < %#v", d.b, d.a) + t.Errorf("unexpected %v < %v", d.b, d.a) } } } diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index dffebc58f2..e05a124b29 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -291,12 +291,12 @@ func assignop(src, dst *types.Type) (ir.Op, string) { why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym) } else if have != nil && have.Sym == missing.Sym { why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+ - "\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type) + "\t\thave %v%S\n\t\twant %v%S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type) } else if ptr != 0 { why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym) } else if have != nil { why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+ - "\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type) + "\t\thave %v%S\n\t\twant %v%S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type) } else { why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym) } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 85094dbebc..a7c05c6c0f 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -58,7 +58,7 @@ func tracePrint(title string, n ir.Node) func(np *ir.Node) { skipDowidthForTracing = true defer func() { skipDowidthForTracing = false }() - fmt.Printf("%s: %s=> %p %s %v tc=%d type=%#L\n", pos, indent, n, op, n, tc, typ) + fmt.Printf("%s: %s=> %p %s %v tc=%d type=%L\n", pos, indent, n, op, n, tc, typ) } } @@ -1039,12 +1039,12 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { if !implements(n.Type(), t, &missing, &have, &ptr) { if have != nil && have.Sym == missing.Sym { base.Errorf("impossible type assertion:\n\t%v does not implement %v (wrong type for %v method)\n"+ - "\t\thave %v%0S\n\t\twant %v%0S", n.Type(), t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type) + "\t\thave %v%S\n\t\twant %v%S", n.Type(), t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type) } else if ptr != 0 { base.Errorf("impossible type assertion:\n\t%v does not implement %v (%v method has pointer receiver)", n.Type(), t, missing.Sym) } else if have != nil { base.Errorf("impossible type assertion:\n\t%v does not implement %v (missing %v method)\n"+ - "\t\thave %v%0S\n\t\twant %v%0S", n.Type(), t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type) + "\t\thave %v%S\n\t\twant %v%S", n.Type(), t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type) } else { base.Errorf("impossible type assertion:\n\t%v does not implement %v (missing %v method)", n.Type(), t, missing.Sym) } diff --git a/src/cmd/compile/internal/gc/unsafe.go b/src/cmd/compile/internal/gc/unsafe.go index 678924b229..d7ae5d7aaa 100644 --- a/src/cmd/compile/internal/gc/unsafe.go +++ b/src/cmd/compile/internal/gc/unsafe.go @@ -70,7 +70,7 @@ func evalunsafe(n ir.Node) int64 { v += r.Offset() default: ir.Dump("unsafenmagic", n.Left()) - base.Fatalf("impossible %#v node after dot insertion", r.Op()) + base.Fatalf("impossible %v node after dot insertion", r.Op()) } } return v diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 346817e589..4189d1a721 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -2154,7 +2154,7 @@ func reorder3(all []ir.Node) []ir.Node { switch l.Op() { default: - base.Fatalf("reorder3 unexpected lvalue %#v", l.Op()) + base.Fatalf("reorder3 unexpected lvalue %v", l.Op()) case ir.ONAME: break diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 85c6b218e2..68e425bdaa 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -125,12 +125,6 @@ func (o Op) Format(s fmt.State, verb rune) { // %+v Debug syntax, as in Dump. // func FmtNode(n Node, s fmt.State, verb rune) { - // TODO(rsc): Remove uses of %#v, which behaves just like %v. - // TODO(rsc): Remove uses of %S, which behaves just like %v. - if verb == 'S' { - verb = 'v' - } - // %+v prints Dump. // Otherwise we print Go syntax. if s.Flag('+') && verb == 'v' { @@ -355,7 +349,7 @@ func stmtFmt(n Node, s fmt.State) { break } - fmt.Fprintf(s, "%v %#v= %v", n.Left(), n.SubOp(), n.Right()) + fmt.Fprintf(s, "%v %v= %v", n.Left(), n.SubOp(), n.Right()) case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: if n.Colas() && !complexinit { @@ -446,7 +440,7 @@ func stmtFmt(n Node, s fmt.State) { break } - fmt.Fprintf(s, "%#v", n.Op()) + fmt.Fprintf(s, "%v", n.Op()) if simpleinit { fmt.Fprintf(s, " %v;", n.Init().First()) } @@ -466,9 +460,9 @@ func stmtFmt(n Node, s fmt.State) { case OBREAK, OCONTINUE, OGOTO, OFALL: if n.Sym() != nil { - fmt.Fprintf(s, "%#v %v", n.Op(), n.Sym()) + fmt.Fprintf(s, "%v %v", n.Op(), n.Sym()) } else { - fmt.Fprintf(s, "%#v", n.Op()) + fmt.Fprintf(s, "%v", n.Op()) } case OLABEL: @@ -754,9 +748,9 @@ func exprFmt(n Node, s fmt.State, prec int) { case OCOMPLEX, OCOPY: if n.Left() != nil { - fmt.Fprintf(s, "%#v(%v, %v)", n.Op(), n.Left(), n.Right()) + fmt.Fprintf(s, "%v(%v, %v)", n.Op(), n.Left(), n.Right()) } else { - fmt.Fprintf(s, "%#v(%.v)", n.Op(), n.List()) + fmt.Fprintf(s, "%v(%.v)", n.Op(), n.List()) } case OCONV, @@ -795,14 +789,14 @@ func exprFmt(n Node, s fmt.State, prec int) { OPRINT, OPRINTN: if n.Left() != nil { - fmt.Fprintf(s, "%#v(%v)", n.Op(), n.Left()) + fmt.Fprintf(s, "%v(%v)", n.Op(), n.Left()) return } if n.IsDDD() { - fmt.Fprintf(s, "%#v(%.v...)", n.Op(), n.List()) + fmt.Fprintf(s, "%v(%.v...)", n.Op(), n.List()) return } - fmt.Fprintf(s, "%#v(%.v)", n.Op(), n.List()) + fmt.Fprintf(s, "%v(%.v)", n.Op(), n.List()) case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG: exprFmt(n.Left(), s, nprec) @@ -832,7 +826,7 @@ func exprFmt(n Node, s fmt.State, prec int) { case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV: // Unary - fmt.Fprintf(s, "%#v", n.Op()) + fmt.Fprintf(s, "%v", n.Op()) if n.Left() != nil && n.Left().Op() == n.Op() { fmt.Fprint(s, " ") } @@ -860,7 +854,7 @@ func exprFmt(n Node, s fmt.State, prec int) { OSUB, OXOR: exprFmt(n.Left(), s, nprec) - fmt.Fprintf(s, " %#v ", n.Op()) + fmt.Fprintf(s, " %v ", n.Op()) exprFmt(n.Right(), s, nprec+1) case OADDSTR: From 2de0af3b1b09e11b71ec4c58bb406be7abf112b0 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 6 Dec 2020 15:49:58 -0500 Subject: [PATCH 177/212] [dev.regabi] cmd/compile: prepare mknode for rename of Func.body The next CL will rename Func.body to Func.Body_. At some point in the future we will rename it to Func.Body. Make the generator not get confused. Passes buildall w/ toolstash -cmp. Change-Id: Iee3f4915889a8287377bf3304d5b9250a909477e Reviewed-on: https://go-review.googlesource.com/c/go/+/275783 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/mknode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ir/mknode.go b/src/cmd/compile/internal/ir/mknode.go index 2c007f93f1..978b2de5a5 100644 --- a/src/cmd/compile/internal/ir/mknode.go +++ b/src/cmd/compile/internal/ir/mknode.go @@ -141,7 +141,7 @@ func forNodeFields(typName string, typ *types.Struct, f func(name string, is fun } switch typName { case "Func": - if v.Name() != "body" { + if strings.ToLower(strings.TrimSuffix(v.Name(), "_")) != "body" { continue } case "Name", "Pack": From 6d783e7440056ca24b57b52605def43d09d8b2a2 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 6 Dec 2020 15:36:58 -0500 Subject: [PATCH 178/212] [dev.regabi] cmd/compile: export all Node fields [generated] The plan was always to export them once we remove the getters and setters, but do it a bit early, with _ suffixes as needed, so that the reflection-based ir.Dump can access the fields. Passes buildall w/ toolstash -cmp. [git-generate] cd src/cmd/compile/internal/ir rf ' mv AddStringExpr.list AddStringExpr.List_ mv BlockStmt.list BlockStmt.List_ mv CallExpr.body CallExpr.Body_ mv CaseStmt.list CaseStmt.List_ mv CaseStmt.body CaseStmt.Body_ mv ClosureExpr.fn ClosureExpr.Func_ mv CompLitExpr.list CompLitExpr.List_ mv ForStmt.body ForStmt.Body_ mv Func.body Func.Body_ mv IfStmt.body IfStmt.Body_ mv InlinedCallExpr.body InlinedCallExpr.Body_ mv RangeStmt.body RangeStmt.Body_ mv SliceExpr.list SliceExpr.List_ mv SliceHeaderExpr.lenCap SliceHeaderExpr.LenCap_ mv TypeSwitchGuard.name TypeSwitchGuard.Name_ ' go generate Change-Id: I06e65920cecbcc51bea2254f52fcd7d5c5d0dc90 Reviewed-on: https://go-review.googlesource.com/c/go/+/275784 Trust: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/expr.go | 80 +++++++++++------------ src/cmd/compile/internal/ir/func.go | 12 ++-- src/cmd/compile/internal/ir/node_gen.go | 86 ++++++++++++------------- src/cmd/compile/internal/ir/stmt.go | 78 +++++++++++----------- 4 files changed, 128 insertions(+), 128 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 7165a06b25..a74e0712b9 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -91,20 +91,20 @@ func toNtype(x Node) Ntype { // An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1]. type AddStringExpr struct { miniExpr - list Nodes + List_ Nodes } func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr { n := &AddStringExpr{} n.pos = pos n.op = OADDSTR - n.list.Set(list) + n.List_.Set(list) return n } -func (n *AddStringExpr) List() Nodes { return n.list } -func (n *AddStringExpr) PtrList() *Nodes { return &n.list } -func (n *AddStringExpr) SetList(x Nodes) { n.list = x } +func (n *AddStringExpr) List() Nodes { return n.List_ } +func (n *AddStringExpr) PtrList() *Nodes { return &n.List_ } +func (n *AddStringExpr) SetList(x Nodes) { n.List_ = x } // An AddrExpr is an address-of expression &X. // It may end up being a normal address-of or an allocation of a composite literal. @@ -185,7 +185,7 @@ type CallExpr struct { X Node Args Nodes Rargs Nodes // TODO(rsc): Delete. - body Nodes // TODO(rsc): Delete. + Body_ Nodes // TODO(rsc): Delete. DDD bool Use CallUse noInline bool @@ -216,9 +216,9 @@ func (n *CallExpr) IsDDD() bool { return n.DDD } func (n *CallExpr) SetIsDDD(x bool) { n.DDD = x } func (n *CallExpr) NoInline() bool { return n.noInline } func (n *CallExpr) SetNoInline(x bool) { n.noInline = x } -func (n *CallExpr) Body() Nodes { return n.body } -func (n *CallExpr) PtrBody() *Nodes { return &n.body } -func (n *CallExpr) SetBody(x Nodes) { n.body = x } +func (n *CallExpr) Body() Nodes { return n.Body_ } +func (n *CallExpr) PtrBody() *Nodes { return &n.Body_ } +func (n *CallExpr) SetBody(x Nodes) { n.Body_ = x } func (n *CallExpr) SetOp(op Op) { switch op { @@ -255,17 +255,17 @@ func (n *CallPartExpr) SetLeft(x Node) { n.X = x } // A ClosureExpr is a function literal expression. type ClosureExpr struct { miniExpr - fn *Func + Func_ *Func } func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr { - n := &ClosureExpr{fn: fn} + n := &ClosureExpr{Func_: fn} n.op = OCLOSURE n.pos = pos return n } -func (n *ClosureExpr) Func() *Func { return n.fn } +func (n *ClosureExpr) Func() *Func { return n.Func_ } // A ClosureRead denotes reading a variable stored within a closure struct. type ClosureRead struct { @@ -289,14 +289,14 @@ type CompLitExpr struct { miniExpr orig Node Ntype Ntype - list Nodes // initialized values + List_ Nodes // initialized values } func NewCompLitExpr(pos src.XPos, typ Ntype, list []Node) *CompLitExpr { n := &CompLitExpr{Ntype: typ} n.pos = pos n.op = OCOMPLIT - n.list.Set(list) + n.List_.Set(list) n.orig = n return n } @@ -305,9 +305,9 @@ func (n *CompLitExpr) Orig() Node { return n.orig } func (n *CompLitExpr) SetOrig(x Node) { n.orig = x } func (n *CompLitExpr) Right() Node { return n.Ntype } func (n *CompLitExpr) SetRight(x Node) { n.Ntype = toNtype(x) } -func (n *CompLitExpr) List() Nodes { return n.list } -func (n *CompLitExpr) PtrList() *Nodes { return &n.list } -func (n *CompLitExpr) SetList(x Nodes) { n.list = x } +func (n *CompLitExpr) List() Nodes { return n.List_ } +func (n *CompLitExpr) PtrList() *Nodes { return &n.List_ } +func (n *CompLitExpr) SetList(x Nodes) { n.List_ = x } func (n *CompLitExpr) SetOp(op Op) { switch op { @@ -436,7 +436,7 @@ func (n *KeyExpr) SetOp(op Op) { // An InlinedCallExpr is an inlined function call. type InlinedCallExpr struct { miniExpr - body Nodes + Body_ Nodes ReturnVars Nodes } @@ -444,14 +444,14 @@ func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { n := &InlinedCallExpr{} n.pos = pos n.op = OINLCALL - n.body.Set(body) + n.Body_.Set(body) n.ReturnVars.Set(retvars) return n } -func (n *InlinedCallExpr) Body() Nodes { return n.body } -func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.body } -func (n *InlinedCallExpr) SetBody(x Nodes) { n.body = x } +func (n *InlinedCallExpr) Body() Nodes { return n.Body_ } +func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.Body_ } +func (n *InlinedCallExpr) SetBody(x Nodes) { n.Body_ = x } func (n *InlinedCallExpr) Rlist() Nodes { return n.ReturnVars } func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars } func (n *InlinedCallExpr) SetRlist(x Nodes) { n.ReturnVars = x } @@ -617,8 +617,8 @@ func (*SelectorExpr) CanBeNtype() {} // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max]. type SliceExpr struct { miniExpr - X Node - list Nodes // TODO(rsc): Use separate Nodes + X Node + List_ Nodes // TODO(rsc): Use separate Nodes } func NewSliceExpr(pos src.XPos, op Op, x Node) *SliceExpr { @@ -630,9 +630,9 @@ func NewSliceExpr(pos src.XPos, op Op, x Node) *SliceExpr { func (n *SliceExpr) Left() Node { return n.X } func (n *SliceExpr) SetLeft(x Node) { n.X = x } -func (n *SliceExpr) List() Nodes { return n.list } -func (n *SliceExpr) PtrList() *Nodes { return &n.list } -func (n *SliceExpr) SetList(x Nodes) { n.list = x } +func (n *SliceExpr) List() Nodes { return n.List_ } +func (n *SliceExpr) PtrList() *Nodes { return &n.List_ } +func (n *SliceExpr) SetList(x Nodes) { n.List_ = x } func (n *SliceExpr) SetOp(op Op) { switch op { @@ -646,16 +646,16 @@ func (n *SliceExpr) SetOp(op Op) { // SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max]. // n must be a slice expression. max is nil if n is a simple slice expression. func (n *SliceExpr) SliceBounds() (low, high, max Node) { - if n.list.Len() == 0 { + if n.List_.Len() == 0 { return nil, nil, nil } switch n.Op() { case OSLICE, OSLICEARR, OSLICESTR: - s := n.list.Slice() + s := n.List_.Slice() return s[0], s[1], nil case OSLICE3, OSLICE3ARR: - s := n.list.Slice() + s := n.List_.Slice() return s[0], s[1], s[2] } base.Fatalf("SliceBounds op %v: %v", n.Op(), n) @@ -670,24 +670,24 @@ func (n *SliceExpr) SetSliceBounds(low, high, max Node) { if max != nil { base.Fatalf("SetSliceBounds %v given three bounds", n.Op()) } - s := n.list.Slice() + s := n.List_.Slice() if s == nil { if low == nil && high == nil { return } - n.list.Set2(low, high) + n.List_.Set2(low, high) return } s[0] = low s[1] = high return case OSLICE3, OSLICE3ARR: - s := n.list.Slice() + s := n.List_.Slice() if s == nil { if low == nil && high == nil && max == nil { return } - n.list.Set3(low, high, max) + n.List_.Set3(low, high, max) return } s[0] = low @@ -714,8 +714,8 @@ func (o Op) IsSlice3() bool { // A SliceHeader expression constructs a slice header from its parts. type SliceHeaderExpr struct { miniExpr - Ptr Node - lenCap Nodes // TODO(rsc): Split into two Node fields + Ptr Node + LenCap_ Nodes // TODO(rsc): Split into two Node fields } func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr { @@ -723,15 +723,15 @@ func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *Slic n.pos = pos n.op = OSLICEHEADER n.typ = typ - n.lenCap.Set2(len, cap) + n.LenCap_.Set2(len, cap) return n } func (n *SliceHeaderExpr) Left() Node { return n.Ptr } func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x } -func (n *SliceHeaderExpr) List() Nodes { return n.lenCap } -func (n *SliceHeaderExpr) PtrList() *Nodes { return &n.lenCap } -func (n *SliceHeaderExpr) SetList(x Nodes) { n.lenCap = x } +func (n *SliceHeaderExpr) List() Nodes { return n.LenCap_ } +func (n *SliceHeaderExpr) PtrList() *Nodes { return &n.LenCap_ } +func (n *SliceHeaderExpr) SetList(x Nodes) { n.LenCap_ = x } // A StarExpr is a dereference expression *X. // It may end up being a value or a type. diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 3bca25b504..8aa6daed6f 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -49,9 +49,9 @@ import ( // pointer from the Func back to the OCALLPART. type Func struct { miniNode - typ *types.Type - body Nodes - iota int64 + typ *types.Type + Body_ Nodes + iota int64 Nname *Name // ONAME node OClosure *ClosureExpr // OCLOSURE node @@ -117,9 +117,9 @@ func NewFunc(pos src.XPos) *Func { func (f *Func) isStmt() {} func (f *Func) Func() *Func { return f } -func (f *Func) Body() Nodes { return f.body } -func (f *Func) PtrBody() *Nodes { return &f.body } -func (f *Func) SetBody(x Nodes) { f.body = x } +func (f *Func) Body() Nodes { return f.Body_ } +func (f *Func) PtrBody() *Nodes { return &f.Body_ } +func (f *Func) SetBody(x Nodes) { f.Body_ = x } func (f *Func) Type() *types.Type { return f.typ } func (f *Func) SetType(x *types.Type) { f.typ = x } func (f *Func) Iota() int64 { return f.iota } diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index 4c47a4486e..b3fd89c367 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -9,18 +9,18 @@ func (n *AddStringExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *AddStringExpr) copy() Node { c := *n c.init = c.init.Copy() - c.list = c.list.Copy() + c.List_ = c.List_.Copy() return &c } func (n *AddStringExpr) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) - err = maybeDoList(n.list, err, do) + err = maybeDoList(n.List_, err, do) return err } func (n *AddStringExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) - editList(n.list, edit) + editList(n.List_, edit) } func (n *AddrExpr) String() string { return fmt.Sprint(n) } @@ -147,18 +147,18 @@ func (n *BlockStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *BlockStmt) copy() Node { c := *n c.init = c.init.Copy() - c.list = c.list.Copy() + c.List_ = c.List_.Copy() return &c } func (n *BlockStmt) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) - err = maybeDoList(n.list, err, do) + err = maybeDoList(n.List_, err, do) return err } func (n *BlockStmt) editChildren(edit func(Node) Node) { editList(n.init, edit) - editList(n.list, edit) + editList(n.List_, edit) } func (n *BranchStmt) String() string { return fmt.Sprint(n) } @@ -184,7 +184,7 @@ func (n *CallExpr) copy() Node { c.init = c.init.Copy() c.Args = c.Args.Copy() c.Rargs = c.Rargs.Copy() - c.body = c.body.Copy() + c.Body_ = c.Body_.Copy() return &c } func (n *CallExpr) doChildren(do func(Node) error) error { @@ -193,7 +193,7 @@ func (n *CallExpr) doChildren(do func(Node) error) error { err = maybeDo(n.X, err, do) err = maybeDoList(n.Args, err, do) err = maybeDoList(n.Rargs, err, do) - err = maybeDoList(n.body, err, do) + err = maybeDoList(n.Body_, err, do) return err } func (n *CallExpr) editChildren(edit func(Node) Node) { @@ -201,7 +201,7 @@ func (n *CallExpr) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) editList(n.Args, edit) editList(n.Rargs, edit) - editList(n.body, edit) + editList(n.Body_, edit) } func (n *CallPartExpr) String() string { return fmt.Sprint(n) } @@ -228,25 +228,25 @@ func (n *CaseStmt) copy() Node { c := *n c.init = c.init.Copy() c.Vars = c.Vars.Copy() - c.list = c.list.Copy() - c.body = c.body.Copy() + c.List_ = c.List_.Copy() + c.Body_ = c.Body_.Copy() return &c } func (n *CaseStmt) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) err = maybeDoList(n.Vars, err, do) - err = maybeDoList(n.list, err, do) + err = maybeDoList(n.List_, err, do) err = maybeDo(n.Comm, err, do) - err = maybeDoList(n.body, err, do) + err = maybeDoList(n.Body_, err, do) return err } func (n *CaseStmt) editChildren(edit func(Node) Node) { editList(n.init, edit) editList(n.Vars, edit) - editList(n.list, edit) + editList(n.List_, edit) n.Comm = maybeEdit(n.Comm, edit) - editList(n.body, edit) + editList(n.Body_, edit) } func (n *ChanType) String() string { return fmt.Sprint(n) } @@ -301,20 +301,20 @@ func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *CompLitExpr) copy() Node { c := *n c.init = c.init.Copy() - c.list = c.list.Copy() + c.List_ = c.List_.Copy() return &c } func (n *CompLitExpr) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) err = maybeDo(n.Ntype, err, do) - err = maybeDoList(n.list, err, do) + err = maybeDoList(n.List_, err, do) return err } func (n *CompLitExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) n.Ntype = toNtype(maybeEdit(n.Ntype, edit)) - editList(n.list, edit) + editList(n.List_, edit) } func (n *ConstExpr) String() string { return fmt.Sprint(n) } @@ -390,7 +390,7 @@ func (n *ForStmt) copy() Node { c := *n c.init = c.init.Copy() c.Late = c.Late.Copy() - c.body = c.body.Copy() + c.Body_ = c.Body_.Copy() return &c } func (n *ForStmt) doChildren(do func(Node) error) error { @@ -399,7 +399,7 @@ func (n *ForStmt) doChildren(do func(Node) error) error { err = maybeDo(n.Cond, err, do) err = maybeDoList(n.Late, err, do) err = maybeDo(n.Post, err, do) - err = maybeDoList(n.body, err, do) + err = maybeDoList(n.Body_, err, do) return err } func (n *ForStmt) editChildren(edit func(Node) Node) { @@ -407,23 +407,23 @@ func (n *ForStmt) editChildren(edit func(Node) Node) { n.Cond = maybeEdit(n.Cond, edit) editList(n.Late, edit) n.Post = maybeEdit(n.Post, edit) - editList(n.body, edit) + editList(n.Body_, edit) } func (n *Func) String() string { return fmt.Sprint(n) } func (n *Func) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *Func) copy() Node { c := *n - c.body = c.body.Copy() + c.Body_ = c.Body_.Copy() return &c } func (n *Func) doChildren(do func(Node) error) error { var err error - err = maybeDoList(n.body, err, do) + err = maybeDoList(n.Body_, err, do) return err } func (n *Func) editChildren(edit func(Node) Node) { - editList(n.body, edit) + editList(n.Body_, edit) } func (n *FuncType) String() string { return fmt.Sprint(n) } @@ -473,7 +473,7 @@ func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *IfStmt) copy() Node { c := *n c.init = c.init.Copy() - c.body = c.body.Copy() + c.Body_ = c.Body_.Copy() c.Else = c.Else.Copy() return &c } @@ -481,14 +481,14 @@ func (n *IfStmt) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) err = maybeDo(n.Cond, err, do) - err = maybeDoList(n.body, err, do) + err = maybeDoList(n.Body_, err, do) err = maybeDoList(n.Else, err, do) return err } func (n *IfStmt) editChildren(edit func(Node) Node) { editList(n.init, edit) n.Cond = maybeEdit(n.Cond, edit) - editList(n.body, edit) + editList(n.Body_, edit) editList(n.Else, edit) } @@ -533,20 +533,20 @@ func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *InlinedCallExpr) copy() Node { c := *n c.init = c.init.Copy() - c.body = c.body.Copy() + c.Body_ = c.Body_.Copy() c.ReturnVars = c.ReturnVars.Copy() return &c } func (n *InlinedCallExpr) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) - err = maybeDoList(n.body, err, do) + err = maybeDoList(n.Body_, err, do) err = maybeDoList(n.ReturnVars, err, do) return err } func (n *InlinedCallExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) - editList(n.body, edit) + editList(n.Body_, edit) editList(n.ReturnVars, edit) } @@ -725,7 +725,7 @@ func (n *RangeStmt) copy() Node { c := *n c.init = c.init.Copy() c.Vars = c.Vars.Copy() - c.body = c.body.Copy() + c.Body_ = c.Body_.Copy() return &c } func (n *RangeStmt) doChildren(do func(Node) error) error { @@ -733,14 +733,14 @@ func (n *RangeStmt) doChildren(do func(Node) error) error { err = maybeDoList(n.init, err, do) err = maybeDoList(n.Vars, err, do) err = maybeDo(n.X, err, do) - err = maybeDoList(n.body, err, do) + err = maybeDoList(n.Body_, err, do) return err } func (n *RangeStmt) editChildren(edit func(Node) Node) { editList(n.init, edit) editList(n.Vars, edit) n.X = maybeEdit(n.X, edit) - editList(n.body, edit) + editList(n.Body_, edit) } func (n *ResultExpr) String() string { return fmt.Sprint(n) } @@ -843,20 +843,20 @@ func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SliceExpr) copy() Node { c := *n c.init = c.init.Copy() - c.list = c.list.Copy() + c.List_ = c.List_.Copy() return &c } func (n *SliceExpr) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) err = maybeDo(n.X, err, do) - err = maybeDoList(n.list, err, do) + err = maybeDoList(n.List_, err, do) return err } func (n *SliceExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) n.X = maybeEdit(n.X, edit) - editList(n.list, edit) + editList(n.List_, edit) } func (n *SliceHeaderExpr) String() string { return fmt.Sprint(n) } @@ -864,20 +864,20 @@ func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SliceHeaderExpr) copy() Node { c := *n c.init = c.init.Copy() - c.lenCap = c.lenCap.Copy() + c.LenCap_ = c.LenCap_.Copy() return &c } func (n *SliceHeaderExpr) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) err = maybeDo(n.Ptr, err, do) - err = maybeDoList(n.lenCap, err, do) + err = maybeDoList(n.LenCap_, err, do) return err } func (n *SliceHeaderExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) n.Ptr = maybeEdit(n.Ptr, edit) - editList(n.lenCap, edit) + editList(n.LenCap_, edit) } func (n *SliceType) String() string { return fmt.Sprint(n) } @@ -984,15 +984,15 @@ func (n *TypeSwitchGuard) copy() Node { } func (n *TypeSwitchGuard) doChildren(do func(Node) error) error { var err error - if n.name != nil { - err = maybeDo(n.name, err, do) + if n.Name_ != nil { + err = maybeDo(n.Name_, err, do) } err = maybeDo(n.X, err, do) return err } func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) { - if n.name != nil { - n.name = edit(n.name).(*Name) + if n.Name_ != nil { + n.Name_ = edit(n.Name_).(*Name) } n.X = maybeEdit(n.X, edit) } diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 836bbcb453..ccf46dfa73 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -161,20 +161,20 @@ func (n *AssignOpStmt) SetType(x *types.Type) { n.typ = x } // A BlockStmt is a block: { List }. type BlockStmt struct { miniStmt - list Nodes + List_ Nodes } func NewBlockStmt(pos src.XPos, list []Node) *BlockStmt { n := &BlockStmt{} n.pos = pos n.op = OBLOCK - n.list.Set(list) + n.List_.Set(list) return n } -func (n *BlockStmt) List() Nodes { return n.list } -func (n *BlockStmt) PtrList() *Nodes { return &n.list } -func (n *BlockStmt) SetList(x Nodes) { n.list = x } +func (n *BlockStmt) List() Nodes { return n.List_ } +func (n *BlockStmt) PtrList() *Nodes { return &n.List_ } +func (n *BlockStmt) SetList(x Nodes) { n.List_ = x } // A BranchStmt is a break, continue, fallthrough, or goto statement. // @@ -204,27 +204,27 @@ func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym } // A CaseStmt is a case statement in a switch or select: case List: Body. type CaseStmt struct { miniStmt - Vars Nodes // declared variable for this case in type switch - list Nodes // list of expressions for switch, early select - Comm Node // communication case (Exprs[0]) after select is type-checked - body Nodes + Vars Nodes // declared variable for this case in type switch + List_ Nodes // list of expressions for switch, early select + Comm Node // communication case (Exprs[0]) after select is type-checked + Body_ Nodes } func NewCaseStmt(pos src.XPos, list, body []Node) *CaseStmt { n := &CaseStmt{} n.pos = pos n.op = OCASE - n.list.Set(list) - n.body.Set(body) + n.List_.Set(list) + n.Body_.Set(body) return n } -func (n *CaseStmt) List() Nodes { return n.list } -func (n *CaseStmt) PtrList() *Nodes { return &n.list } -func (n *CaseStmt) SetList(x Nodes) { n.list = x } -func (n *CaseStmt) Body() Nodes { return n.body } -func (n *CaseStmt) PtrBody() *Nodes { return &n.body } -func (n *CaseStmt) SetBody(x Nodes) { n.body = x } +func (n *CaseStmt) List() Nodes { return n.List_ } +func (n *CaseStmt) PtrList() *Nodes { return &n.List_ } +func (n *CaseStmt) SetList(x Nodes) { n.List_ = x } +func (n *CaseStmt) Body() Nodes { return n.Body_ } +func (n *CaseStmt) PtrBody() *Nodes { return &n.Body_ } +func (n *CaseStmt) SetBody(x Nodes) { n.Body_ = x } func (n *CaseStmt) Rlist() Nodes { return n.Vars } func (n *CaseStmt) PtrRlist() *Nodes { return &n.Vars } func (n *CaseStmt) SetRlist(x Nodes) { n.Vars = x } @@ -255,7 +255,7 @@ type ForStmt struct { Cond Node Late Nodes Post Node - body Nodes + Body_ Nodes hasBreak bool } @@ -264,7 +264,7 @@ func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStm n.pos = pos n.op = OFOR n.init.Set(init) - n.body.Set(body) + n.Body_.Set(body) return n } @@ -274,9 +274,9 @@ func (n *ForStmt) Left() Node { return n.Cond } func (n *ForStmt) SetLeft(x Node) { n.Cond = x } func (n *ForStmt) Right() Node { return n.Post } func (n *ForStmt) SetRight(x Node) { n.Post = x } -func (n *ForStmt) Body() Nodes { return n.body } -func (n *ForStmt) PtrBody() *Nodes { return &n.body } -func (n *ForStmt) SetBody(x Nodes) { n.body = x } +func (n *ForStmt) Body() Nodes { return n.Body_ } +func (n *ForStmt) PtrBody() *Nodes { return &n.Body_ } +func (n *ForStmt) SetBody(x Nodes) { n.Body_ = x } func (n *ForStmt) List() Nodes { return n.Late } func (n *ForStmt) PtrList() *Nodes { return &n.Late } func (n *ForStmt) SetList(x Nodes) { n.Late = x } @@ -310,7 +310,7 @@ func (n *GoStmt) SetLeft(x Node) { n.Call = x } type IfStmt struct { miniStmt Cond Node - body Nodes + Body_ Nodes Else Nodes likely bool // code layout hint } @@ -319,16 +319,16 @@ func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt { n := &IfStmt{Cond: cond} n.pos = pos n.op = OIF - n.body.Set(body) + n.Body_.Set(body) n.Else.Set(els) return n } func (n *IfStmt) Left() Node { return n.Cond } func (n *IfStmt) SetLeft(x Node) { n.Cond = x } -func (n *IfStmt) Body() Nodes { return n.body } -func (n *IfStmt) PtrBody() *Nodes { return &n.body } -func (n *IfStmt) SetBody(x Nodes) { n.body = x } +func (n *IfStmt) Body() Nodes { return n.Body_ } +func (n *IfStmt) PtrBody() *Nodes { return &n.Body_ } +func (n *IfStmt) SetBody(x Nodes) { n.Body_ = x } func (n *IfStmt) Rlist() Nodes { return n.Else } func (n *IfStmt) PtrRlist() *Nodes { return &n.Else } func (n *IfStmt) SetRlist(x Nodes) { n.Else = x } @@ -375,7 +375,7 @@ type RangeStmt struct { Vars Nodes // TODO(rsc): Replace with Key, Value Node Def bool X Node - body Nodes + Body_ Nodes hasBreak bool typ *types.Type // TODO(rsc): Remove - use X.Type() instead } @@ -385,7 +385,7 @@ func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt { n.pos = pos n.op = ORANGE n.Vars.Set(vars) - n.body.Set(body) + n.Body_.Set(body) return n } @@ -393,9 +393,9 @@ func (n *RangeStmt) Sym() *types.Sym { return n.Label } func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x } func (n *RangeStmt) Right() Node { return n.X } func (n *RangeStmt) SetRight(x Node) { n.X = x } -func (n *RangeStmt) Body() Nodes { return n.body } -func (n *RangeStmt) PtrBody() *Nodes { return &n.body } -func (n *RangeStmt) SetBody(x Nodes) { n.body = x } +func (n *RangeStmt) Body() Nodes { return n.Body_ } +func (n *RangeStmt) PtrBody() *Nodes { return &n.Body_ } +func (n *RangeStmt) SetBody(x Nodes) { n.Body_ = x } func (n *RangeStmt) List() Nodes { return n.Vars } func (n *RangeStmt) PtrList() *Nodes { return &n.Vars } func (n *RangeStmt) SetList(x Nodes) { n.Vars = x } @@ -514,14 +514,14 @@ func (n *SwitchStmt) SetHasBreak(x bool) { n.hasBreak = x } // A TypeSwitchGuard is the [Name :=] X.(type) in a type switch. type TypeSwitchGuard struct { miniNode - name *Name - X Node + Name_ *Name + X Node } func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard { n := &TypeSwitchGuard{X: x} if name != nil { - n.name = name.(*Name) + n.Name_ = name.(*Name) } n.pos = pos n.op = OTYPESW @@ -529,17 +529,17 @@ func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard { } func (n *TypeSwitchGuard) Left() Node { - if n.name == nil { + if n.Name_ == nil { return nil } - return n.name + return n.Name_ } func (n *TypeSwitchGuard) SetLeft(x Node) { if x == nil { - n.name = nil + n.Name_ = nil return } - n.name = x.(*Name) + n.Name_ = x.(*Name) } func (n *TypeSwitchGuard) Right() Node { return n.X } func (n *TypeSwitchGuard) SetRight(x Node) { n.X = x } From 7ad6596c4711c48ef95334c9c6516a0c30979bd9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 7 Dec 2020 15:20:37 -0500 Subject: [PATCH 179/212] io/fs: fix Sub method error text Noticed in (and alternative to) CL 275520. Change-Id: If6c107ee9928dd1910facd4dc66da7234cb91c39 Reviewed-on: https://go-review.googlesource.com/c/go/+/275879 Trust: Russ Cox Trust: Robert Griesemer Run-TryBot: Russ Cox Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/io/fs/sub.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/io/fs/sub.go b/src/io/fs/sub.go index 381f409504..64cdffe6de 100644 --- a/src/io/fs/sub.go +++ b/src/io/fs/sub.go @@ -88,7 +88,7 @@ func (f *subFS) Open(name string) (File, error) { } func (f *subFS) ReadDir(name string) ([]DirEntry, error) { - full, err := f.fullName("open", name) + full, err := f.fullName("read", name) if err != nil { return nil, err } @@ -97,7 +97,7 @@ func (f *subFS) ReadDir(name string) ([]DirEntry, error) { } func (f *subFS) ReadFile(name string) ([]byte, error) { - full, err := f.fullName("open", name) + full, err := f.fullName("read", name) if err != nil { return nil, err } From 63722da46bbf320670e8f993490fe1431feeeb04 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 5 Dec 2020 17:24:48 -0800 Subject: [PATCH 180/212] [dev.regabi] cmd/compile: fix comment Russ, is this what you meant? Change-Id: I27d2847811c6eabd94358e435eb3eb4bc8cfaa9e Reviewed-on: https://go-review.googlesource.com/c/go/+/275712 Trust: Keith Randall Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/typecheck.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index a7c05c6c0f..990921189a 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3361,7 +3361,7 @@ out: // type check function definition // To be called by typecheck, not directly. -// (Call typecheckfn instead.) +// (Call typecheckFunc instead.) func typecheckfunc(n *ir.Func) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckfunc", n)(nil) From 9b8c27255893faf01e82227164a59baad1ff0011 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 2 Dec 2020 18:25:19 -0800 Subject: [PATCH 181/212] reflect: document multiple keys in struct tags For #40281 Fixes #42959 Change-Id: Ibc4769fda1592a1373ec720ea30baf319c0a0136 Reviewed-on: https://go-review.googlesource.com/c/go/+/274448 Trust: Ian Lance Taylor Reviewed-by: Rob Pike Reviewed-by: Dmitri Shuralyov --- src/reflect/type.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/reflect/type.go b/src/reflect/type.go index a2076bb3f1..1f1e70d485 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1104,12 +1104,16 @@ type StructField struct { // A StructTag is the tag string in a struct field. // -// By convention, tag strings are a concatenation of -// optionally space-separated key:"value" pairs. -// Each key is a non-empty string consisting of non-control -// characters other than space (U+0020 ' '), quote (U+0022 '"'), -// and colon (U+003A ':'). Each value is quoted using U+0022 '"' -// characters and Go string literal syntax. +// By convention, tag strings are a mapping of keys to values. +// The format is key:"value". Each key is a non-empty string consisting +// of non-control characters other than space (U+0020 ' '), +// quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted +// using U+0022 '"' characters and Go string literal syntax. +// Multiple key-value mappings are separated by zero or more spaces, as in +// key1:"value1" key2:"value2" +// Multiple keys may map to a single shared value by separating the keys +// with spaces, as in +// key1 key2:"value" type StructTag string // Get returns the value associated with key in the tag string. From 6362d01c152071751bd594bdf10c301514fc2d4e Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 7 Dec 2020 17:15:06 -0500 Subject: [PATCH 182/212] doc/go1.16: update linker stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit benchstat v2 comparison vs HEAD: 1.15.6 1.16 sec/op sec/op vs base LinkIstio-48 4.44 ± 1% 3.43 ± 1% -22.79% (p=0.000 n=20) LinkKubelet-48 10.89 ± 1% 8.42 ± 1% -22.63% (p=0.000 n=20) LinkDiscovery-48 1.43 ± 1% 1.06 ± 1% -25.68% (p=0.000 n=20) LinkIstio-4 4.50 ± 1% 3.52 ± 1% -21.84% (p=0.000 n=20) LinkKubelet-4 10.84 ± 2% 8.55 ± 1% -21.09% (p=0.000 n=20) LinkDiscovery-4 1.45 ± 2% 1.11 ± 2% -23.81% (p=0.000 n=20) 1.15.6 1.16 max-RSS-bytes max-RSS-bytes vs base LinkIstio-48 1085Mi ± 1% 1006Mi ± 0% -7.32% (p=0.000 n=20) LinkKubelet-48 1.60Gi ± 5% 1.46Gi ± 1% -8.57% (p=0.000 n=20) LinkDiscovery-48 392Mi ± 1% 362Mi ± 2% -7.71% (p=0.000 n=20) LinkIstio-4 1022Mi ± 6% 958Mi ± 1% -6.26% (p=0.000 n=20) LinkKubelet-4 1.63Gi ± 2% 1.44Gi ± 0% -11.44% (p=0.000 n=20) LinkDiscovery-4 400Mi ± 0% 353Mi ± 1% -11.83% (p=0.000 n=20) 1.15.6 1.16 exe-bytes exe-bytes vs base LinkIstio-48 97.7Mi ± 0% 93.4Mi ± 0% -4.38% (p=0.000 n=20) LinkKubelet-48 129Mi ± 0% 127Mi ± 0% -1.17% (p=0.000 n=20) LinkDiscovery-48 31.9Mi ± 0% 29.1Mi ± 0% -8.67% (p=0.000 n=20) LinkIstio-4 97.7Mi ± 0% 93.4Mi ± 0% -4.38% (p=0.000 n=20) LinkKubelet-4 129Mi ± 0% 127Mi ± 0% -1.17% (p=0.000 n=20) LinkDiscovery-4 31.9Mi ± 0% 29.1Mi ± 0% -8.67% (p=0.000 n=20) https://perf.golang.org/search?q=upload:20201207.6 For #40700. Change-Id: I3f7b3e08db4fb7980d2472f15e5fc04503e95ea0 Reviewed-on: https://go-review.googlesource.com/c/go/+/275912 Trust: Austin Clements Reviewed-by: Cherry Zhang --- doc/go1.16.html | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index a1f07c10fd..da8f560f85 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -361,13 +361,10 @@ Do not send CLs removing the interior tags from such phrases. supported architecture/OS combinations (the 1.15 performance improvements were primarily focused on ELF-based OSes and amd64 architectures). For a representative set of - large Go programs, linking is 20-35% faster than 1.15 and requires + large Go programs, linking is 20-25% faster than 1.15 and requires 5-15% less memory on average for linux/amd64, with larger - improvements for other architectures and OSes. -

- -

- TODO: update with final numbers later in the release. + improvements for other architectures and OSes. Most binaries are + also smaller as a result of more aggressive symbol pruning.

From 1a98ab0e2dad7029d9db18fc1fae0b7e4fa4970c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 7 Dec 2020 17:15:44 -0800 Subject: [PATCH 183/212] [dev.regabi] cmd/compile: add ssa.Aux tag interface for Value.Aux It's currently hard to automate refactorings around the Value.Aux field, because we don't have any static typing information for it. Adding a tag interface will make subsequent CLs easier and safer. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: I41ae8e411a66bda3195a0957b60c2fe8a8002893 Reviewed-on: https://go-review.googlesource.com/c/go/+/275756 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Matthew Dempsky --- src/cmd/compile/fmtmap_test.go | 3 ++ src/cmd/compile/internal/gc/ssa.go | 22 +++++----- src/cmd/compile/internal/ir/mini.go | 3 +- src/cmd/compile/internal/ir/node.go | 1 + src/cmd/compile/internal/ssa/block.go | 2 +- src/cmd/compile/internal/ssa/check.go | 2 +- src/cmd/compile/internal/ssa/cse.go | 2 +- src/cmd/compile/internal/ssa/cse_test.go | 2 + src/cmd/compile/internal/ssa/debug.go | 4 +- src/cmd/compile/internal/ssa/func.go | 22 ++++------ src/cmd/compile/internal/ssa/func_test.go | 8 ++-- src/cmd/compile/internal/ssa/nilcheck_test.go | 2 +- src/cmd/compile/internal/ssa/op.go | 3 ++ src/cmd/compile/internal/ssa/rewrite.go | 44 ++++++++++++------- src/cmd/compile/internal/ssa/value.go | 5 ++- src/cmd/compile/internal/ssa/zcse.go | 2 +- src/cmd/compile/internal/types/type.go | 2 + src/cmd/internal/obj/link.go | 4 +- src/cmd/internal/obj/s390x/condition_code.go | 2 + src/cmd/internal/obj/s390x/rotate.go | 2 + 20 files changed, 80 insertions(+), 57 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index 756320285c..e62b9613e1 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -43,6 +43,9 @@ var knownFormats = map[string]string{ "cmd/compile/internal/ir.Nodes %+v": "", "cmd/compile/internal/ir.Nodes %.v": "", "cmd/compile/internal/ir.Op %+v": "", + "cmd/compile/internal/ssa.Aux %#v": "", + "cmd/compile/internal/ssa.Aux %q": "", + "cmd/compile/internal/ssa.Aux %s": "", "cmd/compile/internal/ssa.BranchPrediction %d": "", "cmd/compile/internal/ssa.ID %d": "", "cmd/compile/internal/ssa.LocalSlot %s": "", diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index add50c35d7..95650328b1 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -772,7 +772,7 @@ func (s *state) newValue0(op ssa.Op, t *types.Type) *ssa.Value { } // newValue0A adds a new value with no arguments and an aux value to the current block. -func (s *state) newValue0A(op ssa.Op, t *types.Type, aux interface{}) *ssa.Value { +func (s *state) newValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value { return s.curBlock.NewValue0A(s.peekPos(), op, t, aux) } @@ -787,14 +787,14 @@ func (s *state) newValue1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value { } // newValue1A adds a new value with one argument and an aux value to the current block. -func (s *state) newValue1A(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value) *ssa.Value { +func (s *state) newValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value { return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg) } // newValue1Apos adds a new value with one argument and an aux value to the current block. // isStmt determines whether the created values may be a statement or not // (i.e., false means never, yes means maybe). -func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value, isStmt bool) *ssa.Value { +func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value, isStmt bool) *ssa.Value { if isStmt { return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg) } @@ -812,14 +812,14 @@ func (s *state) newValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value) *ssa. } // newValue2A adds a new value with two arguments and an aux value to the current block. -func (s *state) newValue2A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value) *ssa.Value { +func (s *state) newValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value) *ssa.Value { return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1) } // newValue2Apos adds a new value with two arguments and an aux value to the current block. // isStmt determines whether the created values may be a statement or not // (i.e., false means never, yes means maybe). -func (s *state) newValue2Apos(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value, isStmt bool) *ssa.Value { +func (s *state) newValue2Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value, isStmt bool) *ssa.Value { if isStmt { return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1) } @@ -842,14 +842,14 @@ func (s *state) newValue3I(op ssa.Op, t *types.Type, aux int64, arg0, arg1, arg2 } // newValue3A adds a new value with three arguments and an aux value to the current block. -func (s *state) newValue3A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *ssa.Value) *ssa.Value { +func (s *state) newValue3A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1, arg2 *ssa.Value) *ssa.Value { return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2) } // newValue3Apos adds a new value with three arguments and an aux value to the current block. // isStmt determines whether the created values may be a statement or not // (i.e., false means never, yes means maybe). -func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *ssa.Value, isStmt bool) *ssa.Value { +func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1, arg2 *ssa.Value, isStmt bool) *ssa.Value { if isStmt { return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2) } @@ -872,7 +872,7 @@ func (s *state) entryNewValue0(op ssa.Op, t *types.Type) *ssa.Value { } // entryNewValue0A adds a new value with no arguments and an aux value to the entry block. -func (s *state) entryNewValue0A(op ssa.Op, t *types.Type, aux interface{}) *ssa.Value { +func (s *state) entryNewValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value { return s.f.Entry.NewValue0A(src.NoXPos, op, t, aux) } @@ -887,7 +887,7 @@ func (s *state) entryNewValue1I(op ssa.Op, t *types.Type, auxint int64, arg *ssa } // entryNewValue1A adds a new value with one argument and an aux value to the entry block. -func (s *state) entryNewValue1A(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value) *ssa.Value { +func (s *state) entryNewValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value { return s.f.Entry.NewValue1A(src.NoXPos, op, t, aux, arg) } @@ -897,7 +897,7 @@ func (s *state) entryNewValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value) } // entryNewValue2A adds a new value with two arguments and an aux value to the entry block. -func (s *state) entryNewValue2A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value) *ssa.Value { +func (s *state) entryNewValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value) *ssa.Value { return s.f.Entry.NewValue2A(src.NoXPos, op, t, aux, arg0, arg1) } @@ -2060,7 +2060,7 @@ func (s *state) expr(n ir.Node) *ssa.Value { if i == "" { return s.constEmptyString(n.Type()) } - return s.entryNewValue0A(ssa.OpConstString, n.Type(), i) + return s.entryNewValue0A(ssa.OpConstString, n.Type(), ssa.StringToAux(i)) case constant.Bool: return s.constBool(constant.BoolVal(u)) case constant.Float: diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index 612e7d62c3..edb3b197da 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -198,5 +198,6 @@ func (n *miniNode) MarkReadonly() { panic(n.no("MarkReadonly")) } func (n *miniNode) TChanDir() types.ChanDir { panic(n.no("TChanDir")) } func (n *miniNode) SetTChanDir(types.ChanDir) { panic(n.no("SetTChanDir")) } -// TODO: Delete when CanBeAnSSASym is removed from Node itself. +// TODO: Delete when these are removed from Node itself. func (*miniNode) CanBeAnSSASym() {} +func (*miniNode) CanBeAnSSAAux() {} diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index ba7eaae1b9..b878b00546 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -113,6 +113,7 @@ type Node interface { // Only for SSA and should be removed when SSA starts // using a more specific type than Node. CanBeAnSSASym() + CanBeAnSSAAux() } // Line returns n's position as a string. If n has been inlined, diff --git a/src/cmd/compile/internal/ssa/block.go b/src/cmd/compile/internal/ssa/block.go index 519ac214ca..937c757b21 100644 --- a/src/cmd/compile/internal/ssa/block.go +++ b/src/cmd/compile/internal/ssa/block.go @@ -52,7 +52,7 @@ type Block struct { Controls [2]*Value // Auxiliary info for the block. Its value depends on the Kind. - Aux interface{} + Aux Aux AuxInt int64 // The unordered set of Values that define the operation of this block. diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index 5f5dfc328a..4d57eef556 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -161,7 +161,7 @@ func checkFunc(f *Func) { f.Fatalf("value %v has an AuxInt that encodes a NaN", v) } case auxString: - if _, ok := v.Aux.(string); !ok { + if _, ok := v.Aux.(stringAux); !ok { f.Fatalf("value %v has Aux type %T, want string", v, v.Aux) } canHaveAux = true diff --git a/src/cmd/compile/internal/ssa/cse.go b/src/cmd/compile/internal/ssa/cse.go index 3b4f2be37e..f78527410c 100644 --- a/src/cmd/compile/internal/ssa/cse.go +++ b/src/cmd/compile/internal/ssa/cse.go @@ -275,7 +275,7 @@ func lt2Cmp(isLt bool) types.Cmp { return types.CMPgt } -type auxmap map[interface{}]int32 +type auxmap map[Aux]int32 func cmpVal(v, w *Value, auxIDs auxmap) types.Cmp { // Try to order these comparison by cost (cheaper first) diff --git a/src/cmd/compile/internal/ssa/cse_test.go b/src/cmd/compile/internal/ssa/cse_test.go index 9e76645f54..8052016f3a 100644 --- a/src/cmd/compile/internal/ssa/cse_test.go +++ b/src/cmd/compile/internal/ssa/cse_test.go @@ -14,6 +14,8 @@ type tstAux struct { s string } +func (*tstAux) CanBeAnSSAAux() {} + // This tests for a bug found when partitioning, but not sorting by the Aux value. func TestCSEAuxPartitionBug(t *testing.T) { c := testConfig(t) diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go index 0d660361b1..44e91270fa 100644 --- a/src/cmd/compile/internal/ssa/debug.go +++ b/src/cmd/compile/internal/ssa/debug.go @@ -143,13 +143,13 @@ func (loc VarLoc) absent() bool { var BlockStart = &Value{ ID: -10000, Op: OpInvalid, - Aux: "BlockStart", + Aux: StringToAux("BlockStart"), } var BlockEnd = &Value{ ID: -20000, Op: OpInvalid, - Aux: "BlockEnd", + Aux: StringToAux("BlockEnd"), } // RegisterSet is a bitmap of registers, indexed by Register.num. diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index e6f899a2c7..e6c4798a78 100644 --- a/src/cmd/compile/internal/ssa/func.go +++ b/src/cmd/compile/internal/ssa/func.go @@ -377,13 +377,7 @@ func (b *Block) NewValue0I(pos src.XPos, op Op, t *types.Type, auxint int64) *Va } // NewValue returns a new value in the block with no arguments and an aux value. -func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux interface{}) *Value { - if _, ok := aux.(int64); ok { - // Disallow int64 aux values. They should be in the auxint field instead. - // Maybe we want to allow this at some point, but for now we disallow it - // to prevent errors like using NewValue1A instead of NewValue1I. - b.Fatalf("aux field has int64 type op=%s type=%s aux=%v", op, t, aux) - } +func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux Aux) *Value { v := b.Func.newValue(op, t, b, pos) v.AuxInt = 0 v.Aux = aux @@ -392,7 +386,7 @@ func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux interface{}) } // NewValue returns a new value in the block with no arguments and both an auxint and aux values. -func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}) *Value { +func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux) *Value { v := b.Func.newValue(op, t, b, pos) v.AuxInt = auxint v.Aux = aux @@ -421,7 +415,7 @@ func (b *Block) NewValue1I(pos src.XPos, op Op, t *types.Type, auxint int64, arg } // NewValue1A returns a new value in the block with one argument and an aux value. -func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg *Value) *Value { +func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux Aux, arg *Value) *Value { v := b.Func.newValue(op, t, b, pos) v.AuxInt = 0 v.Aux = aux @@ -432,7 +426,7 @@ func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux interface{}, } // NewValue1IA returns a new value in the block with one argument and both an auxint and aux values. -func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg *Value) *Value { +func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux, arg *Value) *Value { v := b.Func.newValue(op, t, b, pos) v.AuxInt = auxint v.Aux = aux @@ -455,7 +449,7 @@ func (b *Block) NewValue2(pos src.XPos, op Op, t *types.Type, arg0, arg1 *Value) } // NewValue2A returns a new value in the block with two arguments and one aux values. -func (b *Block) NewValue2A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1 *Value) *Value { +func (b *Block) NewValue2A(pos src.XPos, op Op, t *types.Type, aux Aux, arg0, arg1 *Value) *Value { v := b.Func.newValue(op, t, b, pos) v.AuxInt = 0 v.Aux = aux @@ -480,7 +474,7 @@ func (b *Block) NewValue2I(pos src.XPos, op Op, t *types.Type, auxint int64, arg } // NewValue2IA returns a new value in the block with two arguments and both an auxint and aux values. -func (b *Block) NewValue2IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg0, arg1 *Value) *Value { +func (b *Block) NewValue2IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux, arg0, arg1 *Value) *Value { v := b.Func.newValue(op, t, b, pos) v.AuxInt = auxint v.Aux = aux @@ -521,7 +515,7 @@ func (b *Block) NewValue3I(pos src.XPos, op Op, t *types.Type, auxint int64, arg } // NewValue3A returns a new value in the block with three argument and an aux value. -func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *Value) *Value { +func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux Aux, arg0, arg1, arg2 *Value) *Value { v := b.Func.newValue(op, t, b, pos) v.AuxInt = 0 v.Aux = aux @@ -633,7 +627,7 @@ func (f *Func) ConstNil(t *types.Type) *Value { } func (f *Func) ConstEmptyString(t *types.Type) *Value { v := f.constVal(OpConstString, t, constEmptyStringMagic, false) - v.Aux = "" + v.Aux = StringToAux("") return v } func (f *Func) ConstOffPtrSP(t *types.Type, c int64, sp *Value) *Value { diff --git a/src/cmd/compile/internal/ssa/func_test.go b/src/cmd/compile/internal/ssa/func_test.go index 568c6436f5..276c444b9a 100644 --- a/src/cmd/compile/internal/ssa/func_test.go +++ b/src/cmd/compile/internal/ssa/func_test.go @@ -232,7 +232,7 @@ func Bloc(name string, entries ...interface{}) bloc { } // Valu defines a value in a block. -func Valu(name string, op Op, t *types.Type, auxint int64, aux interface{}, args ...string) valu { +func Valu(name string, op Op, t *types.Type, auxint int64, aux Aux, args ...string) valu { return valu{name, op, t, auxint, aux, args} } @@ -277,7 +277,7 @@ type valu struct { op Op t *types.Type auxint int64 - aux interface{} + aux Aux args []string } @@ -402,12 +402,12 @@ func TestEquiv(t *testing.T) { cfg.Fun("entry", Bloc("entry", Valu("mem", OpInitMem, types.TypeMem, 0, nil), - Valu("a", OpConst64, cfg.config.Types.Int64, 0, 14), + Valu("a", OpConstString, cfg.config.Types.String, 0, StringToAux("foo")), Exit("mem"))), cfg.Fun("entry", Bloc("entry", Valu("mem", OpInitMem, types.TypeMem, 0, nil), - Valu("a", OpConst64, cfg.config.Types.Int64, 0, 26), + Valu("a", OpConstString, cfg.config.Types.String, 0, StringToAux("bar")), Exit("mem"))), }, // value args different diff --git a/src/cmd/compile/internal/ssa/nilcheck_test.go b/src/cmd/compile/internal/ssa/nilcheck_test.go index 16d94614d8..2e32afe2a6 100644 --- a/src/cmd/compile/internal/ssa/nilcheck_test.go +++ b/src/cmd/compile/internal/ssa/nilcheck_test.go @@ -212,7 +212,7 @@ func TestNilcheckPhi(t *testing.T) { Valu("mem", OpInitMem, types.TypeMem, 0, nil), Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil), Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil), - Valu("baddr", OpLocalAddr, c.config.Types.Bool, 0, "b", "sp", "mem"), + Valu("baddr", OpLocalAddr, c.config.Types.Bool, 0, StringToAux("b"), "sp", "mem"), Valu("bool1", OpLoad, c.config.Types.Bool, 0, nil, "baddr", "mem"), If("bool1", "b1", "b2")), Bloc("b1", diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index 6f029a421e..97726a6f95 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -197,6 +197,8 @@ func ClosureAuxCall(args []Param, results []Param) *AuxCall { return &AuxCall{Fn: nil, args: args, results: results} } +func (*AuxCall) CanBeAnSSAAux() {} + const ( auxNone auxType = iota auxBool // auxInt is 0/1 for false/true @@ -248,6 +250,7 @@ const ( type Sym interface { String() string CanBeAnSSASym() + CanBeAnSSAAux() } // A ValAndOff is used by the several opcodes. It holds diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 24efd38fb7..9abfe0938b 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -678,43 +678,53 @@ func opToAuxInt(o Op) int64 { return int64(o) } -func auxToString(i interface{}) string { - return i.(string) +// Aux is an interface to hold miscellaneous data in Blocks and Values. +type Aux interface { + CanBeAnSSAAux() } -func auxToSym(i interface{}) Sym { + +// stringAux wraps string values for use in Aux. +type stringAux string + +func (stringAux) CanBeAnSSAAux() {} + +func auxToString(i Aux) string { + return string(i.(stringAux)) +} +func auxToSym(i Aux) Sym { // TODO: kind of a hack - allows nil interface through s, _ := i.(Sym) return s } -func auxToType(i interface{}) *types.Type { +func auxToType(i Aux) *types.Type { return i.(*types.Type) } -func auxToCall(i interface{}) *AuxCall { +func auxToCall(i Aux) *AuxCall { return i.(*AuxCall) } -func auxToS390xCCMask(i interface{}) s390x.CCMask { +func auxToS390xCCMask(i Aux) s390x.CCMask { return i.(s390x.CCMask) } -func auxToS390xRotateParams(i interface{}) s390x.RotateParams { +func auxToS390xRotateParams(i Aux) s390x.RotateParams { return i.(s390x.RotateParams) } -func stringToAux(s string) interface{} { +func StringToAux(s string) Aux { + return stringAux(s) +} +func symToAux(s Sym) Aux { return s } -func symToAux(s Sym) interface{} { +func callToAux(s *AuxCall) Aux { return s } -func callToAux(s *AuxCall) interface{} { - return s -} -func typeToAux(t *types.Type) interface{} { +func typeToAux(t *types.Type) Aux { return t } -func s390xCCMaskToAux(c s390x.CCMask) interface{} { +func s390xCCMaskToAux(c s390x.CCMask) Aux { return c } -func s390xRotateParamsToAux(r s390x.RotateParams) interface{} { +func s390xRotateParamsToAux(r s390x.RotateParams) Aux { return r } @@ -725,7 +735,7 @@ func uaddOvf(a, b int64) bool { // de-virtualize an InterCall // 'sym' is the symbol for the itab -func devirt(v *Value, aux interface{}, sym Sym, offset int64) *AuxCall { +func devirt(v *Value, aux Aux, sym Sym, offset int64) *AuxCall { f := v.Block.Func n, ok := sym.(*obj.LSym) if !ok { @@ -748,7 +758,7 @@ func devirt(v *Value, aux interface{}, sym Sym, offset int64) *AuxCall { // de-virtualize an InterLECall // 'sym' is the symbol for the itab -func devirtLESym(v *Value, aux interface{}, sym Sym, offset int64) *obj.LSym { +func devirtLESym(v *Value, aux Aux, sym Sym, offset int64) *obj.LSym { n, ok := sym.(*obj.LSym) if !ok { return nil diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go index edc43aaae7..993c5a580f 100644 --- a/src/cmd/compile/internal/ssa/value.go +++ b/src/cmd/compile/internal/ssa/value.go @@ -36,7 +36,7 @@ type Value struct { // Users of AuxInt which interpret AuxInt as unsigned (e.g. shifts) must be careful. // Use Value.AuxUnsigned to get the zero-extended value of AuxInt. AuxInt int64 - Aux interface{} + Aux Aux // Arguments of this value Args []*Value @@ -492,3 +492,6 @@ func (v *Value) removeable() bool { } return true } + +// TODO(mdempsky): Shouldn't be necessary; see discussion at golang.org/cl/275756 +func (*Value) CanBeAnSSAAux() {} diff --git a/src/cmd/compile/internal/ssa/zcse.go b/src/cmd/compile/internal/ssa/zcse.go index ec38b7d1ba..e08272c345 100644 --- a/src/cmd/compile/internal/ssa/zcse.go +++ b/src/cmd/compile/internal/ssa/zcse.go @@ -57,7 +57,7 @@ func zcse(f *Func) { type vkey struct { op Op ai int64 // aux int - ax interface{} // aux + ax Aux // aux t *types.Type // type } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index c5807af199..e968a799e3 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -164,6 +164,8 @@ type Type struct { flags bitset8 } +func (*Type) CanBeAnSSAAux() {} + const ( typeNotInHeap = 1 << iota // type cannot be heap allocated typeBroke // broken type definition diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 8c8ff587ff..eaebfaf4b6 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -723,8 +723,8 @@ func (s *LSym) String() string { } // The compiler needs *LSym to be assignable to cmd/compile/internal/ssa.Sym. -func (s *LSym) CanBeAnSSASym() { -} +func (*LSym) CanBeAnSSASym() {} +func (*LSym) CanBeAnSSAAux() {} type Pcln struct { // Aux symbols for pcln diff --git a/src/cmd/internal/obj/s390x/condition_code.go b/src/cmd/internal/obj/s390x/condition_code.go index 764fc5bc6a..f498fd6f77 100644 --- a/src/cmd/internal/obj/s390x/condition_code.go +++ b/src/cmd/internal/obj/s390x/condition_code.go @@ -124,3 +124,5 @@ func (c CCMask) String() string { // invalid return fmt.Sprintf("Invalid (%#x)", c) } + +func (CCMask) CanBeAnSSAAux() {} diff --git a/src/cmd/internal/obj/s390x/rotate.go b/src/cmd/internal/obj/s390x/rotate.go index 7dbc45e648..c999880492 100644 --- a/src/cmd/internal/obj/s390x/rotate.go +++ b/src/cmd/internal/obj/s390x/rotate.go @@ -113,3 +113,5 @@ func (r RotateParams) OutMerge(mask uint64) *RotateParams { func (r RotateParams) InMerge(mask uint64) *RotateParams { return r.OutMerge(bits.RotateLeft64(mask, int(r.Amount))) } + +func (RotateParams) CanBeAnSSAAux() {} From dcec658f6c9798b226d2f1e72a7b22b613e95c00 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 6 Dec 2020 12:02:22 -0800 Subject: [PATCH 184/212] [dev.regabi] cmd/compile: change LocalSlot.N to *ir.Name This was already documented as always being an ONAME, so it just needed a few type assertion changes. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: I61f4b6ebd57c43b41977f4b37b81fe94fb11a723 Reviewed-on: https://go-review.googlesource.com/c/go/+/275757 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Reviewed-by: Russ Cox Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/ssa.go | 7 +++---- src/cmd/compile/internal/ssa/config.go | 2 +- src/cmd/compile/internal/ssa/debug.go | 2 +- src/cmd/compile/internal/ssa/export_test.go | 2 +- src/cmd/compile/internal/ssa/location.go | 2 +- src/cmd/compile/internal/ssa/sizeof_test.go | 2 +- src/cmd/compile/internal/ssa/stackalloc.go | 2 +- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 95650328b1..2378ea7711 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -6078,7 +6078,7 @@ func (s *state) addNamedValue(n ir.Node, v *ssa.Value) { if n.Class() == ir.PAUTO && n.Offset() != 0 { s.Fatalf("AUTO var with offset %v %d", n, n.Offset()) } - loc := ssa.LocalSlot{N: n, Type: n.Type(), Off: 0} + loc := ssa.LocalSlot{N: n.Name(), Type: n.Type(), Off: 0} values, ok := s.f.NamedValues[loc] if !ok { s.f.Names = append(s.f.Names, loc) @@ -6979,9 +6979,8 @@ func (e *ssafn) StringData(s string) *obj.LSym { return data } -func (e *ssafn) Auto(pos src.XPos, t *types.Type) ir.Node { - n := tempAt(pos, e.curfn, t) // Note: adds new auto to e.curfn.Func.Dcl list - return n +func (e *ssafn) Auto(pos src.XPos, t *types.Type) *ir.Name { + return tempAt(pos, e.curfn, t) // Note: adds new auto to e.curfn.Func.Dcl list } func (e *ssafn) SplitString(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) { diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index eeabd81d03..8dc2ee8213 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -139,7 +139,7 @@ type Frontend interface { // Auto returns a Node for an auto variable of the given type. // The SSA compiler uses this function to allocate space for spills. - Auto(src.XPos, *types.Type) ir.Node + Auto(src.XPos, *types.Type) *ir.Name // Given the name for a compound type, returns the name we should use // for the parts of that compound type. diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go index 44e91270fa..6123978e55 100644 --- a/src/cmd/compile/internal/ssa/debug.go +++ b/src/cmd/compile/internal/ssa/debug.go @@ -380,7 +380,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu for _, b := range f.Blocks { for _, v := range b.Values { if v.Op == OpVarDef || v.Op == OpVarKill { - n := v.Aux.(ir.Node) + n := v.Aux.(*ir.Name) if ir.IsSynthetic(n) { continue } diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index 55fce31088..644baa8548 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -68,7 +68,7 @@ type TestFrontend struct { func (TestFrontend) StringData(s string) *obj.LSym { return nil } -func (TestFrontend) Auto(pos src.XPos, t *types.Type) ir.Node { +func (TestFrontend) Auto(pos src.XPos, t *types.Type) *ir.Name { n := ir.NewNameAt(pos, &types.Sym{Name: "aFakeAuto"}) n.SetClass(ir.PAUTO) return n diff --git a/src/cmd/compile/internal/ssa/location.go b/src/cmd/compile/internal/ssa/location.go index 3dc3a81703..69f90d9ab4 100644 --- a/src/cmd/compile/internal/ssa/location.go +++ b/src/cmd/compile/internal/ssa/location.go @@ -60,7 +60,7 @@ func (r *Register) GCNum() int16 { // { N: len, Type: int, Off: 0, SplitOf: parent, SplitOffset: 8} // parent = &{N: s, Type: string} type LocalSlot struct { - N ir.Node // an ONAME *gc.Node representing a stack location. + N *ir.Name // an ONAME *ir.Name representing a stack location. Type *types.Type // type of slot Off int64 // offset of slot in N diff --git a/src/cmd/compile/internal/ssa/sizeof_test.go b/src/cmd/compile/internal/ssa/sizeof_test.go index 60ada011e3..a27002ee3a 100644 --- a/src/cmd/compile/internal/ssa/sizeof_test.go +++ b/src/cmd/compile/internal/ssa/sizeof_test.go @@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) { }{ {Value{}, 72, 112}, {Block{}, 164, 304}, - {LocalSlot{}, 32, 48}, + {LocalSlot{}, 28, 40}, {valState{}, 28, 40}, } diff --git a/src/cmd/compile/internal/ssa/stackalloc.go b/src/cmd/compile/internal/ssa/stackalloc.go index 5257d44cfe..68a6f08a2a 100644 --- a/src/cmd/compile/internal/ssa/stackalloc.go +++ b/src/cmd/compile/internal/ssa/stackalloc.go @@ -157,7 +157,7 @@ func (s *stackAllocState) stackalloc() { if v.Aux == nil { f.Fatalf("%s has nil Aux\n", v.LongString()) } - loc := LocalSlot{N: v.Aux.(ir.Node), Type: v.Type, Off: v.AuxInt} + loc := LocalSlot{N: v.Aux.(*ir.Name), Type: v.Type, Off: v.AuxInt} if f.pass.debug > stackDebug { fmt.Printf("stackalloc %s to %s\n", v, loc) } From 9c91cab0da9814a598f2c4f7568b6276ff972672 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 8 Dec 2020 04:21:33 +1100 Subject: [PATCH 185/212] runtime: correct sigfwd on openbsd/mips64 Position independent code expects that R25 (aka $t9) contains the address of the called function. As such, use R25 when calling from sigfwd. Change-Id: I66b2b9bfa1f1bb983c7385eb2eaa19d9cd87d9fb Reviewed-on: https://go-review.googlesource.com/c/go/+/275893 Trust: Joel Sing Reviewed-by: Cherry Zhang --- src/runtime/sys_openbsd_mips64.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/sys_openbsd_mips64.s b/src/runtime/sys_openbsd_mips64.s index 57a5dbd40e..3e4d209081 100644 --- a/src/runtime/sys_openbsd_mips64.s +++ b/src/runtime/sys_openbsd_mips64.s @@ -244,8 +244,8 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 MOVW sig+8(FP), R4 MOVV info+16(FP), R5 MOVV ctx+24(FP), R6 - MOVV fn+0(FP), R7 - CALL (R7) // Alignment for ELF ABI? + MOVV fn+0(FP), R25 // Must use R25, needed for PIC code. + CALL (R25) RET TEXT runtime·sigtramp(SB),NOSPLIT,$192 From 1c8943a6add218f6ffd86c0952372fe54b0672a4 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 6 Dec 2020 18:10:34 -0800 Subject: [PATCH 186/212] [dev.regabi] cmd/compile: introduce FwdRefAux for wrapping ir.Node as ssa.Aux OpFwdRef is the only SSA value that needs the ability to store an arbitrary ir.Node in its Aux field. Every other SSA value always uses an *ir.Name. This CL introduces FwdRefAux, which wraps an ir.Node and implements the ssa.Aux tag interface, so that a subsequent refactoring can change ir.Node to not implement ssa.Aux. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: Id1475b28847579573cd376e82f28761d84cd1c23 Reviewed-on: https://go-review.googlesource.com/c/go/+/275788 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/gc/phi.go | 18 +++++++++++++----- src/cmd/compile/internal/gc/ssa.go | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/gc/phi.go b/src/cmd/compile/internal/gc/phi.go index 677bfc92df..def11e1be0 100644 --- a/src/cmd/compile/internal/gc/phi.go +++ b/src/cmd/compile/internal/gc/phi.go @@ -23,6 +23,14 @@ const smallBlocks = 500 const debugPhi = false +// FwdRefAux wraps an arbitrary ir.Node as an ssa.Aux for use with OpFwdref. +type FwdRefAux struct { + _ [0]func() // ensure ir.Node isn't compared for equality + N ir.Node +} + +func (FwdRefAux) CanBeAnSSAAux() {} + // insertPhis finds all the places in the function where a phi is // necessary and inserts them. // Uses FwdRef ops to find all uses of variables, and s.defvars to find @@ -79,7 +87,7 @@ func (s *phiState) insertPhis() { if v.Op != ssa.OpFwdRef { continue } - var_ := v.Aux.(ir.Node) + var_ := v.Aux.(FwdRefAux).N // Optimization: look back 1 block for the definition. if len(b.Preds) == 1 { @@ -319,7 +327,7 @@ func (s *phiState) resolveFwdRefs() { if v.Op != ssa.OpFwdRef { continue } - n := s.varnum[v.Aux.(ir.Node)] + n := s.varnum[v.Aux.(FwdRefAux).N] v.Op = ssa.OpCopy v.Aux = nil v.AddArg(values[n]) @@ -450,7 +458,7 @@ func (s *simplePhiState) insertPhis() { continue } s.fwdrefs = append(s.fwdrefs, v) - var_ := v.Aux.(ir.Node) + var_ := v.Aux.(FwdRefAux).N if _, ok := s.defvars[b.ID][var_]; !ok { s.defvars[b.ID][var_] = v // treat FwdDefs as definitions. } @@ -464,7 +472,7 @@ loop: v := s.fwdrefs[len(s.fwdrefs)-1] s.fwdrefs = s.fwdrefs[:len(s.fwdrefs)-1] b := v.Block - var_ := v.Aux.(ir.Node) + var_ := v.Aux.(FwdRefAux).N if b == s.f.Entry { // No variable should be live at entry. s.s.Fatalf("Value live at entry. It shouldn't be. func %s, node %v, value %v", s.f.Name, var_, v) @@ -531,7 +539,7 @@ func (s *simplePhiState) lookupVarOutgoing(b *ssa.Block, t *types.Type, var_ ir. } } // Generate a FwdRef for the variable and return that. - v := b.NewValue0A(line, ssa.OpFwdRef, t, var_) + v := b.NewValue0A(line, ssa.OpFwdRef, t, FwdRefAux{N: var_}) s.defvars[b.ID][var_] = v s.s.addNamedValue(var_, v) s.fwdrefs = append(s.fwdrefs, v) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 2378ea7711..90c7546042 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -6051,7 +6051,7 @@ func (s *state) variable(name ir.Node, t *types.Type) *ssa.Value { } // Make a FwdRef, which records a value that's live on block input. // We'll find the matching definition as part of insertPhis. - v = s.newValue0A(ssa.OpFwdRef, t, name) + v = s.newValue0A(ssa.OpFwdRef, t, FwdRefAux{N: name}) s.fwdVars[name] = v s.addNamedValue(name, v) return v From 6db970e20acd7caeed268fdff458609570f21c90 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 6 Dec 2020 18:13:43 -0800 Subject: [PATCH 187/212] [dev.regabi] cmd/compile: rewrite Aux uses of ir.Node to *ir.Name [generated] Now that the only remaining ir.Node implementation that is stored (directly) into ssa.Aux, we can rewrite all of the conversions between ir.Node and ssa.Aux to use *ir.Name instead. rf doesn't have a way to rewrite the type switch case clauses, so we just use sed instead. There's only a handful, and they're the only times that "case ir.Node" appears anyway. The next CL will move the tag method declarations so that ir.Node no longer implements ssa.Aux. Passes buildall w/ toolstash -cmp. Updates #42982. [git-generate] cd src/cmd/compile/internal sed -i -e 's/case ir.Node/case *ir.Name/' gc/plive.go */ssa.go cd ssa rf ' ex . ../gc { import "cmd/compile/internal/ir" var v *Value v.Aux.(ir.Node) -> v.Aux.(*ir.Name) var n ir.Node var asAux func(Aux) strict n # only match ir.Node-typed expressions; not *ir.Name implicit asAux # match implicit assignments to ssa.Aux asAux(n) -> n.(*ir.Name) } ' Change-Id: I3206ef5f12a7cfa37c5fecc67a1ca02ea4d52b32 Reviewed-on: https://go-review.googlesource.com/c/go/+/275789 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/arm/ssa.go | 2 +- src/cmd/compile/internal/arm64/ssa.go | 2 +- src/cmd/compile/internal/gc/pgen.go | 2 +- src/cmd/compile/internal/gc/plive.go | 6 ++-- src/cmd/compile/internal/gc/ssa.go | 40 +++++++++++------------ src/cmd/compile/internal/mips/ssa.go | 2 +- src/cmd/compile/internal/mips64/ssa.go | 2 +- src/cmd/compile/internal/riscv64/ssa.go | 2 +- src/cmd/compile/internal/ssa/deadstore.go | 10 +++--- src/cmd/compile/internal/ssa/debug.go | 2 +- src/cmd/compile/internal/ssa/nilcheck.go | 2 +- src/cmd/compile/internal/ssa/regalloc.go | 2 +- src/cmd/compile/internal/wasm/ssa.go | 2 +- 13 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/cmd/compile/internal/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go index b34e2973b2..8b155712aa 100644 --- a/src/cmd/compile/internal/arm/ssa.go +++ b/src/cmd/compile/internal/arm/ssa.go @@ -546,7 +546,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case ir.Node: + case *ir.Name: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index d5bd9687cf..3eb0ae6557 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -396,7 +396,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case ir.Node: + case *ir.Name: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index 1da0929290..a7b19953ba 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -128,7 +128,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { scratchUsed := false for _, b := range f.Blocks { for _, v := range b.Values { - if n, ok := v.Aux.(ir.Node); ok { + if n, ok := v.Aux.(*ir.Name); ok { switch n.Class() { case ir.PPARAM, ir.PPARAMOUT: // Don't modify nodfp; it is a global. diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index 06e423daa1..9952bfcf36 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -324,9 +324,9 @@ func affectedNode(v *ssa.Value) (ir.Node, ssa.SymEffect) { return n, ssa.SymWrite case ssa.OpVarLive: - return v.Aux.(ir.Node), ssa.SymRead + return v.Aux.(*ir.Name), ssa.SymRead case ssa.OpVarDef, ssa.OpVarKill: - return v.Aux.(ir.Node), ssa.SymWrite + return v.Aux.(*ir.Name), ssa.SymWrite case ssa.OpKeepAlive: n, _ := AutoVar(v.Args[0]) return n, ssa.SymRead @@ -341,7 +341,7 @@ func affectedNode(v *ssa.Value) (ir.Node, ssa.SymEffect) { case nil, *obj.LSym: // ok, but no node return nil, e - case ir.Node: + case *ir.Name: return a, e default: base.Fatalf("weird aux: %s", v.LongString()) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 90c7546042..e8f345d8f6 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1504,7 +1504,7 @@ func (s *state) stmt(n ir.Node) { case ir.OVARDEF: if !s.canSSA(n.Left()) { - s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, n.Left(), s.mem(), false) + s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, n.Left().(*ir.Name), s.mem(), false) } case ir.OVARKILL: // Insert a varkill op to record that a variable is no longer live. @@ -1512,7 +1512,7 @@ func (s *state) stmt(n ir.Node) { // varkill in the store chain is enough to keep it correctly ordered // with respect to call ops. if !s.canSSA(n.Left()) { - s.vars[memVar] = s.newValue1Apos(ssa.OpVarKill, types.TypeMem, n.Left(), s.mem(), false) + s.vars[memVar] = s.newValue1Apos(ssa.OpVarKill, types.TypeMem, n.Left().(*ir.Name), s.mem(), false) } case ir.OVARLIVE: @@ -1525,7 +1525,7 @@ func (s *state) stmt(n ir.Node) { default: s.Fatalf("VARLIVE variable %v must be Auto or Arg", n.Left()) } - s.vars[memVar] = s.newValue1A(ssa.OpVarLive, types.TypeMem, n.Left(), s.mem()) + s.vars[memVar] = s.newValue1A(ssa.OpVarLive, types.TypeMem, n.Left().(*ir.Name), s.mem()) case ir.OCHECKNIL: p := s.expr(n.Left()) @@ -1571,7 +1571,7 @@ func (s *state) exit() *ssa.Block { for _, n := range s.returns { addr := s.decladdrs[n] val := s.variable(n, n.Type()) - s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem()) + s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n.(*ir.Name), s.mem()) s.store(n.Type(), addr, val) // TODO: if val is ever spilled, we'd like to use the // PPARAMOUT slot for spilling it. That won't happen @@ -2866,7 +2866,7 @@ func (s *state) append(n ir.Node, inplace bool) *ssa.Value { if inplace { if sn.Op() == ir.ONAME && sn.Class() != ir.PEXTERN { // Tell liveness we're about to build a new slice - s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, sn, s.mem()) + s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, sn.(*ir.Name), s.mem()) } capaddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, sliceCapOffset, addr) s.store(types.Types[types.TINT], capaddr, r[2]) @@ -3076,7 +3076,7 @@ func (s *state) assign(left ir.Node, right *ssa.Value, deref bool, skip skipMask // If this assignment clobbers an entire local variable, then emit // OpVarDef so liveness analysis knows the variable is redefined. if base := clobberBase(left); base.Op() == ir.ONAME && base.Class() != ir.PEXTERN && skip == 0 { - s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, base, s.mem(), !ir.IsAutoTmp(base)) + s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, base.(*ir.Name), s.mem(), !ir.IsAutoTmp(base)) } // Left is not ssa-able. Compute its address. @@ -4236,7 +4236,7 @@ func (s *state) openDeferRecord(n ir.Node) { // call the function directly if it is a static function. closureVal := s.expr(fn) closure := s.openDeferSave(nil, fn.Type(), closureVal) - opendefer.closureNode = closure.Aux.(ir.Node) + opendefer.closureNode = closure.Aux.(*ir.Name) if !(fn.Op() == ir.ONAME && fn.Class() == ir.PFUNC) { opendefer.closure = closure } @@ -4249,7 +4249,7 @@ func (s *state) openDeferRecord(n ir.Node) { // runtime panic code to use. But in the defer exit code, we will // call the method directly. closure := s.openDeferSave(nil, fn.Type(), closureVal) - opendefer.closureNode = closure.Aux.(ir.Node) + opendefer.closureNode = closure.Aux.(*ir.Name) } else { if fn.Op() != ir.ODOTINTER { base.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op()) @@ -4259,8 +4259,8 @@ func (s *state) openDeferRecord(n ir.Node) { // Important to get the receiver type correct, so it is recognized // as a pointer for GC purposes. opendefer.rcvr = s.openDeferSave(nil, fn.Type().Recv().Type, rcvr) - opendefer.closureNode = opendefer.closure.Aux.(ir.Node) - opendefer.rcvrNode = opendefer.rcvr.Aux.(ir.Node) + opendefer.closureNode = opendefer.closure.Aux.(*ir.Name) + opendefer.rcvrNode = opendefer.rcvr.Aux.(*ir.Name) } for _, argn := range n.Rlist().Slice() { var v *ssa.Value @@ -4270,7 +4270,7 @@ func (s *state) openDeferRecord(n ir.Node) { v = s.openDeferSave(argn, argn.Type(), nil) } args = append(args, v) - argNodes = append(argNodes, v.Aux.(ir.Node)) + argNodes = append(argNodes, v.Aux.(*ir.Name)) } opendefer.argVals = args opendefer.argNodes = argNodes @@ -4458,16 +4458,16 @@ func (s *state) openDeferExit() { // use the first call of the last defer exit to compute liveness // for the deferreturn, so we want all stack slots to be live. if r.closureNode != nil { - s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, r.closureNode, s.mem(), false) + s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, r.closureNode.(*ir.Name), s.mem(), false) } if r.rcvrNode != nil { if r.rcvrNode.Type().HasPointers() { - s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, r.rcvrNode, s.mem(), false) + s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, r.rcvrNode.(*ir.Name), s.mem(), false) } } for _, argNode := range r.argNodes { if argNode.Type().HasPointers() { - s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, argNode, s.mem(), false) + s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, argNode.(*ir.Name), s.mem(), false) } } @@ -4855,17 +4855,17 @@ func (s *state) addr(n ir.Node) *ssa.Value { } if n == nodfp { // Special arg that points to the frame pointer (Used by ORECOVER). - return s.entryNewValue2A(ssa.OpLocalAddr, t, n, s.sp, s.startmem) + return s.entryNewValue2A(ssa.OpLocalAddr, t, n.(*ir.Name), s.sp, s.startmem) } s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs) return nil case ir.PAUTO: - return s.newValue2Apos(ssa.OpLocalAddr, t, n, s.sp, s.mem(), !ir.IsAutoTmp(n)) + return s.newValue2Apos(ssa.OpLocalAddr, t, n.(*ir.Name), s.sp, s.mem(), !ir.IsAutoTmp(n)) case ir.PPARAMOUT: // Same as PAUTO -- cannot generate LEA early. // ensure that we reuse symbols for out parameters so // that cse works on their addresses - return s.newValue2Apos(ssa.OpLocalAddr, t, n, s.sp, s.mem(), true) + return s.newValue2Apos(ssa.OpLocalAddr, t, n.(*ir.Name), s.sp, s.mem(), true) default: s.Fatalf("variable address class %v not implemented", n.Class()) return nil @@ -5951,7 +5951,7 @@ func (s *state) dottype(n ir.Node, commaok bool) (res, resok *ssa.Value) { // unSSAable type, use temporary. // TODO: get rid of some of these temporaries. tmp = tempAt(n.Pos(), s.curfn, n.Type()) - s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, tmp, s.mem()) + s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, tmp.(*ir.Name), s.mem()) addr = s.addr(tmp) } @@ -6027,7 +6027,7 @@ func (s *state) dottype(n ir.Node, commaok bool) (res, resok *ssa.Value) { delete(s.vars, valVar) } else { res = s.load(n.Type(), addr) - s.vars[memVar] = s.newValue1A(ssa.OpVarKill, types.TypeMem, tmp, s.mem()) + s.vars[memVar] = s.newValue1A(ssa.OpVarKill, types.TypeMem, tmp.(*ir.Name), s.mem()) } resok = s.variable(okVar, types.Types[types.TBOOL]) delete(s.vars, okVar) @@ -6680,7 +6680,7 @@ func AddAux2(a *obj.Addr, v *ssa.Value, offset int64) { case *obj.LSym: a.Name = obj.NAME_EXTERN a.Sym = n - case ir.Node: + case *ir.Name: if n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT { a.Name = obj.NAME_PARAM a.Sym = ir.Orig(n).Sym().Linksym() diff --git a/src/cmd/compile/internal/mips/ssa.go b/src/cmd/compile/internal/mips/ssa.go index bd71b2fcd8..10453c27d5 100644 --- a/src/cmd/compile/internal/mips/ssa.go +++ b/src/cmd/compile/internal/mips/ssa.go @@ -289,7 +289,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case ir.Node: + case *ir.Name: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go index bcadebde4e..9aaf8715de 100644 --- a/src/cmd/compile/internal/mips64/ssa.go +++ b/src/cmd/compile/internal/mips64/ssa.go @@ -263,7 +263,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case ir.Node: + case *ir.Name: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index c81b6897a6..d382304d72 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -324,7 +324,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case ir.Node: + case *ir.Name: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go index f3ef33d670..d0446a0311 100644 --- a/src/cmd/compile/internal/ssa/deadstore.go +++ b/src/cmd/compile/internal/ssa/deadstore.go @@ -147,7 +147,7 @@ func elimDeadAutosGeneric(f *Func) { switch v.Op { case OpAddr, OpLocalAddr: // Propagate the address if it points to an auto. - n, ok := v.Aux.(ir.Node) + n, ok := v.Aux.(*ir.Name) if !ok || n.Class() != ir.PAUTO { return } @@ -158,7 +158,7 @@ func elimDeadAutosGeneric(f *Func) { return case OpVarDef, OpVarKill: // v should be eliminated if we eliminate the auto. - n, ok := v.Aux.(ir.Node) + n, ok := v.Aux.(*ir.Name) if !ok || n.Class() != ir.PAUTO { return } @@ -174,7 +174,7 @@ func elimDeadAutosGeneric(f *Func) { // for open-coded defers from being removed (since they // may not be used by the inline code, but will be used by // panic processing). - n, ok := v.Aux.(ir.Node) + n, ok := v.Aux.(*ir.Name) if !ok || n.Class() != ir.PAUTO { return } @@ -303,7 +303,7 @@ func elimUnreadAutos(f *Func) { var stores []*Value for _, b := range f.Blocks { for _, v := range b.Values { - n, ok := v.Aux.(ir.Node) + n, ok := v.Aux.(*ir.Name) if !ok { continue } @@ -335,7 +335,7 @@ func elimUnreadAutos(f *Func) { // Eliminate stores to unread autos. for _, store := range stores { - n, _ := store.Aux.(ir.Node) + n, _ := store.Aux.(*ir.Name) if seen[n] { continue } diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go index 6123978e55..405817dbe1 100644 --- a/src/cmd/compile/internal/ssa/debug.go +++ b/src/cmd/compile/internal/ssa/debug.go @@ -718,7 +718,7 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) switch { case v.Op == OpVarDef, v.Op == OpVarKill: - n := v.Aux.(ir.Node) + n := v.Aux.(*ir.Name) if ir.IsSynthetic(n) { break } diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go index b36f6b97e1..bae50657c9 100644 --- a/src/cmd/compile/internal/ssa/nilcheck.go +++ b/src/cmd/compile/internal/ssa/nilcheck.go @@ -236,7 +236,7 @@ func nilcheckelim2(f *Func) { continue } if v.Type.IsMemory() || v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() { - if v.Op == OpVarKill || v.Op == OpVarLive || (v.Op == OpVarDef && !v.Aux.(ir.Node).Type().HasPointers()) { + if v.Op == OpVarKill || v.Op == OpVarLive || (v.Op == OpVarDef && !v.Aux.(*ir.Name).Type().HasPointers()) { // These ops don't really change memory. continue // Note: OpVarDef requires that the defined variable not have pointers. diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 376ca97512..8c25b1c81d 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -1249,7 +1249,7 @@ func (s *regAllocState) regalloc(f *Func) { // This forces later liveness analysis to make the // value live at this point. v.SetArg(0, s.makeSpill(a, b)) - } else if _, ok := a.Aux.(ir.Node); ok && vi.rematerializeable { + } else if _, ok := a.Aux.(*ir.Name); ok && vi.rematerializeable { // Rematerializeable value with a gc.Node. This is the address of // a stack object (e.g. an LEAQ). Keep the object live. // Change it to VarLive, which is what plive expects for locals. diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go index e7451381b4..01ba721556 100644 --- a/src/cmd/compile/internal/wasm/ssa.go +++ b/src/cmd/compile/internal/wasm/ssa.go @@ -237,7 +237,7 @@ func ssaGenValueOnStack(s *gc.SSAGenState, v *ssa.Value, extend bool) { switch v.Aux.(type) { case *obj.LSym: gc.AddAux(&p.From, v) - case ir.Node: + case *ir.Name: p.From.Reg = v.Args[0].Reg() gc.AddAux(&p.From, v) default: From bb31c75343de2114f541cd66870ace3f33047550 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 6 Dec 2020 18:25:41 -0800 Subject: [PATCH 188/212] [dev.regabi] cmd/compile: ir.Node is no longer an ssa.Aux After the previous rewrite, we can now remove CanBeAnSSASym and CanBeAnSSAAux from the generic Node interface, and declare them just on *ir.Name. Updates #42982. Change-Id: I865771fd30c95c009740410844f20ade08648343 Reviewed-on: https://go-review.googlesource.com/c/go/+/275790 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le Reviewed-by: Russ Cox --- src/cmd/compile/internal/ir/mini.go | 4 ---- src/cmd/compile/internal/ir/name.go | 4 +++- src/cmd/compile/internal/ir/node.go | 5 ----- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index edb3b197da..7ecdcbf32f 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -197,7 +197,3 @@ func (n *miniNode) SetOpt(interface{}) { panic(n.no("SetOpt")) } func (n *miniNode) MarkReadonly() { panic(n.no("MarkReadonly")) } func (n *miniNode) TChanDir() types.ChanDir { panic(n.no("TChanDir")) } func (n *miniNode) SetTChanDir(types.ChanDir) { panic(n.no("SetTChanDir")) } - -// TODO: Delete when these are removed from Node itself. -func (*miniNode) CanBeAnSSASym() {} -func (*miniNode) CanBeAnSSAAux() {} diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index c527ba281d..319c40e4e9 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -165,7 +165,9 @@ func (n *Name) SetOffset(x int64) { n.offset = x } func (n *Name) Iota() int64 { return n.offset } func (n *Name) SetIota(x int64) { n.offset = x } -func (*Name) CanBeNtype() {} +func (*Name) CanBeNtype() {} +func (*Name) CanBeAnSSASym() {} +func (*Name) CanBeAnSSAAux() {} func (n *Name) SetOp(op Op) { if n.op != ONONAME { diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index b878b00546..d6dab0b9e2 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -109,11 +109,6 @@ type Node interface { MarkNonNil() HasCall() bool SetHasCall(x bool) - - // Only for SSA and should be removed when SSA starts - // using a more specific type than Node. - CanBeAnSSASym() - CanBeAnSSAAux() } // Line returns n's position as a string. If n has been inlined, From dbf2fc8cff5f7d6a5fcbeea0d4b0349cc7d158e2 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 6 Dec 2020 18:28:49 -0800 Subject: [PATCH 189/212] [dev.regabi] cmd/compile: replace many uses of ir.Node with *ir.Name This commit adds exactly two "n := n.(*ir.Name)" statements, that are each immediately preceded by a "case ir.ONAME:" clause in an n.Op() switch. The rest of the changes are simply replacing "ir.Node" to "*ir.Name" and removing now unnecessary "n.(*ir.Name)" type assertions, exposing the latent typing details. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: I8ea3bbb7ddf0c7192245cafa49a19c0e7a556a39 Reviewed-on: https://go-review.googlesource.com/c/go/+/275791 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/inl.go | 5 ++-- src/cmd/compile/internal/gc/order.go | 6 ++--- src/cmd/compile/internal/gc/pgen.go | 28 +++++++++++----------- src/cmd/compile/internal/gc/ssa.go | 29 ++++++++++++----------- src/cmd/compile/internal/ssa/deadstore.go | 10 ++++---- src/cmd/compile/internal/ssa/debug.go | 8 +++---- 6 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index f965fa6325..37e5167c25 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -205,7 +205,7 @@ func caninl(fn *ir.Func) { visitor := hairyVisitor{ budget: inlineMaxBudget, extraCallCost: cc, - usedLocals: make(map[ir.Node]bool), + usedLocals: make(map[*ir.Name]bool), } if visitor.tooHairy(fn) { reason = visitor.reason @@ -292,7 +292,7 @@ type hairyVisitor struct { budget int32 reason string extraCallCost int32 - usedLocals map[ir.Node]bool + usedLocals map[*ir.Name]bool do func(ir.Node) error } @@ -431,6 +431,7 @@ func (v *hairyVisitor) doNode(n ir.Node) error { } case ir.ONAME: + n := n.(*ir.Name) if n.Class() == ir.PAUTO { v.usedLocals[n] = true } diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 39b78c9819..c3645256a6 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -63,7 +63,7 @@ func order(fn *ir.Func) { // newTemp allocates a new temporary with the given type, // pushes it onto the temp stack, and returns it. // If clear is true, newTemp emits code to zero the temporary. -func (o *Order) newTemp(t *types.Type, clear bool) ir.Node { +func (o *Order) newTemp(t *types.Type, clear bool) *ir.Name { var v *ir.Name // Note: LongString is close to the type equality we want, // but not exactly. We still need to double-check with types.Identical. @@ -107,11 +107,11 @@ func (o *Order) copyExpr(n ir.Node) ir.Node { // (The other candidate would be map access, but map access // returns a pointer to the result data instead of taking a pointer // to be filled in.) -func (o *Order) copyExprClear(n ir.Node) ir.Node { +func (o *Order) copyExprClear(n ir.Node) *ir.Name { return o.copyExpr1(n, true) } -func (o *Order) copyExpr1(n ir.Node, clear bool) ir.Node { +func (o *Order) copyExpr1(n ir.Node, clear bool) *ir.Name { t := n.Type() v := o.newTemp(t, clear) a := ir.Nod(ir.OAS, v, n) diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index a7b19953ba..5b04e10657 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -438,7 +438,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S // which used to use the ONAME form. isODCLFUNC := infosym.Name == "" - var apdecls []ir.Node + var apdecls []*ir.Name // Populate decls for fn. if isODCLFUNC { for _, n := range fn.Dcl { @@ -495,7 +495,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S return scopes, inlcalls } -func declPos(decl ir.Node) src.XPos { +func declPos(decl *ir.Name) src.XPos { if decl.Name().Defn != nil && (decl.Name().Captured() || decl.Name().Byval()) { // It's not clear which position is correct for captured variables here: // * decl.Pos is the wrong position for captured variables, in the inner @@ -518,10 +518,10 @@ func declPos(decl ir.Node) src.XPos { // createSimpleVars creates a DWARF entry for every variable declared in the // function, claiming that they are permanently on the stack. -func createSimpleVars(fnsym *obj.LSym, apDecls []ir.Node) ([]ir.Node, []*dwarf.Var, map[ir.Node]bool) { +func createSimpleVars(fnsym *obj.LSym, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var, map[*ir.Name]bool) { var vars []*dwarf.Var - var decls []ir.Node - selected := make(map[ir.Node]bool) + var decls []*ir.Name + selected := make(map[*ir.Name]bool) for _, n := range apDecls { if ir.IsAutoTmp(n) { continue @@ -534,7 +534,7 @@ func createSimpleVars(fnsym *obj.LSym, apDecls []ir.Node) ([]ir.Node, []*dwarf.V return decls, vars, selected } -func createSimpleVar(fnsym *obj.LSym, n ir.Node) *dwarf.Var { +func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var { var abbrev int offs := n.Offset() @@ -585,13 +585,13 @@ func createSimpleVar(fnsym *obj.LSym, n ir.Node) *dwarf.Var { // createComplexVars creates recomposed DWARF vars with location lists, // suitable for describing optimized code. -func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]ir.Node, []*dwarf.Var, map[ir.Node]bool) { +func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]*ir.Name, []*dwarf.Var, map[*ir.Name]bool) { debugInfo := fn.DebugInfo.(*ssa.FuncDebug) // Produce a DWARF variable entry for each user variable. - var decls []ir.Node + var decls []*ir.Name var vars []*dwarf.Var - ssaVars := make(map[ir.Node]bool) + ssaVars := make(map[*ir.Name]bool) for varID, dvar := range debugInfo.Vars { n := dvar @@ -611,11 +611,11 @@ func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]ir.Node, []*dwarf.Var, m // createDwarfVars process fn, returning a list of DWARF variables and the // Nodes they represent. -func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []ir.Node) ([]ir.Node, []*dwarf.Var) { +func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir.Name) ([]*ir.Name, []*dwarf.Var) { // Collect a raw list of DWARF vars. var vars []*dwarf.Var - var decls []ir.Node - var selected map[ir.Node]bool + var decls []*ir.Name + var selected map[*ir.Name]bool if base.Ctxt.Flag_locationlists && base.Ctxt.Flag_optimize && fn.DebugInfo != nil && complexOK { decls, vars, selected = createComplexVars(fnsym, fn) } else { @@ -714,9 +714,9 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []ir. // function that is not local to the package being compiled, then the // names of the variables may have been "versioned" to avoid conflicts // with local vars; disregard this versioning when sorting. -func preInliningDcls(fnsym *obj.LSym) []ir.Node { +func preInliningDcls(fnsym *obj.LSym) []*ir.Name { fn := base.Ctxt.DwFixups.GetPrecursorFunc(fnsym).(*ir.Func) - var rdcl []ir.Node + var rdcl []*ir.Name for _, n := range fn.Inl.Dcl { c := n.Sym().Name[0] // Avoid reporting "_" parameters, since if there are more than diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index e8f345d8f6..9539e9cc8a 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -410,7 +410,7 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func { } // Generate addresses of local declarations - s.decladdrs = map[ir.Node]*ssa.Value{} + s.decladdrs = map[*ir.Name]*ssa.Value{} var args []ssa.Param var results []ssa.Param for _, n := range fn.Dcl { @@ -576,7 +576,7 @@ type openDeferInfo struct { // function call are stored. argVals []*ssa.Value // The nodes representing the argtmps where the args of the defer are stored - argNodes []ir.Node + argNodes []*ir.Name } type state struct { @@ -613,7 +613,7 @@ type state struct { defvars []map[ir.Node]*ssa.Value // addresses of PPARAM and PPARAMOUT variables. - decladdrs map[ir.Node]*ssa.Value + decladdrs map[*ir.Name]*ssa.Value // starting values. Memory, stack pointer, and globals pointer startmem *ssa.Value @@ -633,7 +633,7 @@ type state struct { panics map[funcLine]*ssa.Block // list of PPARAMOUT (return) variables. - returns []ir.Node + returns []*ir.Name cgoUnsafeArgs bool hasdefer bool // whether the function contains a defer statement @@ -685,7 +685,7 @@ func (s *state) Fatalf(msg string, args ...interface{}) { func (s *state) Warnl(pos src.XPos, msg string, args ...interface{}) { s.f.Warnl(pos, msg, args...) } func (s *state) Debug_checknil() bool { return s.f.Frontend().Debug_checknil() } -func ssaMarker(name string) ir.Node { +func ssaMarker(name string) *ir.Name { return NewName(&types.Sym{Name: name}) } @@ -1571,7 +1571,7 @@ func (s *state) exit() *ssa.Block { for _, n := range s.returns { addr := s.decladdrs[n] val := s.variable(n, n.Type()) - s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n.(*ir.Name), s.mem()) + s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem()) s.store(n.Type(), addr, val) // TODO: if val is ever spilled, we'd like to use the // PPARAMOUT slot for spilling it. That won't happen @@ -4224,7 +4224,7 @@ func (s *state) openDeferRecord(n ir.Node) { s.stmtList(n.List()) var args []*ssa.Value - var argNodes []ir.Node + var argNodes []*ir.Name opendefer := &openDeferInfo{ n: n, @@ -4467,7 +4467,7 @@ func (s *state) openDeferExit() { } for _, argNode := range r.argNodes { if argNode.Type().HasPointers() { - s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, argNode.(*ir.Name), s.mem(), false) + s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, argNode, s.mem(), false) } } @@ -4838,6 +4838,7 @@ func (s *state) addr(n ir.Node) *ssa.Value { t := types.NewPtr(n.Type()) switch n.Op() { case ir.ONAME: + n := n.(*ir.Name) switch n.Class() { case ir.PEXTERN: // global variable @@ -4855,17 +4856,17 @@ func (s *state) addr(n ir.Node) *ssa.Value { } if n == nodfp { // Special arg that points to the frame pointer (Used by ORECOVER). - return s.entryNewValue2A(ssa.OpLocalAddr, t, n.(*ir.Name), s.sp, s.startmem) + return s.entryNewValue2A(ssa.OpLocalAddr, t, n, s.sp, s.startmem) } s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs) return nil case ir.PAUTO: - return s.newValue2Apos(ssa.OpLocalAddr, t, n.(*ir.Name), s.sp, s.mem(), !ir.IsAutoTmp(n)) + return s.newValue2Apos(ssa.OpLocalAddr, t, n, s.sp, s.mem(), !ir.IsAutoTmp(n)) case ir.PPARAMOUT: // Same as PAUTO -- cannot generate LEA early. // ensure that we reuse symbols for out parameters so // that cse works on their addresses - return s.newValue2Apos(ssa.OpLocalAddr, t, n.(*ir.Name), s.sp, s.mem(), true) + return s.newValue2Apos(ssa.OpLocalAddr, t, n, s.sp, s.mem(), true) default: s.Fatalf("variable address class %v not implemented", n.Class()) return nil @@ -6196,15 +6197,15 @@ func (s *SSAGenState) DebugFriendlySetPosFrom(v *ssa.Value) { } } -// byXoffset implements sort.Interface for []*Node using Xoffset as the ordering. -type byXoffset []ir.Node +// byXoffset implements sort.Interface for []*ir.Name using Xoffset as the ordering. +type byXoffset []*ir.Name func (s byXoffset) Len() int { return len(s) } func (s byXoffset) Less(i, j int) bool { return s[i].Offset() < s[j].Offset() } func (s byXoffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func emitStackObjects(e *ssafn, pp *Progs) { - var vars []ir.Node + var vars []*ir.Name for _, n := range e.curfn.Dcl { if livenessShouldTrack(n) && n.Addrtaken() { vars = append(vars, n) diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go index d0446a0311..a68c82ba97 100644 --- a/src/cmd/compile/internal/ssa/deadstore.go +++ b/src/cmd/compile/internal/ssa/deadstore.go @@ -137,9 +137,9 @@ func dse(f *Func) { // reaches stores then we delete all the stores. The other operations will then // be eliminated by the dead code elimination pass. func elimDeadAutosGeneric(f *Func) { - addr := make(map[*Value]ir.Node) // values that the address of the auto reaches - elim := make(map[*Value]ir.Node) // values that could be eliminated if the auto is - used := make(map[ir.Node]bool) // used autos that must be kept + addr := make(map[*Value]*ir.Name) // values that the address of the auto reaches + elim := make(map[*Value]*ir.Name) // values that could be eliminated if the auto is + used := make(map[*ir.Name]bool) // used autos that must be kept // visit the value and report whether any of the maps are updated visit := func(v *Value) (changed bool) { @@ -222,7 +222,7 @@ func elimDeadAutosGeneric(f *Func) { } // Propagate any auto addresses through v. - var node ir.Node + var node *ir.Name for _, a := range args { if n, ok := addr[a]; ok && !used[n] { if node == nil { @@ -299,7 +299,7 @@ func elimUnreadAutos(f *Func) { // Loop over all ops that affect autos taking note of which // autos we need and also stores that we might be able to // eliminate. - seen := make(map[ir.Node]bool) + seen := make(map[*ir.Name]bool) var stores []*Value for _, b := range f.Blocks { for _, v := range b.Values { diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go index 405817dbe1..68b6ab5fe9 100644 --- a/src/cmd/compile/internal/ssa/debug.go +++ b/src/cmd/compile/internal/ssa/debug.go @@ -25,7 +25,7 @@ type FuncDebug struct { // Slots is all the slots used in the debug info, indexed by their SlotID. Slots []LocalSlot // The user variables, indexed by VarID. - Vars []ir.Node + Vars []*ir.Name // The slots that make up each variable, indexed by VarID. VarSlots [][]SlotID // The location list data, indexed by VarID. Must be processed by PutLocationList. @@ -166,7 +166,7 @@ func (s *debugState) logf(msg string, args ...interface{}) { type debugState struct { // See FuncDebug. slots []LocalSlot - vars []ir.Node + vars []*ir.Name varSlots [][]SlotID lists [][]byte @@ -190,7 +190,7 @@ type debugState struct { // The pending location list entry for each user variable, indexed by VarID. pendingEntries []pendingEntry - varParts map[ir.Node][]SlotID + varParts map[*ir.Name][]SlotID blockDebug []BlockDebug pendingSlotLocs []VarLoc liveSlots []liveSlot @@ -347,7 +347,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu } if state.varParts == nil { - state.varParts = make(map[ir.Node][]SlotID) + state.varParts = make(map[*ir.Name][]SlotID) } else { for n := range state.varParts { delete(state.varParts, n) From 48d6275952184f1e858c2796d36c6b205d5d7e83 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sun, 6 Dec 2020 21:20:15 -0500 Subject: [PATCH 190/212] doc/go1.16: improve channel race detector changes description Based on text from Daniel Fava. For #40700. Change-Id: I0bc3a4340b8a777ff96d3cf226a7d51d3f65db2c Reviewed-on: https://go-review.googlesource.com/c/go/+/275786 Trust: Austin Clements Reviewed-by: Daniel Fava Reviewed-by: Dmitry Vyukov --- doc/go1.16.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index da8f560f85..012be1656f 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -331,9 +331,11 @@ Do not send CLs removing the interior tags from such phrases.

- The race detector's model for channel operations now more precisely - follows the Go memory model. As a result, it - may report now races that it previously missed. + Go 1.16 fixes a discrepancy between the race detector and + the Go memory model. The race detector now + more precisely follows the channel synchronization rules of the + memory model. As a result, the detector may now report races it + previously missed.

Compiler

From 01b76d5fbc4d4acdd28b08a061b072b73b22f44e Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 8 Dec 2020 09:44:48 -0500 Subject: [PATCH 191/212] go/types: correct error position for inherited const init expressions This is a port of CL 275517 from the dev.typeparams branch, to fix the positioning of error messages for invalid const init expressions that are inherited. Differences from CL 275517: + The inherited flag is added to the constDecl intermediate representation. + The errpos override is made a positioner, the internal interface used by go/types to capture error position and span. For const decls errpos is just set to a singular point, but using positioner is correct and causes span start and end positions to also be overridden. + Test cases are updated to assert on just 'overflows', as the go/types error message is, for example, "cannot use 255 + iota (untyped int constant 256) as byte value in constant declaration (overflows)". This is more verbose than the compiler's "constant 256 overflows byte", but changing that is out of scope. Fixes #42991 Change-Id: I0a71d2290f7fff5513f2a6e49b83e6f0f4da30e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/276172 Run-TryBot: Robert Findley TryBot-Result: Go Bot Trust: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/check.go | 1 + src/go/types/decl.go | 35 +++++++++++++++++++++-------- src/go/types/errors.go | 20 +++++++++++++---- src/go/types/resolver.go | 15 +++++++------ src/go/types/testdata/constdecl.src | 31 +++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 20 deletions(-) diff --git a/src/go/types/check.go b/src/go/types/check.go index 5e7bd92076..280792e838 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -46,6 +46,7 @@ type context struct { scope *Scope // top-most scope for lookups pos token.Pos // if valid, identifiers are looked up as if at position pos (used by Eval) iota constant.Value // value of iota in a constant declaration; nil otherwise + errpos positioner // if set, identifier position of a constant with inherited initializer sig *Signature // function signature if inside a function; nil otherwise isPanic map[*ast.CallExpr]bool // set of panic call expressions (used for termination check) hasLabel bool // set if a function makes use of labels (only ~1% of functions); unused outside functions diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 17b66ca387..1f0bc358a2 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -183,7 +183,7 @@ func (check *Checker) objDecl(obj Object, def *Named) { switch obj := obj.(type) { case *Const: check.decl = d // new package-level const decl - check.constDecl(obj, d.typ, d.init) + check.constDecl(obj, d.typ, d.init, d.inherited) case *Var: check.decl = d // new package-level var decl check.varDecl(obj, d.lhs, d.typ, d.init) @@ -388,10 +388,11 @@ type ( importDecl struct{ spec *ast.ImportSpec } constDecl struct { - spec *ast.ValueSpec - iota int - typ ast.Expr - init []ast.Expr + spec *ast.ValueSpec + iota int + typ ast.Expr + init []ast.Expr + inherited bool } varDecl struct{ spec *ast.ValueSpec } typeDecl struct{ spec *ast.TypeSpec } @@ -424,14 +425,17 @@ func (check *Checker) walkDecl(d ast.Decl, f func(decl)) { switch d.Tok { case token.CONST: // determine which initialization expressions to use + inherited := true switch { case s.Type != nil || len(s.Values) > 0: last = s + inherited = false case last == nil: last = new(ast.ValueSpec) // make sure last exists + inherited = false } check.arityMatch(s, last) - f(constDecl{spec: s, iota: iota, init: last.Values, typ: last.Type}) + f(constDecl{spec: s, iota: iota, typ: last.Type, init: last.Values, inherited: inherited}) case token.VAR: check.arityMatch(s, nil) f(varDecl{s}) @@ -451,12 +455,16 @@ func (check *Checker) walkDecl(d ast.Decl, f func(decl)) { } } -func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) { +func (check *Checker) constDecl(obj *Const, typ, init ast.Expr, inherited bool) { assert(obj.typ == nil) // use the correct value of iota - defer func(iota constant.Value) { check.iota = iota }(check.iota) + defer func(iota constant.Value, errpos positioner) { + check.iota = iota + check.errpos = errpos + }(check.iota, check.errpos) check.iota = obj.val + check.errpos = nil // provide valid constant value under all circumstances obj.val = constant.MakeUnknown() @@ -479,6 +487,15 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) { // check initialization var x operand if init != nil { + if inherited { + // The initialization expression is inherited from a previous + // constant declaration, and (error) positions refer to that + // expression and not the current constant declaration. Use + // the constant identifier position for any errors during + // init expression evaluation since that is all we have + // (see issues #42991, #42992). + check.errpos = atPos(obj.pos) + } check.expr(&x, init) } check.initConst(obj, &x) @@ -753,7 +770,7 @@ func (check *Checker) declStmt(d ast.Decl) { init = d.init[i] } - check.constDecl(obj, d.typ, init) + check.constDecl(obj, d.typ, init, d.inherited) } // process function literals in init expressions before scope changes diff --git a/src/go/types/errors.go b/src/go/types/errors.go index c9c475e469..a2195011f0 100644 --- a/src/go/types/errors.go +++ b/src/go/types/errors.go @@ -89,6 +89,18 @@ func (check *Checker) err(err error) { return } + if check.errpos != nil && isInternal { + // If we have an internal error and the errpos override is set, use it to + // augment our error positioning. + // TODO(rFindley) we may also want to augment the error message and refer + // to the position (pos) in the original expression. + span := spanOf(check.errpos) + e.Pos = span.pos + e.go116start = span.start + e.go116end = span.end + err = e + } + if check.firstErr == nil { check.firstErr = err } @@ -111,15 +123,15 @@ func (check *Checker) err(err error) { } func (check *Checker) newError(at positioner, code errorCode, soft bool, msg string) error { - ext := spanOf(at) + span := spanOf(at) return Error{ Fset: check.fset, - Pos: ext.pos, + Pos: span.pos, Msg: msg, Soft: soft, go116code: code, - go116start: ext.start, - go116end: ext.end, + go116start: span.start, + go116end: span.end, } } diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 4092d55b4e..b637f8b8ca 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -17,12 +17,13 @@ import ( // A declInfo describes a package-level const, type, var, or func declaration. type declInfo struct { - file *Scope // scope of file containing this declaration - lhs []*Var // lhs of n:1 variable declarations, or nil - typ ast.Expr // type, or nil - init ast.Expr // init/orig expression, or nil - fdecl *ast.FuncDecl // func declaration, or nil - alias bool // type alias declaration + file *Scope // scope of file containing this declaration + lhs []*Var // lhs of n:1 variable declarations, or nil + typ ast.Expr // type, or nil + init ast.Expr // init/orig expression, or nil + inherited bool // if set, the init expression is inherited from a previous constant declaration + fdecl *ast.FuncDecl // func declaration, or nil + alias bool // type alias declaration // The deps field tracks initialization expression dependencies. deps map[Object]bool // lazily initialized @@ -323,7 +324,7 @@ func (check *Checker) collectObjects() { init = d.init[i] } - d := &declInfo{file: fileScope, typ: d.typ, init: init} + d := &declInfo{file: fileScope, typ: d.typ, init: init, inherited: d.inherited} check.declarePkgObj(name, obj, d) } diff --git a/src/go/types/testdata/constdecl.src b/src/go/types/testdata/constdecl.src index c2f40ed6e6..680c85aff3 100644 --- a/src/go/types/testdata/constdecl.src +++ b/src/go/types/testdata/constdecl.src @@ -107,4 +107,35 @@ func _() { const x, y, z = 0, 1, unsafe.Sizeof(func() { _ = x /* ERROR "undeclared name" */ + y /* ERROR "undeclared name" */ + z /* ERROR "undeclared name" */ }) } +// Test cases for errors in inherited constant initialization expressions. +// Errors related to inherited initialization expressions must appear at +// the constant identifier being declared, not at the original expression +// (issues #42991, #42992). +const ( + _ byte = 255 + iota + /* some gap */ + _ // ERROR overflows + /* some gap */ + /* some gap */ _ /* ERROR overflows */; _ /* ERROR overflows */ + /* some gap */ + _ = 255 + iota + _ = byte /* ERROR overflows */ (255) + iota + _ /* ERROR overflows */ +) + +// Test cases from issue. +const ( + ok = byte(iota + 253) + bad + barn + bard // ERROR cannot convert +) + +const ( + c = len([1 - iota]int{}) + d + e // ERROR invalid array length + f // ERROR invalid array length +) + // TODO(gri) move extra tests from testdata/const0.src into here From 31496cfde50a490639ce0723f75de0f16a8291dd Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 8 Dec 2020 14:07:19 -0800 Subject: [PATCH 192/212] cmd/vet: vendor in x/tools, enable framepointer vet check Vendor in latest x/tools. Add framepointer vet check to vet. Fixes #43014 Change-Id: Ife72f85b1261aa60c0028041c58040d60a40918a Reviewed-on: https://go-review.googlesource.com/c/go/+/276372 Trust: Keith Randall Run-TryBot: Keith Randall Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../passes/framepointer/framepointer.go | 91 +++++++++++++++++++ .../passes/ifaceassert/ifaceassert.go | 4 + src/cmd/vendor/modules.txt | 3 +- src/cmd/vet/main.go | 2 + 6 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 98ef23d61b..c7d43873ef 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -8,5 +8,5 @@ require ( golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/mod v0.4.0 golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect - golang.org/x/tools v0.0.0-20201110201400-7099162a900a + golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 70f14f6640..30edf77282 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -31,8 +31,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20201110201400-7099162a900a h1:5E6TPwSBG74zT8xSrVc8W59K4ch4NFobVTnh2BYzHyU= -golang.org/x/tools v0.0.0-20201110201400-7099162a900a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49 h1:K1QAOVIWIvmQ66F1Z3AEa9Wzp0bj+xU3YzLkvROk2Ds= +golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go new file mode 100644 index 0000000000..741492e477 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go @@ -0,0 +1,91 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package framepointer defines an Analyzer that reports assembly code +// that clobbers the frame pointer before saving it. +package framepointer + +import ( + "go/build" + "regexp" + "strings" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/internal/analysisutil" +) + +const Doc = "report assembly that clobbers the frame pointer before saving it" + +var Analyzer = &analysis.Analyzer{ + Name: "framepointer", + Doc: Doc, + Run: run, +} + +var ( + re = regexp.MustCompile + asmWriteBP = re(`,\s*BP$`) // TODO: can have false positive, e.g. for TESTQ BP,BP. Seems unlikely. + asmMentionBP = re(`\bBP\b`) + asmControlFlow = re(`^(J|RET)`) +) + +func run(pass *analysis.Pass) (interface{}, error) { + if build.Default.GOARCH != "amd64" { // TODO: arm64 also? + return nil, nil + } + if build.Default.GOOS != "linux" && build.Default.GOOS != "darwin" { + return nil, nil + } + + // Find assembly files to work on. + var sfiles []string + for _, fname := range pass.OtherFiles { + if strings.HasSuffix(fname, ".s") && pass.Pkg.Path() != "runtime" { + sfiles = append(sfiles, fname) + } + } + + for _, fname := range sfiles { + content, tf, err := analysisutil.ReadFile(pass.Fset, fname) + if err != nil { + return nil, err + } + + lines := strings.SplitAfter(string(content), "\n") + active := false + for lineno, line := range lines { + lineno++ + + // Ignore comments and commented-out code. + if i := strings.Index(line, "//"); i >= 0 { + line = line[:i] + } + line = strings.TrimSpace(line) + + // We start checking code at a TEXT line for a frameless function. + if strings.HasPrefix(line, "TEXT") && strings.Contains(line, "(SB)") && strings.Contains(line, "$0") { + active = true + continue + } + if !active { + continue + } + + if asmWriteBP.MatchString(line) { // clobber of BP, function is not OK + pass.Reportf(analysisutil.LineStart(tf, lineno), "frame pointer is clobbered before saving") + active = false + continue + } + if asmMentionBP.MatchString(line) { // any other use of BP might be a read, so function is OK + active = false + continue + } + if asmControlFlow.MatchString(line) { // give up after any branch instruction + active = false + continue + } + } + } + return nil, nil +} diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go index c5a71a7c57..fd2285332c 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go @@ -41,6 +41,10 @@ var Analyzer = &analysis.Analyzer{ // assertableTo checks whether interface v can be asserted into t. It returns // nil on success, or the first conflicting method on failure. func assertableTo(v, t types.Type) *types.Func { + if t == nil || v == nil { + // not assertable to, but there is no missing method + return nil + } // ensure that v and t are interfaces V, _ := v.Underlying().(*types.Interface) T, _ := t.Underlying().(*types.Interface) diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index cda5fd0556..b549258cfa 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -44,7 +44,7 @@ golang.org/x/mod/zip golang.org/x/sys/internal/unsafeheader golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/tools v0.0.0-20201110201400-7099162a900a +# golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49 ## explicit golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis/internal/analysisflags @@ -59,6 +59,7 @@ golang.org/x/tools/go/analysis/passes/composite golang.org/x/tools/go/analysis/passes/copylock golang.org/x/tools/go/analysis/passes/ctrlflow golang.org/x/tools/go/analysis/passes/errorsas +golang.org/x/tools/go/analysis/passes/framepointer golang.org/x/tools/go/analysis/passes/httpresponse golang.org/x/tools/go/analysis/passes/ifaceassert golang.org/x/tools/go/analysis/passes/inspect diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go index bad3807039..d50c45d691 100644 --- a/src/cmd/vet/main.go +++ b/src/cmd/vet/main.go @@ -14,6 +14,7 @@ import ( "golang.org/x/tools/go/analysis/passes/composite" "golang.org/x/tools/go/analysis/passes/copylock" "golang.org/x/tools/go/analysis/passes/errorsas" + "golang.org/x/tools/go/analysis/passes/framepointer" "golang.org/x/tools/go/analysis/passes/httpresponse" "golang.org/x/tools/go/analysis/passes/ifaceassert" "golang.org/x/tools/go/analysis/passes/loopclosure" @@ -45,6 +46,7 @@ func main() { composite.Analyzer, copylock.Analyzer, errorsas.Analyzer, + framepointer.Analyzer, httpresponse.Analyzer, ifaceassert.Analyzer, loopclosure.Analyzer, From ae9b442df2436b3d65ef765572681bf9aacdfbbb Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 8 Dec 2020 14:35:41 -0800 Subject: [PATCH 193/212] doc: add description of new framepointer vet check Update #43014 Change-Id: I5fbfaa16e6acb8859fd0b1188f532f5a225f6349 Reviewed-on: https://go-review.googlesource.com/c/go/+/276373 Trust: Keith Randall Reviewed-by: Dmitri Shuralyov --- doc/go1.16.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/go1.16.html b/doc/go1.16.html index 012be1656f..504165f3ea 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -293,6 +293,18 @@ Do not send CLs removing the interior tags from such phrases.

+

+ The vet tool now warns about amd64 assembly that clobbers the BP + register (the frame pointer) without saving and restoring it, + contrary to the calling convention. Code that doesn't preserve the + BP register must be modified to either not use BP at all or preserve + BP by saving and restoring it. An easy way to preserve BP is to set + the frame size to a nonzero value, which causes the generated + prologue and epilogue to preserve the BP register for you. + See CL 248260 for example + fixes. +

+

Runtime

From 6fa06d960b5ec38867a35dc278ae318ecff1b6c6 Mon Sep 17 00:00:00 2001 From: Haoran Luo Date: Tue, 8 Dec 2020 14:29:04 +0000 Subject: [PATCH 194/212] runtime: prevent stack growth after fork in runtime.sigfillset This fixes the unexpected growth of stack in child process, which is caused by stack checking code in runtime.sigfillset called from runtime.sigset while clearing the signal handlers in child process. The redundant stack checking code is generated due to missing '//go:nosplit' directive that should be annotated for runtime.sigfillset. Fixes #43066 Updates #21314 Change-Id: I9483a962a4b0747074313991841e2440ee32198c Reviewed-on: https://go-review.googlesource.com/c/go/+/276173 Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Michael Pratt Reviewed-by: Austin Clements --- src/runtime/os_linux_be64.go | 1 + src/runtime/os_linux_generic.go | 1 + src/runtime/os_linux_mips64x.go | 1 + src/runtime/os_linux_mipsx.go | 1 + 4 files changed, 4 insertions(+) diff --git a/src/runtime/os_linux_be64.go b/src/runtime/os_linux_be64.go index 14fbad5d5f..9860002ee4 100644 --- a/src/runtime/os_linux_be64.go +++ b/src/runtime/os_linux_be64.go @@ -38,6 +38,7 @@ func sigdelset(mask *sigset, i int) { *mask &^= 1 << (uint(i) - 1) } +//go:nosplit func sigfillset(mask *uint64) { *mask = ^uint64(0) } diff --git a/src/runtime/os_linux_generic.go b/src/runtime/os_linux_generic.go index 14810e3cc3..e1d0952ddf 100644 --- a/src/runtime/os_linux_generic.go +++ b/src/runtime/os_linux_generic.go @@ -38,6 +38,7 @@ func sigdelset(mask *sigset, i int) { (*mask)[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) } +//go:nosplit func sigfillset(mask *uint64) { *mask = ^uint64(0) } diff --git a/src/runtime/os_linux_mips64x.go b/src/runtime/os_linux_mips64x.go index 4ff66f9538..815a83a04b 100644 --- a/src/runtime/os_linux_mips64x.go +++ b/src/runtime/os_linux_mips64x.go @@ -48,6 +48,7 @@ func sigdelset(mask *sigset, i int) { (*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63) } +//go:nosplit func sigfillset(mask *[2]uint64) { (*mask)[0], (*mask)[1] = ^uint64(0), ^uint64(0) } diff --git a/src/runtime/os_linux_mipsx.go b/src/runtime/os_linux_mipsx.go index 87962ed982..00fb02e4bf 100644 --- a/src/runtime/os_linux_mipsx.go +++ b/src/runtime/os_linux_mipsx.go @@ -42,6 +42,7 @@ func sigdelset(mask *sigset, i int) { (*mask)[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31) } +//go:nosplit func sigfillset(mask *[4]uint32) { (*mask)[0], (*mask)[1], (*mask)[2], (*mask)[3] = ^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0) } From 854a2f8e01a554d8052445563863775406a04b71 Mon Sep 17 00:00:00 2001 From: Michael Fraenkel Date: Wed, 2 Dec 2020 17:07:27 -0700 Subject: [PATCH 195/212] net/http: add connections back that haven't been canceled Issue #41600 fixed the issue when a second request canceled a connection while the first request was still in roundTrip. This uncovered a second issue where a request was being canceled (in roundtrip) but the connection was put back into the idle pool for a subsequent request. The fix is the similar except its now in readLoop instead of roundTrip. A persistent connection is only added back if it successfully removed the cancel function; otherwise we know the roundTrip has started cancelRequest. Fixes #42942 Change-Id: Ia56add20880ccd0c1ab812d380d8628e45f6f44c Reviewed-on: https://go-review.googlesource.com/c/go/+/274973 Trust: Dmitri Shuralyov Trust: Damien Neil Reviewed-by: Damien Neil --- src/net/http/transport.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 8de0f3a6a0..a5830703af 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -784,7 +784,8 @@ func (t *Transport) CancelRequest(req *Request) { } // Cancel an in-flight request, recording the error value. -func (t *Transport) cancelRequest(key cancelKey, err error) { +// Returns whether the request was canceled. +func (t *Transport) cancelRequest(key cancelKey, err error) bool { t.reqMu.Lock() cancel := t.reqCanceler[key] delete(t.reqCanceler, key) @@ -792,6 +793,8 @@ func (t *Transport) cancelRequest(key cancelKey, err error) { if cancel != nil { cancel(err) } + + return cancel != nil } // @@ -2127,18 +2130,17 @@ func (pc *persistConn) readLoop() { } if !hasBody || bodyWritable { - pc.t.setReqCanceler(rc.cancelKey, nil) + replaced := pc.t.replaceReqCanceler(rc.cancelKey, nil) // Put the idle conn back into the pool before we send the response // so if they process it quickly and make another request, they'll // get this same conn. But we use the unbuffered channel 'rc' // to guarantee that persistConn.roundTrip got out of its select // potentially waiting for this persistConn to close. - // but after alive = alive && !pc.sawEOF && pc.wroteRequest() && - tryPutIdleConn(trace) + replaced && tryPutIdleConn(trace) if bodyWritable { closeErr = errCallerOwnsConn @@ -2200,12 +2202,12 @@ func (pc *persistConn) readLoop() { // reading the response body. (or for cancellation or death) select { case bodyEOF := <-waitForBodyRead: - pc.t.setReqCanceler(rc.cancelKey, nil) // before pc might return to idle pool + replaced := pc.t.replaceReqCanceler(rc.cancelKey, nil) // before pc might return to idle pool alive = alive && bodyEOF && !pc.sawEOF && pc.wroteRequest() && - tryPutIdleConn(trace) + replaced && tryPutIdleConn(trace) if bodyEOF { eofc <- struct{}{} } @@ -2600,6 +2602,7 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err cancelChan := req.Request.Cancel ctxDoneChan := req.Context().Done() pcClosed := pc.closech + canceled := false for { testHookWaitResLoop() select { @@ -2621,8 +2624,7 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err } case <-pcClosed: pcClosed = nil - // check if we are still using the connection - if pc.t.replaceReqCanceler(req.cancelKey, nil) { + if canceled || pc.t.replaceReqCanceler(req.cancelKey, nil) { if debugRoundTrip { req.logf("closech recv: %T %#v", pc.closed, pc.closed) } @@ -2646,10 +2648,10 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err } return re.res, nil case <-cancelChan: - pc.t.cancelRequest(req.cancelKey, errRequestCanceled) + canceled = pc.t.cancelRequest(req.cancelKey, errRequestCanceled) cancelChan = nil case <-ctxDoneChan: - pc.t.cancelRequest(req.cancelKey, req.Context().Err()) + canceled = pc.t.cancelRequest(req.cancelKey, req.Context().Err()) cancelChan = nil ctxDoneChan = nil } From db6032dd0cbce3e4feff0160287cbe3d9234a540 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Wed, 9 Dec 2020 14:17:56 +0000 Subject: [PATCH 196/212] cmd/compile: fix message typo occurences -> occurrences Change-Id: Ia81671f5de8a24ddd303a77b4580e8c726f29122 GitHub-Last-Rev: 11f9ab9f8c2c9acd70bcf170930426547d9b63eb GitHub-Pull-Request: golang/go#43097 Reviewed-on: https://go-review.googlesource.com/c/go/+/276612 Reviewed-by: Robert Griesemer Reviewed-by: Keith Randall --- src/cmd/compile/internal/logopt/logopt_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go index 51bab49518..e121c1abd2 100644 --- a/src/cmd/compile/internal/logopt/logopt_test.go +++ b/src/cmd/compile/internal/logopt/logopt_test.go @@ -51,7 +51,7 @@ func want(t *testing.T, out string, desired string) { func wantN(t *testing.T, out string, desired string, n int) { if strings.Count(out, desired) != n { - t.Errorf("expected exactly %d occurences of %s in \n%s", n, desired, out) + t.Errorf("expected exactly %d occurrences of %s in \n%s", n, desired, out) } } From 5627a4dc3013fed02c4b8097413643b682cac276 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Tue, 8 Dec 2020 19:44:33 -0500 Subject: [PATCH 197/212] runtime/metrics: simplify test to support more environments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit go test sets the working directory to that of the package being tested, so opening one of the package source files can be done in a simpler way. This also allows the test to run in more environments, for example when GOROOT_FINAL¹ is set. Also remove the testenv.HasSrc-like check for Go source. The doc.go file is a part of the package being built and tested, so it's expected to be available. If it's important for this test to handle when a test binary is built with go test -c and executed elsewhere without package source files, something more than testenv.HasSrc would be needed. ¹ https://golang.org/cmd/go/#hdr-Environment_variables Fixes #43085. Change-Id: Ie6ade395a8fc7beebdadbad6f4873800138dfc26 Reviewed-on: https://go-review.googlesource.com/c/go/+/276452 Reviewed-by: Bryan C. Mills Reviewed-by: Michael Knyszek Trust: Dmitri Shuralyov --- src/runtime/metrics/description_test.go | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/runtime/metrics/description_test.go b/src/runtime/metrics/description_test.go index e966a281a1..448639ee77 100644 --- a/src/runtime/metrics/description_test.go +++ b/src/runtime/metrics/description_test.go @@ -7,9 +7,7 @@ package metrics_test import ( "bufio" "os" - "path/filepath" "regexp" - "runtime" "runtime/metrics" "strings" "testing" @@ -26,17 +24,9 @@ func TestDescriptionNameFormat(t *testing.T) { } func extractMetricDocs(t *testing.T) map[string]string { - if runtime.GOOS == "android" { - t.Skip("no access to Go source on android") - } - - // Get doc.go. - _, filename, _, _ := runtime.Caller(0) - filename = filepath.Join(filepath.Dir(filename), "doc.go") - - f, err := os.Open(filename) + f, err := os.Open("doc.go") if err != nil { - t.Fatal(err) + t.Fatalf("failed to open doc.go in runtime/metrics package: %v", err) } const ( stateSearch = iota // look for list of metrics @@ -90,7 +80,7 @@ func extractMetricDocs(t *testing.T) map[string]string { } } if state == stateSearch { - t.Fatalf("failed to find supported metrics docs in %s", filename) + t.Fatalf("failed to find supported metrics docs in %s", f.Name()) } return result } From e2d278bfeb2f0f117efc50b3f0f9dcb086a45ed2 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 7 Dec 2020 15:26:24 -0500 Subject: [PATCH 198/212] [dev.regabi] cmd/compile: two small fixes Addressing comments from CL 275434 and CL 275444. I forgot to run "git rw" to rebase the fixup CLs down before running "git submit". Change-Id: Ideaa2340a81511491c096555c6834cd9bdb267d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/275881 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/mknode.go | 2 +- src/cmd/compile/internal/ir/stmt.go | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/ir/mknode.go b/src/cmd/compile/internal/ir/mknode.go index 978b2de5a5..72034022cb 100644 --- a/src/cmd/compile/internal/ir/mknode.go +++ b/src/cmd/compile/internal/ir/mknode.go @@ -144,7 +144,7 @@ func forNodeFields(typName string, typ *types.Struct, f func(name string, is fun if strings.ToLower(strings.TrimSuffix(v.Name(), "_")) != "body" { continue } - case "Name", "Pack": + case "Name": continue } switch v.Name() { diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index ccf46dfa73..68f9b0bd7c 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -33,7 +33,12 @@ func (n *Decl) Left() Node { return n.X } func (n *Decl) SetLeft(x Node) { n.X = x } // A Stmt is a Node that can appear as a statement. -// This includes statement-like expressions such as <-c and f(). +// This includes statement-like expressions such as f(). +// +// (It's possible it should include <-c, but that would require +// splitting ORECV out of UnaryExpr, which hasn't yet been +// necessary. Maybe instead we will introduce ExprStmt at +// some point.) type Stmt interface { Node isStmt() From 4090af83c57c857de600ada68e7a27dffd37d8b1 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 6 Dec 2020 15:17:05 -0500 Subject: [PATCH 199/212] [dev.regabi] cmd/compile: use reflection in ir.Dump ir.Dump is the final (I think!) piece of the compiler that was walking nodes using Left, Right etc without knowing what they meant. This CL uses reflection to walk nodes without knowing what they mean instead. One benefit is that we can print actual meanings (field names). While we are here, I could not resist fixing a long-standing mental TODO: make the line number more clearly a line number. I've forgotten where the line number is in the dumps far too many times in the last decade. As a small example, here is a fragment of go tool compile -W test/235.go: . FOR l(28) tc(1) . . LT-init . . . AS l(28) tc(1) . . . . NAME-main..autotmp_4 l(28) x(0) class(PAUTO) esc(N) tc(1) assigned used int . . . . LEN l(28) tc(1) int . . . . . NAME-main.xs g(2) l(26) x(0) class(PPARAM) esc(no) tc(1) used SLICE-[]uint64 . . LT l(28) tc(1) hascall bool . . . NAME-main.i g(4) l(28) x(0) class(PAUTO) esc(no) tc(1) assigned used int . . . NAME-main..autotmp_4 l(28) x(0) class(PAUTO) esc(N) tc(1) assigned used int . . BLOCK l(28) . . BLOCK-list . . . ASOP-ADD l(28) tc(1) implicit(true) int . . . . NAME-main.i g(4) l(28) x(0) class(PAUTO) esc(no) tc(1) assigned used int . . . . LITERAL-1 l(28) tc(1) int . FOR-body . . VARKILL l(28) tc(1) . . . NAME-main..autotmp_4 l(28) x(0) class(PAUTO) esc(N) tc(1) assigned used int . . IF l(29) tc(1) . . . LT l(29) tc(1) bool . . . . INDEX l(29) tc(1) uint64 . . . . . NAME-main.xs g(2) l(26) x(0) class(PPARAM) esc(no) tc(1) used SLICE-[]uint64 . . . . . NAME-main.i g(4) l(28) x(0) class(PAUTO) esc(no) tc(1) assigned used int . . . . NAME-main.m g(3) l(27) x(0) class(PAUTO) esc(no) tc(1) assigned used uint64 . . IF-body . . . AS l(30) tc(1) . . . . NAME-main.m g(3) l(27) x(0) class(PAUTO) esc(no) tc(1) assigned used uint64 . . . . INDEX l(30) tc(1) uint64 . . . . . NAME-main.xs g(2) l(26) x(0) class(PPARAM) esc(no) tc(1) used SLICE-[]uint64 . . . . . NAME-main.i g(4) l(28) x(0) class(PAUTO) esc(no) tc(1) assigned used int and here it is after this CL: . FOR tc(1) # 235.go:28 . FOR-Cond . . LT-init . . . AS tc(1) # 235.go:28 . . . . NAME-main..autotmp_4 x(0) class(PAUTO) esc(N) tc(1) assigned used int # 235.go:28 . . . . LEN tc(1) int # 235.go:28 int . . . . . NAME-main.xs g(2) x(0) class(PPARAM) esc(no) tc(1) used SLICE-[]uint64 # 235.go:26 . . LT tc(1) hascall bool # 235.go:28 bool . . . NAME-main.i g(4) x(0) class(PAUTO) esc(no) tc(1) assigned used int # 235.go:28 . . . NAME-main..autotmp_4 x(0) class(PAUTO) esc(N) tc(1) assigned used int # 235.go:28 . FOR-Post . . BLOCK # 235.go:28 . . BLOCK-List . . . ASOP-ADD tc(1) implicit(true) int # 235.go:28 int . . . . NAME-main.i g(4) x(0) class(PAUTO) esc(no) tc(1) assigned used int # 235.go:28 . . . . LITERAL-1 tc(1) int # 235.go:28 . FOR-Body . . VARKILL tc(1) # 235.go:28 . . . NAME-main..autotmp_4 x(0) class(PAUTO) esc(N) tc(1) assigned used int # 235.go:28 . . IF tc(1) # 235.go:29 . . IF-Cond . . . LT tc(1) bool # 235.go:29 bool . . . . INDEX tc(1) uint64 # 235.go:29 uint64 . . . . . NAME-main.xs g(2) x(0) class(PPARAM) esc(no) tc(1) used SLICE-[]uint64 # 235.go:26 . . . . . NAME-main.i g(4) x(0) class(PAUTO) esc(no) tc(1) assigned used int # 235.go:28 . . . . NAME-main.m g(3) x(0) class(PAUTO) esc(no) tc(1) assigned used uint64 # 235.go:27 . . IF-Body . . . AS tc(1) # 235.go:30 . . . . NAME-main.m g(3) x(0) class(PAUTO) esc(no) tc(1) assigned used uint64 # 235.go:27 . . . . INDEX tc(1) uint64 # 235.go:30 uint64 . . . . . NAME-main.xs g(2) x(0) class(PPARAM) esc(no) tc(1) used SLICE-[]uint64 # 235.go:26 . . . . . NAME-main.i g(4) x(0) class(PAUTO) esc(no) tc(1) assigned used int # 235.go:28 Note in particular the clear marking of FOR-Cond, FOR-Post, FOR-Body compared to the original. The only changes to a few test files are the improved field name lines, and of course the line numbers. Passes buildall w/ toolstash -cmp. Change-Id: I5b654d9d8ee898976d4c387742ea688a082bac78 Reviewed-on: https://go-review.googlesource.com/c/go/+/275785 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/fmt.go | 149 +++++++++++++++++++---------- 1 file changed, 97 insertions(+), 52 deletions(-) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 68e425bdaa..4bea6e2ae0 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -10,6 +10,9 @@ import ( "go/constant" "io" "os" + "path/filepath" + "reflect" + "strings" "unicode/utf8" @@ -957,17 +960,6 @@ func dumpNodeHeader(w io.Writer, n Node) { fmt.Fprintf(w, " defn(%p)", n.Name().Defn) } - if n.Pos().IsKnown() { - pfx := "" - switch n.Pos().IsStmt() { - case src.PosNotStmt: - pfx = "_" // "-" would be confusing - case src.PosIsStmt: - pfx = "+" - } - fmt.Fprintf(w, " l(%s%d)", pfx, n.Pos().Line()) - } - if n.Offset() != types.BADWIDTH { fmt.Fprintf(w, " x(%d)", n.Offset()) } @@ -1029,6 +1021,32 @@ func dumpNodeHeader(w io.Writer, n Node) { if n.Name() != nil && n.Name().Used() { fmt.Fprint(w, " used") } + + if n.Op() == OCLOSURE { + if fn := n.Func(); fn != nil && fn.Nname.Sym() != nil { + fmt.Fprintf(w, " fnName(%+v)", fn.Nname.Sym()) + } + } + + if n.Type() != nil { + if n.Op() == OTYPE { + fmt.Fprintf(w, " type") + } + fmt.Fprintf(w, " %+v", n.Type()) + } + + if n.Pos().IsKnown() { + pfx := "" + switch n.Pos().IsStmt() { + case src.PosNotStmt: + pfx = "_" // "-" would be confusing + case src.PosIsStmt: + pfx = "+" + } + pos := base.Ctxt.PosTable.Pos(n.Pos()) + file := filepath.Base(pos.Filename()) + fmt.Fprintf(w, " # %s%s:%d", pfx, file, pos.Line()) + } } func dumpNode(w io.Writer, n Node, depth int) { @@ -1052,6 +1070,7 @@ func dumpNode(w io.Writer, n Node, depth int) { case OLITERAL: fmt.Fprintf(w, "%+v-%v", n.Op(), n.Val()) dumpNodeHeader(w, n) + return case ONAME, ONONAME, OMETHEXPR: if n.Sym() != nil { @@ -1065,6 +1084,7 @@ func dumpNode(w io.Writer, n Node, depth int) { fmt.Fprintf(w, "%+v-ntype", n.Op()) dumpNode(w, n.Name().Ntype, depth+1) } + return case OASOP: fmt.Fprintf(w, "%+v-%+v", n.Op(), n.SubOp()) @@ -1073,61 +1093,86 @@ func dumpNode(w io.Writer, n Node, depth int) { case OTYPE: fmt.Fprintf(w, "%+v %+v", n.Op(), n.Sym()) dumpNodeHeader(w, n) - fmt.Fprintf(w, " type=%+v", n.Type()) if n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil { indent(w, depth) fmt.Fprintf(w, "%+v-ntype", n.Op()) dumpNode(w, n.Name().Ntype, depth+1) } + return + + case OCLOSURE: + fmt.Fprintf(w, "%+v", n.Op()) + dumpNodeHeader(w, n) + + case ODCLFUNC: + // Func has many fields we don't want to print. + // Bypass reflection and just print what we want. + fmt.Fprintf(w, "%+v", n.Op()) + dumpNodeHeader(w, n) + fn := n.Func() + if len(fn.Dcl) > 0 { + indent(w, depth) + fmt.Fprintf(w, "%+v-Dcl", n.Op()) + for _, dcl := range n.Func().Dcl { + dumpNode(w, dcl, depth+1) + } + } + if fn.Body().Len() > 0 { + indent(w, depth) + fmt.Fprintf(w, "%+v-body", n.Op()) + dumpNodes(w, n.Body(), depth+1) + } + return } - if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Nname.Sym() != nil { - fmt.Fprintf(w, " fnName %+v", n.Func().Nname.Sym()) - } - if n.Sym() != nil && n.Op() != ONAME { + if n.Sym() != nil { fmt.Fprintf(w, " %+v", n.Sym()) } - if n.Type() != nil { fmt.Fprintf(w, " %+v", n.Type()) } - if n.Left() != nil { - dumpNode(w, n.Left(), depth+1) - } - if n.Right() != nil { - dumpNode(w, n.Right(), depth+1) - } - if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Body().Len() != 0 { - indent(w, depth) - // The function associated with a closure - fmt.Fprintf(w, "%+v-clofunc", n.Op()) - dumpNode(w, n.Func(), depth+1) - } - if n.Op() == ODCLFUNC && n.Func() != nil && n.Func().Dcl != nil && len(n.Func().Dcl) != 0 { - indent(w, depth) - // The dcls for a func or closure - fmt.Fprintf(w, "%+v-dcl", n.Op()) - for _, dcl := range n.Func().Dcl { - dumpNode(w, dcl, depth+1) + v := reflect.ValueOf(n).Elem() + t := reflect.TypeOf(n).Elem() + nf := t.NumField() + for i := 0; i < nf; i++ { + tf := t.Field(i) + vf := v.Field(i) + if tf.PkgPath != "" { + // skip unexported field - Interface will fail + continue + } + switch tf.Type.Kind() { + case reflect.Interface, reflect.Ptr, reflect.Slice: + if vf.IsNil() { + continue + } + } + name := strings.TrimSuffix(tf.Name, "_") + // Do not bother with field name header lines for the + // most common positional arguments: unary, binary expr, + // index expr, send stmt, go and defer call expression. + switch name { + case "X", "Y", "Index", "Chan", "Value", "Call": + name = "" + } + switch val := vf.Interface().(type) { + case Node: + if name != "" { + indent(w, depth) + fmt.Fprintf(w, "%+v-%s", n.Op(), name) + } + dumpNode(w, val, depth+1) + case Nodes: + if val.Len() == 0 { + continue + } + if name != "" { + indent(w, depth) + fmt.Fprintf(w, "%+v-%s", n.Op(), name) + } + dumpNodes(w, val, depth+1) } - } - if n.List().Len() != 0 { - indent(w, depth) - fmt.Fprintf(w, "%+v-list", n.Op()) - dumpNodes(w, n.List(), depth+1) - } - - if n.Rlist().Len() != 0 { - indent(w, depth) - fmt.Fprintf(w, "%+v-rlist", n.Op()) - dumpNodes(w, n.Rlist(), depth+1) - } - - if n.Body().Len() != 0 { - indent(w, depth) - fmt.Fprintf(w, "%+v-body", n.Op()) - dumpNodes(w, n.Body(), depth+1) } } From 0c4944066411c5570ad9e7b66ae414f409d5d826 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 7 Dec 2020 00:04:54 -0500 Subject: [PATCH 200/212] [dev.regabi] cmd/compile: arrange for walkstmt, walkexpr, to return from switch cases Ending them in a returning switch makes it safe for each case to do an appropriate type assertion. Passes buildall w/ toolstash -cmp. Change-Id: I55d8f0a555006104164d84d27822aa8c5ad68515 Reviewed-on: https://go-review.googlesource.com/c/go/+/275882 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/walk.go | 400 +++++++++++++++------------- 1 file changed, 209 insertions(+), 191 deletions(-) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 4189d1a721..f35e9d768b 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -123,6 +123,7 @@ func walkstmt(n ir.Node) ir.Node { base.Errorf("%v is not a top level statement", n.Op()) } ir.Dump("nottop", n) + return n case ir.OAS, ir.OASOP, @@ -166,6 +167,7 @@ func walkstmt(n ir.Node) ir.Node { n = ir.NewBlockStmt(n.Pos(), init.Slice()) } } + return n // special case for a receive where we throw away // the value received. @@ -179,8 +181,7 @@ func walkstmt(n ir.Node) ir.Node { n.SetLeft(walkexpr(n.Left(), &init)) n = mkcall1(chanfn("chanrecv1", 2, n.Left().Type()), nil, &init, n.Left(), nodnil()) n = walkexpr(n, &init) - - n = initExpr(init.Slice(), n) + return initExpr(init.Slice(), n) case ir.OBREAK, ir.OCONTINUE, @@ -193,7 +194,7 @@ func walkstmt(n ir.Node) ir.Node { ir.OVARDEF, ir.OVARKILL, ir.OVARLIVE: - break + return n case ir.ODCL: v := n.Left() @@ -209,12 +210,15 @@ func walkstmt(n ir.Node) ir.Node { nn = typecheck(nn, ctxStmt) return walkstmt(nn) } + return n case ir.OBLOCK: walkstmtlist(n.List().Slice()) + return n case ir.OCASE: base.Errorf("case statement out of place") + panic("unreachable") case ir.ODEFER: Curfn.SetHasDefer(true) @@ -261,6 +265,7 @@ func walkstmt(n ir.Node) ir.Node { init.Append(n) n = ir.NewBlockStmt(n.Pos(), init.Slice()) } + return n case ir.OFOR, ir.OFORUNTIL: if n.Left() != nil { @@ -276,16 +281,18 @@ func walkstmt(n ir.Node) ir.Node { walkstmtlist(n.List().Slice()) } walkstmtlist(n.Body().Slice()) + return n case ir.OIF: n.SetLeft(walkexpr(n.Left(), n.PtrInit())) walkstmtlist(n.Body().Slice()) walkstmtlist(n.Rlist().Slice()) + return n case ir.ORETURN: Curfn.NumReturns++ if n.List().Len() == 0 { - break + return n } if (hasNamedResults(Curfn) && n.List().Len() > 1) || paramoutheap(Curfn) { // assign to the function out parameters, @@ -317,7 +324,7 @@ func walkstmt(n ir.Node) ir.Node { ll := ascompatee(n.Op(), rl, n.List().Slice(), n.PtrInit()) n.PtrList().Set(reorder3(ll)) - break + return n } walkexprlist(n.List().Slice(), n.PtrInit()) @@ -334,27 +341,29 @@ func walkstmt(n ir.Node) ir.Node { res[i] = convas(a, n.PtrInit()) } n.PtrList().Set(res) + return n case ir.ORETJMP: - break + return n case ir.OINLMARK: - break + return n case ir.OSELECT: walkselect(n) + return n case ir.OSWITCH: walkswitch(n) + return n case ir.ORANGE: - n = walkrange(n) + return walkrange(n) } - if n.Op() == ir.ONAME { - base.Fatalf("walkstmt ended up with name: %+v", n) - } - return n + // No return! Each case must return (or panic), + // to avoid confusion about what gets returned + // in the presence of type assertions. } // walk the whole tree of the body of an @@ -477,31 +486,68 @@ func walkexpr(n ir.Node, init *ir.Nodes) ir.Node { return nn } -opswitch: + n = walkexpr1(n, init) + + // Expressions that are constant at run time but not + // considered const by the language spec are not turned into + // constants until walk. For example, if n is y%1 == 0, the + // walk of y%1 may have replaced it by 0. + // Check whether n with its updated args is itself now a constant. + t := n.Type() + n = evalConst(n) + if n.Type() != t { + base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type()) + } + if n.Op() == ir.OLITERAL { + n = typecheck(n, ctxExpr) + // Emit string symbol now to avoid emitting + // any concurrently during the backend. + if v := n.Val(); v.Kind() == constant.String { + _ = stringsym(n.Pos(), constant.StringVal(v)) + } + } + + updateHasCall(n) + + if base.Flag.LowerW != 0 && n != nil { + ir.Dump("after walk expr", n) + } + + base.Pos = lno + return n +} + +func walkexpr1(n ir.Node, init *ir.Nodes) ir.Node { switch n.Op() { default: ir.Dump("walk", n) base.Fatalf("walkexpr: switch 1 unknown op %+v", n.Op()) + panic("unreachable") case ir.ONONAME, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR: + return n case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL: // TODO(mdempsky): Just return n; see discussion on CL 38655. // Perhaps refactor to use Node.mayBeShared for these instead. // If these return early, make sure to still call // stringsym for constant strings. + return n case ir.ONOT, ir.ONEG, ir.OPLUS, ir.OBITNOT, ir.OREAL, ir.OIMAG, ir.ODOTMETH, ir.ODOTINTER, ir.ODEREF, ir.OSPTR, ir.OITAB, ir.OIDATA, ir.OADDR: n.SetLeft(walkexpr(n.Left(), init)) + return n case ir.OEFACE, ir.OAND, ir.OANDNOT, ir.OSUB, ir.OMUL, ir.OADD, ir.OOR, ir.OXOR, ir.OLSH, ir.ORSH: n.SetLeft(walkexpr(n.Left(), init)) n.SetRight(walkexpr(n.Right(), init)) + return n case ir.ODOT, ir.ODOTPTR: usefield(n) n.SetLeft(walkexpr(n.Left(), init)) + return n case ir.ODOTTYPE, ir.ODOTTYPE2: n.SetLeft(walkexpr(n.Left(), init)) @@ -513,12 +559,12 @@ opswitch: if !n.Type().IsInterface() && !n.Left().Type().IsEmptyInterface() { n.PtrList().Set1(itabname(n.Type(), n.Left().Type())) } + return n case ir.OLEN, ir.OCAP: if isRuneCount(n) { // Replace len([]rune(string)) with runtime.countrunes(string). - n = mkcall("countrunes", n.Type(), init, conv(n.Left().Left(), types.Types[types.TSTRING])) - break + return mkcall("countrunes", n.Type(), init, conv(n.Left().Left(), types.Types[types.TSTRING])) } n.SetLeft(walkexpr(n.Left(), init)) @@ -535,6 +581,7 @@ opswitch: n = origIntConst(n, t.NumElem()) n.SetTypecheck(1) } + return n case ir.OCOMPLEX: // Use results from call expression as arguments for complex. @@ -544,9 +591,10 @@ opswitch: } n.SetLeft(walkexpr(n.Left(), init)) n.SetRight(walkexpr(n.Right(), init)) + return n case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: - n = walkcompare(n, init) + return walkcompare(n, init) case ir.OANDAND, ir.OOROR: n.SetLeft(walkexpr(n.Left(), init)) @@ -558,17 +606,19 @@ opswitch: n.SetRight(walkexpr(n.Right(), &ll)) n.SetRight(initExpr(ll.Slice(), n.Right())) + return n case ir.OPRINT, ir.OPRINTN: - n = walkprint(n, init) + return walkprint(n, init) case ir.OPANIC: - n = mkcall("gopanic", nil, init, n.Left()) + return mkcall("gopanic", nil, init, n.Left()) case ir.ORECOVER: - n = mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil)) + return mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil)) case ir.OCLOSUREREAD, ir.OCFUNC: + return n case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH: if n.Op() == ir.OCALLINTER { @@ -597,6 +647,7 @@ opswitch: } walkCall(n, init) + return n case ir.OAS, ir.OASOP: init.AppendNodes(n.PtrInit()) @@ -622,17 +673,16 @@ opswitch: } if oaslit(n, init) { - n = ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil) - break + return ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil) } if n.Right() == nil { // TODO(austin): Check all "implicit zeroing" - break + return n } if !instrumenting && isZero(n.Right()) { - break + return n } switch n.Right().Op() { @@ -646,9 +696,7 @@ opswitch: n1 := ir.Nod(ir.OADDR, n.Left(), nil) r := n.Right().Left() // the channel - n = mkcall1(chanfn("chanrecv1", 2, r.Type()), nil, init, r, n1) - n = walkexpr(n, init) - break opswitch + return mkcall1(chanfn("chanrecv1", 2, r.Type()), nil, init, r, n1) case ir.OAPPEND: // x = append(...) @@ -671,7 +719,7 @@ opswitch: // Do not add a new write barrier. // Set up address of type for back end. r.SetLeft(typename(r.Type().Elem())) - break opswitch + return n } // Otherwise, lowered for race detector. // Treat as ordinary assignment. @@ -680,6 +728,7 @@ opswitch: if n.Left() != nil && n.Right() != nil { n = convas(n, init) } + return n case ir.OAS2: init.AppendNodes(n.PtrInit()) @@ -687,7 +736,7 @@ opswitch: walkexprlistsafe(n.Rlist().Slice(), init) ll := ascompatee(ir.OAS, n.List().Slice(), n.Rlist().Slice(), init) ll = reorder3(ll) - n = liststmt(ll) + return liststmt(ll) // a,b,... = fn() case ir.OAS2FUNC: @@ -699,12 +748,12 @@ opswitch: if isIntrinsicCall(r) { n.PtrRlist().Set1(r) - break + return n } init.Append(r) ll := ascompatet(n.List(), r.Type()) - n = liststmt(ll) + return liststmt(ll) // x, y = <-c // order.stmt made sure x is addressable or blank. @@ -724,7 +773,7 @@ opswitch: ok := n.List().Second() call := mkcall1(fn, types.Types[types.TBOOL], init, r.Left(), n1) n = ir.Nod(ir.OAS, ok, call) - n = typecheck(n, ctxStmt) + return typecheck(n, ctxStmt) // a,b = m[i] case ir.OAS2MAPR: @@ -784,7 +833,7 @@ opswitch: } n = typecheck(n, ctxStmt) - n = walkexpr(n, init) + return walkexpr(n, init) case ir.ODELETE: init.AppendNodes(n.PtrInit()) @@ -799,11 +848,12 @@ opswitch: // order.stmt made sure key is addressable. key = ir.Nod(ir.OADDR, key, nil) } - n = mkcall1(mapfndel(mapdelete[fast], t), nil, init, typename(t), map_, key) + return mkcall1(mapfndel(mapdelete[fast], t), nil, init, typename(t), map_, key) case ir.OAS2DOTTYPE: walkexprlistsafe(n.List().Slice(), init) n.PtrRlist().SetIndex(0, walkexpr(n.Rlist().First(), init)) + return n case ir.OCONVIFACE: n.SetLeft(walkexpr(n.Left(), init)) @@ -828,8 +878,7 @@ opswitch: l := ir.Nod(ir.OEFACE, typeword(), n.Left()) l.SetType(toType) l.SetTypecheck(n.Typecheck()) - n = l - break + return l } if staticuint64s == nil { @@ -878,8 +927,7 @@ opswitch: l := ir.Nod(ir.OEFACE, typeword(), typecheck(ir.Nod(ir.OADDR, value, nil), ctxExpr)) l.SetType(toType) l.SetTypecheck(n.Typecheck()) - n = l - break + return l } // Implement interface to empty interface conversion. @@ -906,8 +954,7 @@ opswitch: e := ir.Nod(ir.OEFACE, tmp, ifaceData(n.Pos(), c, types.NewPtr(types.Types[types.TUINT8]))) e.SetType(toType) // assign type manually, typecheck doesn't understand OEFACE. e.SetTypecheck(1) - n = e - break + return e } fnname, needsaddr := convFuncName(fromType, toType) @@ -928,8 +975,7 @@ opswitch: e := ir.Nod(ir.OEFACE, typeword(), call) e.SetType(toType) e.SetTypecheck(1) - n = e - break + return e } var tab ir.Node @@ -962,7 +1008,7 @@ opswitch: n = ir.Nod(ir.OCALL, fn, nil) n.PtrList().Set2(tab, v) n = typecheck(n, ctxExpr) - n = walkexpr(n, init) + return walkexpr(n, init) case ir.OCONV, ir.OCONVNOP: n.SetLeft(walkexpr(n.Left(), init)) @@ -971,20 +1017,18 @@ opswitch: } if n.Op() == ir.OCONVNOP && checkPtr(Curfn, 1) { if n.Type().IsPtr() && n.Left().Type().IsUnsafePtr() { // unsafe.Pointer to *T - n = walkCheckPtrAlignment(n, init, nil) - break + return walkCheckPtrAlignment(n, init, nil) } if n.Type().IsUnsafePtr() && n.Left().Type().IsUintptr() { // uintptr to unsafe.Pointer - n = walkCheckPtrArithmetic(n, init) - break + return walkCheckPtrArithmetic(n, init) } } param, result := rtconvfn(n.Left().Type(), n.Type()) if param == types.Txxx { - break + return n } fn := types.BasicTypeNames[param] + "to" + types.BasicTypeNames[result] - n = conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type()) + return conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type()) case ir.ODIV, ir.OMOD: n.SetLeft(walkexpr(n.Left(), init)) @@ -996,13 +1040,12 @@ opswitch: if isComplex[et] && n.Op() == ir.ODIV { t := n.Type() n = mkcall("complex128div", types.Types[types.TCOMPLEX128], init, conv(n.Left(), types.Types[types.TCOMPLEX128]), conv(n.Right(), types.Types[types.TCOMPLEX128])) - n = conv(n, t) - break + return conv(n, t) } // Nothing to do for float divisions. if isFloat[et] { - break + return n } // rewrite 64-bit div and mod on 32-bit architectures. @@ -1019,15 +1062,15 @@ opswitch: c = -c } if c != 0 && c&(c-1) == 0 { - break opswitch + return n } case types.TUINT64: c := ir.Uint64Val(n.Right()) if c < 1<<16 { - break opswitch + return n } if c != 0 && c&(c-1) == 0 { - break opswitch + return n } } } @@ -1042,8 +1085,9 @@ opswitch: } else { fn += "mod" } - n = mkcall(fn, n.Type(), init, conv(n.Left(), types.Types[et]), conv(n.Right(), types.Types[et])) + return mkcall(fn, n.Type(), init, conv(n.Left(), types.Types[et]), conv(n.Right(), types.Types[et])) } + return n case ir.OINDEX: n.SetLeft(walkexpr(n.Left(), init)) @@ -1057,7 +1101,7 @@ opswitch: // if range of type cannot exceed static array bound, // disable bounds check. if n.Bounded() { - break + return n } t := n.Left().Type() if t != nil && t.IsPtr() { @@ -1086,6 +1130,7 @@ opswitch: base.Errorf("index out of bounds") } } + return n case ir.OINDEXMAP: // Replace m[k] with *map{access1,assign}(maptype, m, &k) @@ -1124,14 +1169,17 @@ opswitch: n = ir.Nod(ir.ODEREF, n, nil) n.SetType(t.Elem()) n.SetTypecheck(1) + return n case ir.ORECV: base.Fatalf("walkexpr ORECV") // should see inside OAS only + panic("unreachable") case ir.OSLICEHEADER: n.SetLeft(walkexpr(n.Left(), init)) n.List().SetFirst(walkexpr(n.List().First(), init)) n.List().SetSecond(walkexpr(n.List().Second(), init)) + return n case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR: checkSlice := checkPtr(Curfn, 1) && n.Op() == ir.OSLICE3ARR && n.Left().Op() == ir.OCONVNOP && n.Left().Left().Type().IsUnsafePtr() @@ -1160,11 +1208,11 @@ opswitch: } else { n.SetOp(ir.OSLICEARR) } - n = reduceSlice(n) + return reduceSlice(n) } - } else { - n = reduceSlice(n) + return n } + return reduceSlice(n) case ir.ONEW: if n.Type().Elem().NotInHeap() { @@ -1179,28 +1227,26 @@ opswitch: r = typecheck(r, ctxStmt) init.Append(r) r = ir.Nod(ir.OADDR, r.Left(), nil) - r = typecheck(r, ctxExpr) - n = r - } else { - n = callnew(n.Type().Elem()) + return typecheck(r, ctxExpr) } + return callnew(n.Type().Elem()) case ir.OADDSTR: - n = addstr(n, init) + return addstr(n, init) case ir.OAPPEND: // order should make sure we only see OAS(node, OAPPEND), which we handle above. base.Fatalf("append outside assignment") + panic("unreachable") case ir.OCOPY: - n = copyany(n, init, instrumenting && !base.Flag.CompilingRuntime) + return copyany(n, init, instrumenting && !base.Flag.CompilingRuntime) - // cannot use chanfn - closechan takes any, not chan any case ir.OCLOSE: + // cannot use chanfn - closechan takes any, not chan any fn := syslook("closechan") - fn = substArgTypes(fn, n.Left().Type()) - n = mkcall1(fn, nil, init, n.Left()) + return mkcall1(fn, nil, init, n.Left()) case ir.OMAKECHAN: // When size fits into int, use makechan instead of @@ -1217,7 +1263,7 @@ opswitch: argtype = types.Types[types.TINT] } - n = mkcall1(chanfn(fnname, 1, n.Type()), n.Type(), init, typename(n.Type()), conv(size, argtype)) + return mkcall1(chanfn(fnname, 1, n.Type()), n.Type(), init, typename(n.Type()), conv(size, argtype)) case ir.OMAKEMAP: t := n.Type() @@ -1294,42 +1340,41 @@ opswitch: a = typecheck(a, ctxStmt) a = walkexpr(a, init) init.Append(a) - n = convnop(h, t) - } else { - // Call runtime.makehmap to allocate an - // hmap on the heap and initialize hmap's hash0 field. - fn := syslook("makemap_small") - fn = substArgTypes(fn, t.Key(), t.Elem()) - n = mkcall1(fn, n.Type(), init) + return convnop(h, t) } - } else { - if n.Esc() != EscNone { - h = nodnil() - } - // Map initialization with a variable or large hint is - // more complicated. We therefore generate a call to - // runtime.makemap to initialize hmap and allocate the - // map buckets. - - // When hint fits into int, use makemap instead of - // makemap64, which is faster and shorter on 32 bit platforms. - fnname := "makemap64" - argtype := types.Types[types.TINT64] - - // Type checking guarantees that TIDEAL hint is positive and fits in an int. - // See checkmake call in TMAP case of OMAKE case in OpSwitch in typecheck1 function. - // The case of hint overflow when converting TUINT or TUINTPTR to TINT - // will be handled by the negative range checks in makemap during runtime. - if hint.Type().IsKind(types.TIDEAL) || hint.Type().Size() <= types.Types[types.TUINT].Size() { - fnname = "makemap" - argtype = types.Types[types.TINT] - } - - fn := syslook(fnname) - fn = substArgTypes(fn, hmapType, t.Key(), t.Elem()) - n = mkcall1(fn, n.Type(), init, typename(n.Type()), conv(hint, argtype), h) + // Call runtime.makehmap to allocate an + // hmap on the heap and initialize hmap's hash0 field. + fn := syslook("makemap_small") + fn = substArgTypes(fn, t.Key(), t.Elem()) + return mkcall1(fn, n.Type(), init) } + if n.Esc() != EscNone { + h = nodnil() + } + // Map initialization with a variable or large hint is + // more complicated. We therefore generate a call to + // runtime.makemap to initialize hmap and allocate the + // map buckets. + + // When hint fits into int, use makemap instead of + // makemap64, which is faster and shorter on 32 bit platforms. + fnname := "makemap64" + argtype := types.Types[types.TINT64] + + // Type checking guarantees that TIDEAL hint is positive and fits in an int. + // See checkmake call in TMAP case of OMAKE case in OpSwitch in typecheck1 function. + // The case of hint overflow when converting TUINT or TUINTPTR to TINT + // will be handled by the negative range checks in makemap during runtime. + if hint.Type().IsKind(types.TIDEAL) || hint.Type().Size() <= types.Types[types.TUINT].Size() { + fnname = "makemap" + argtype = types.Types[types.TINT] + } + + fn := syslook(fnname) + fn = substArgTypes(fn, hmapType, t.Key(), t.Elem()) + return mkcall1(fn, n.Type(), init, typename(n.Type()), conv(hint, argtype), h) + case ir.OMAKESLICE: l := n.Left() r := n.Right() @@ -1376,39 +1421,39 @@ opswitch: r = conv(r, n.Type()) // in case n.Type is named. r = typecheck(r, ctxExpr) r = walkexpr(r, init) - n = r - } else { - // n escapes; set up a call to makeslice. - // When len and cap can fit into int, use makeslice instead of - // makeslice64, which is faster and shorter on 32 bit platforms. - - len, cap := l, r - - fnname := "makeslice64" - argtype := types.Types[types.TINT64] - - // Type checking guarantees that TIDEAL len/cap are positive and fit in an int. - // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT - // will be handled by the negative range checks in makeslice during runtime. - if (len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size()) && - (cap.Type().IsKind(types.TIDEAL) || cap.Type().Size() <= types.Types[types.TUINT].Size()) { - fnname = "makeslice" - argtype = types.Types[types.TINT] - } - - m := ir.Nod(ir.OSLICEHEADER, nil, nil) - m.SetType(t) - - fn := syslook(fnname) - m.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))) - m.Left().MarkNonNil() - m.PtrList().Set2(conv(len, types.Types[types.TINT]), conv(cap, types.Types[types.TINT])) - - m = typecheck(m, ctxExpr) - m = walkexpr(m, init) - n = m + return r } + // n escapes; set up a call to makeslice. + // When len and cap can fit into int, use makeslice instead of + // makeslice64, which is faster and shorter on 32 bit platforms. + + len, cap := l, r + + fnname := "makeslice64" + argtype := types.Types[types.TINT64] + + // Type checking guarantees that TIDEAL len/cap are positive and fit in an int. + // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT + // will be handled by the negative range checks in makeslice during runtime. + if (len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size()) && + (cap.Type().IsKind(types.TIDEAL) || cap.Type().Size() <= types.Types[types.TUINT].Size()) { + fnname = "makeslice" + argtype = types.Types[types.TINT] + } + + m := ir.Nod(ir.OSLICEHEADER, nil, nil) + m.SetType(t) + + fn := syslook(fnname) + m.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))) + m.Left().MarkNonNil() + m.PtrList().Set2(conv(len, types.Types[types.TINT]), conv(cap, types.Types[types.TINT])) + + m = typecheck(m, ctxExpr) + m = walkexpr(m, init) + return m + case ir.OMAKESLICECOPY: if n.Esc() == EscNone { base.Fatalf("OMAKESLICECOPY with EscNone: %v", n) @@ -1453,18 +1498,18 @@ opswitch: ncopy = walkexpr(ncopy, init) init.Append(ncopy) - n = s - } else { // Replace make+copy with runtime.makeslicecopy. - // instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer - fn := syslook("makeslicecopy") - s := ir.Nod(ir.OSLICEHEADER, nil, nil) - s.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[types.TUNSAFEPTR]))) - s.Left().MarkNonNil() - s.PtrList().Set2(length, length) - s.SetType(t) - n = typecheck(s, ctxExpr) - n = walkexpr(n, init) + return s } + // Replace make+copy with runtime.makeslicecopy. + // instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer + fn := syslook("makeslicecopy") + s := ir.Nod(ir.OSLICEHEADER, nil, nil) + s.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[types.TUNSAFEPTR]))) + s.Left().MarkNonNil() + s.PtrList().Set2(length, length) + s.SetType(t) + n = typecheck(s, ctxExpr) + return walkexpr(n, init) case ir.ORUNESTR: a := nodnil() @@ -1473,7 +1518,7 @@ opswitch: a = ir.Nod(ir.OADDR, temp(t), nil) } // intstring(*[4]byte, rune) - n = mkcall("intstring", n.Type(), init, a, conv(n.Left(), types.Types[types.TINT64])) + return mkcall("intstring", n.Type(), init, a, conv(n.Left(), types.Types[types.TINT64])) case ir.OBYTES2STR, ir.ORUNES2STR: a := nodnil() @@ -1484,25 +1529,24 @@ opswitch: } if n.Op() == ir.ORUNES2STR { // slicerunetostring(*[32]byte, []rune) string - n = mkcall("slicerunetostring", n.Type(), init, a, n.Left()) - } else { - // slicebytetostring(*[32]byte, ptr *byte, n int) string - n.SetLeft(cheapexpr(n.Left(), init)) - ptr, len := backingArrayPtrLen(n.Left()) - n = mkcall("slicebytetostring", n.Type(), init, a, ptr, len) + return mkcall("slicerunetostring", n.Type(), init, a, n.Left()) } + // slicebytetostring(*[32]byte, ptr *byte, n int) string + n.SetLeft(cheapexpr(n.Left(), init)) + ptr, len := backingArrayPtrLen(n.Left()) + return mkcall("slicebytetostring", n.Type(), init, a, ptr, len) case ir.OBYTES2STRTMP: n.SetLeft(walkexpr(n.Left(), init)) if !instrumenting { // Let the backend handle OBYTES2STRTMP directly // to avoid a function call to slicebytetostringtmp. - break + return n } // slicebytetostringtmp(ptr *byte, n int) string n.SetLeft(cheapexpr(n.Left(), init)) ptr, len := backingArrayPtrLen(n.Left()) - n = mkcall("slicebytetostringtmp", n.Type(), init, ptr, len) + return mkcall("slicebytetostringtmp", n.Type(), init, ptr, len) case ir.OSTR2BYTES: s := n.Left() @@ -1534,8 +1578,7 @@ opswitch: slice := ir.NodAt(n.Pos(), ir.OSLICEARR, p, nil) slice.SetType(n.Type()) slice.SetTypecheck(1) - n = walkexpr(slice, init) - break + return walkexpr(slice, init) } a := nodnil() @@ -1545,7 +1588,7 @@ opswitch: a = ir.Nod(ir.OADDR, temp(t), nil) } // stringtoslicebyte(*32[byte], string) []byte - n = mkcall("stringtoslicebyte", n.Type(), init, a, conv(s, types.Types[types.TSTRING])) + return mkcall("stringtoslicebyte", n.Type(), init, a, conv(s, types.Types[types.TSTRING])) case ir.OSTR2BYTESTMP: // []byte(string) conversion that creates a slice @@ -1556,6 +1599,7 @@ opswitch: // The only such case today is: // for i, c := range []byte(string) n.SetLeft(walkexpr(n.Left(), init)) + return n case ir.OSTR2RUNES: a := nodnil() @@ -1565,7 +1609,7 @@ opswitch: a = ir.Nod(ir.OADDR, temp(t), nil) } // stringtoslicerune(*[32]rune, string) []rune - n = mkcall("stringtoslicerune", n.Type(), init, a, conv(n.Left(), types.Types[types.TSTRING])) + return mkcall("stringtoslicerune", n.Type(), init, a, conv(n.Left(), types.Types[types.TSTRING])) case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT, ir.OPTRLIT: if isStaticCompositeLiteral(n) && !canSSAType(n.Type()) { @@ -1573,55 +1617,29 @@ opswitch: // Make direct reference to the static data. See issue 12841. vstat := readonlystaticname(n.Type()) fixedlit(inInitFunction, initKindStatic, n, vstat, init) - n = vstat - n = typecheck(n, ctxExpr) - break + return typecheck(vstat, ctxExpr) } var_ := temp(n.Type()) anylit(n, var_, init) - n = var_ + return var_ case ir.OSEND: n1 := n.Right() n1 = assignconv(n1, n.Left().Type().Elem(), "chan send") n1 = walkexpr(n1, init) n1 = ir.Nod(ir.OADDR, n1, nil) - n = mkcall1(chanfn("chansend1", 2, n.Left().Type()), nil, init, n.Left(), n1) + return mkcall1(chanfn("chansend1", 2, n.Left().Type()), nil, init, n.Left(), n1) case ir.OCLOSURE: - n = walkclosure(n, init) + return walkclosure(n, init) case ir.OCALLPART: - n = walkpartialcall(n.(*ir.CallPartExpr), init) + return walkpartialcall(n.(*ir.CallPartExpr), init) } - // Expressions that are constant at run time but not - // considered const by the language spec are not turned into - // constants until walk. For example, if n is y%1 == 0, the - // walk of y%1 may have replaced it by 0. - // Check whether n with its updated args is itself now a constant. - t := n.Type() - n = evalConst(n) - if n.Type() != t { - base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type()) - } - if n.Op() == ir.OLITERAL { - n = typecheck(n, ctxExpr) - // Emit string symbol now to avoid emitting - // any concurrently during the backend. - if v := n.Val(); v.Kind() == constant.String { - _ = stringsym(n.Pos(), constant.StringVal(v)) - } - } - - updateHasCall(n) - - if base.Flag.LowerW != 0 && n != nil { - ir.Dump("after walk expr", n) - } - - base.Pos = lno - return n + // No return! Each case must return (or panic), + // to avoid confusion about what gets returned + // in the presence of type assertions. } // markTypeUsedInInterface marks that type t is converted to an interface. From 837b35cc55c258bb57ac9fa337ed0783a6fcc617 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 7 Dec 2020 09:14:44 -0500 Subject: [PATCH 201/212] [dev.regabi] cmd/compile: adjust IR representations Based on actually using the IR when prototyping adding type assertions, a few changes to improve it: - Merge DeferStmt and GoStmt, since they are variants of one thing. - Introduce LogicalExpr for && and ||, since they (alone) need an init list before Y. - Add an explicit op to various constructors to make them easier to use. - Add separate StructKeyExpr - it stores Value in a different abstract location (Left) than KeyExpr (Right). - Export all fields for use by rewrites (and later reflection). Passes buildall w/ toolstash -cmp. Change-Id: Iefbff2386d2bb9ef511ce53b7f92ff6c709dc991 Reviewed-on: https://go-review.googlesource.com/c/go/+/275883 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/typecheck.go | 17 +-- src/cmd/compile/internal/gc/universe.go | 3 +- src/cmd/compile/internal/ir/expr.go | 186 ++++++++++++++--------- src/cmd/compile/internal/ir/name.go | 8 + src/cmd/compile/internal/ir/node.go | 51 +++---- src/cmd/compile/internal/ir/node_gen.go | 76 +++++---- src/cmd/compile/internal/ir/stmt.go | 139 ++++++++--------- src/cmd/compile/internal/ir/val.go | 2 +- 8 files changed, 266 insertions(+), 216 deletions(-) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 990921189a..36526d4c2d 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2010,18 +2010,13 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { } return n - case ir.ODEFER: + case ir.ODEFER, ir.OGO: n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr)) if !n.Left().Diag() { checkdefergo(n) } return n - case ir.OGO: - n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr)) - checkdefergo(n) - return n - case ir.OFOR, ir.OFORUNTIL: typecheckslice(n.Init().Slice(), ctxStmt) decldepth++ @@ -2885,9 +2880,9 @@ func typecheckcomplit(n ir.Node) (res ir.Node) { if l.Op() == ir.OKEY { key := l.Left() - l.SetOp(ir.OSTRUCTKEY) - l.SetLeft(l.Right()) - l.SetRight(nil) + sk := ir.NewStructKeyExpr(l.Pos(), nil, l.Right()) + ls[i] = sk + l = sk // An OXDOT uses the Sym field to hold // the field to the right of the dot, @@ -2895,7 +2890,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) { // is never a valid struct literal key. if key.Sym() == nil || key.Op() == ir.OXDOT || key.Sym().IsBlank() { base.Errorf("invalid field name %v in struct initializer", key) - l.SetLeft(typecheck(l.Left(), ctxExpr)) + sk.SetLeft(typecheck(sk.Left(), ctxExpr)) continue } @@ -2909,7 +2904,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) { s = s1 } } - l.SetSym(s) + sk.SetSym(s) } if l.Op() != ir.OSTRUCTKEY { diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 42b996d88d..c592e37497 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -202,8 +202,7 @@ func initUniverse() { ir.AsNode(s.Def).SetSym(s) s = types.BuiltinPkg.Lookup("iota") - s.Def = ir.Nod(ir.OIOTA, nil, nil) - ir.AsNode(s.Def).SetSym(s) + s.Def = ir.NewIota(base.Pos, s) for et := types.TINT8; et <= types.TUINT64; et++ { isInt[et] = true diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index a74e0712b9..8ea31c1929 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -159,8 +159,8 @@ func (n *BinaryExpr) SetOp(op Op) { switch op { default: panic(n.no("SetOp " + op.String())) - case OADD, OADDSTR, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, - OLSH, OLT, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSUB, OXOR, + case OADD, OADDSTR, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, + OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR, OCOPY, OCOMPLEX, OEFACE: n.op = op @@ -181,21 +181,21 @@ const ( // A CallExpr is a function call X(Args). type CallExpr struct { miniExpr - orig Node - X Node - Args Nodes - Rargs Nodes // TODO(rsc): Delete. - Body_ Nodes // TODO(rsc): Delete. - DDD bool - Use CallUse - noInline bool + orig Node + X Node + Args Nodes + Rargs Nodes // TODO(rsc): Delete. + Body_ Nodes // TODO(rsc): Delete. + DDD bool + Use CallUse + NoInline_ bool } -func NewCallExpr(pos src.XPos, fun Node, args []Node) *CallExpr { +func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr { n := &CallExpr{X: fun} n.pos = pos n.orig = n - n.op = OCALL + n.SetOp(op) n.Args.Set(args) return n } @@ -214,8 +214,8 @@ func (n *CallExpr) PtrRlist() *Nodes { return &n.Rargs } func (n *CallExpr) SetRlist(x Nodes) { n.Rargs = x } func (n *CallExpr) IsDDD() bool { return n.DDD } func (n *CallExpr) SetIsDDD(x bool) { n.DDD = x } -func (n *CallExpr) NoInline() bool { return n.noInline } -func (n *CallExpr) SetNoInline(x bool) { n.noInline = x } +func (n *CallExpr) NoInline() bool { return n.NoInline_ } +func (n *CallExpr) SetNoInline(x bool) { n.NoInline_ = x } func (n *CallExpr) Body() Nodes { return n.Body_ } func (n *CallExpr) PtrBody() *Nodes { return &n.Body_ } func (n *CallExpr) SetBody(x Nodes) { n.Body_ = x } @@ -233,21 +233,21 @@ func (n *CallExpr) SetOp(op Op) { // A CallPartExpr is a method expression X.Method (uncalled). type CallPartExpr struct { miniExpr - fn *Func + Func_ *Func X Node Method *types.Field } func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallPartExpr { - n := &CallPartExpr{fn: fn, X: x, Method: method} + n := &CallPartExpr{Func_: fn, X: x, Method: method} n.op = OCALLPART n.pos = pos n.typ = fn.Type() - n.fn = fn + n.Func_ = fn return n } -func (n *CallPartExpr) Func() *Func { return n.fn } +func (n *CallPartExpr) Func() *Func { return n.Func_ } func (n *CallPartExpr) Left() Node { return n.X } func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym } func (n *CallPartExpr) SetLeft(x Node) { n.X = x } @@ -268,20 +268,20 @@ func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr { func (n *ClosureExpr) Func() *Func { return n.Func_ } // A ClosureRead denotes reading a variable stored within a closure struct. -type ClosureRead struct { +type ClosureReadExpr struct { miniExpr - offset int64 + Offset_ int64 } -func NewClosureRead(typ *types.Type, offset int64) *ClosureRead { - n := &ClosureRead{offset: offset} +func NewClosureRead(typ *types.Type, offset int64) *ClosureReadExpr { + n := &ClosureReadExpr{Offset_: offset} n.typ = typ n.op = OCLOSUREREAD return n } -func (n *ClosureRead) Type() *types.Type { return n.typ } -func (n *ClosureRead) Offset() int64 { return n.offset } +func (n *ClosureReadExpr) Type() *types.Type { return n.typ } +func (n *ClosureReadExpr) Offset() int64 { return n.Offset_ } // A CompLitExpr is a composite literal Type{Vals}. // Before type-checking, the type is Ntype. @@ -292,10 +292,10 @@ type CompLitExpr struct { List_ Nodes // initialized values } -func NewCompLitExpr(pos src.XPos, typ Ntype, list []Node) *CompLitExpr { +func NewCompLitExpr(pos src.XPos, op Op, typ Ntype, list []Node) *CompLitExpr { n := &CompLitExpr{Ntype: typ} n.pos = pos - n.op = OCOMPLIT + n.SetOp(op) n.List_.Set(list) n.orig = n return n @@ -397,42 +397,48 @@ func (n *IndexExpr) SetOp(op Op) { } } -// A KeyExpr is an X:Y composite literal key. -// After type-checking, a key for a struct sets Sym to the field. +// A KeyExpr is a Key: Value composite literal key. type KeyExpr struct { miniExpr - Key Node - sym *types.Sym - Value Node - offset int64 + Key Node + Value Node } func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr { n := &KeyExpr{Key: key, Value: value} n.pos = pos n.op = OKEY - n.offset = types.BADWIDTH return n } -func (n *KeyExpr) Left() Node { return n.Key } -func (n *KeyExpr) SetLeft(x Node) { n.Key = x } -func (n *KeyExpr) Right() Node { return n.Value } -func (n *KeyExpr) SetRight(y Node) { n.Value = y } -func (n *KeyExpr) Sym() *types.Sym { return n.sym } -func (n *KeyExpr) SetSym(x *types.Sym) { n.sym = x } -func (n *KeyExpr) Offset() int64 { return n.offset } -func (n *KeyExpr) SetOffset(x int64) { n.offset = x } +func (n *KeyExpr) Left() Node { return n.Key } +func (n *KeyExpr) SetLeft(x Node) { n.Key = x } +func (n *KeyExpr) Right() Node { return n.Value } +func (n *KeyExpr) SetRight(y Node) { n.Value = y } -func (n *KeyExpr) SetOp(op Op) { - switch op { - default: - panic(n.no("SetOp " + op.String())) - case OKEY, OSTRUCTKEY: - n.op = op - } +// A StructKeyExpr is an Field: Value composite literal key. +type StructKeyExpr struct { + miniExpr + Field *types.Sym + Value Node + Offset_ int64 } +func NewStructKeyExpr(pos src.XPos, field *types.Sym, value Node) *StructKeyExpr { + n := &StructKeyExpr{Field: field, Value: value} + n.pos = pos + n.op = OSTRUCTKEY + n.Offset_ = types.BADWIDTH + return n +} + +func (n *StructKeyExpr) Sym() *types.Sym { return n.Field } +func (n *StructKeyExpr) SetSym(x *types.Sym) { n.Field = x } +func (n *StructKeyExpr) Left() Node { return n.Value } +func (n *StructKeyExpr) SetLeft(x Node) { n.Value = x } +func (n *StructKeyExpr) Offset() int64 { return n.Offset_ } +func (n *StructKeyExpr) SetOffset(x int64) { n.Offset_ = x } + // An InlinedCallExpr is an inlined function call. type InlinedCallExpr struct { miniExpr @@ -456,6 +462,36 @@ func (n *InlinedCallExpr) Rlist() Nodes { return n.ReturnVars } func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars } func (n *InlinedCallExpr) SetRlist(x Nodes) { n.ReturnVars = x } +// A LogicalExpr is a expression X Op Y where Op is && or ||. +// It is separate from BinaryExpr to make room for statements +// that must be executed before Y but after X. +type LogicalExpr struct { + miniExpr + X Node + Y Node +} + +func NewLogicalExpr(pos src.XPos, op Op, x, y Node) *LogicalExpr { + n := &LogicalExpr{X: x, Y: y} + n.pos = pos + n.SetOp(op) + return n +} + +func (n *LogicalExpr) Left() Node { return n.X } +func (n *LogicalExpr) SetLeft(x Node) { n.X = x } +func (n *LogicalExpr) Right() Node { return n.Y } +func (n *LogicalExpr) SetRight(y Node) { n.Y = y } + +func (n *LogicalExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case OANDAND, OOROR: + n.op = op + } +} + // A MakeExpr is a make expression: make(Type[, Len[, Cap]]). // Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY, // but *not* OMAKE (that's a pre-typechecking CallExpr). @@ -489,19 +525,19 @@ func (n *MakeExpr) SetOp(op Op) { // A MethodExpr is a method value X.M (where X is an expression, not a type). type MethodExpr struct { miniExpr - X Node - M Node - sym *types.Sym - offset int64 - class Class - Method *types.Field + X Node + M Node + Sym_ *types.Sym + Offset_ int64 + Class_ Class + Method *types.Field } -func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr { +func NewMethodExpr(pos src.XPos, x, m Node) *MethodExpr { n := &MethodExpr{X: x, M: m} n.pos = pos n.op = OMETHEXPR - n.offset = types.BADWIDTH + n.Offset_ = types.BADWIDTH return n } @@ -509,18 +545,18 @@ func (n *MethodExpr) Left() Node { return n.X } func (n *MethodExpr) SetLeft(x Node) { n.X = x } func (n *MethodExpr) Right() Node { return n.M } func (n *MethodExpr) SetRight(y Node) { n.M = y } -func (n *MethodExpr) Sym() *types.Sym { return n.sym } -func (n *MethodExpr) SetSym(x *types.Sym) { n.sym = x } -func (n *MethodExpr) Offset() int64 { return n.offset } -func (n *MethodExpr) SetOffset(x int64) { n.offset = x } -func (n *MethodExpr) Class() Class { return n.class } -func (n *MethodExpr) SetClass(x Class) { n.class = x } +func (n *MethodExpr) Sym() *types.Sym { return n.Sym_ } +func (n *MethodExpr) SetSym(x *types.Sym) { n.Sym_ = x } +func (n *MethodExpr) Offset() int64 { return n.Offset_ } +func (n *MethodExpr) SetOffset(x int64) { n.Offset_ = x } +func (n *MethodExpr) Class() Class { return n.Class_ } +func (n *MethodExpr) SetClass(x Class) { n.Class_ = x } // A NilExpr represents the predefined untyped constant nil. // (It may be copied and assigned a type, though.) type NilExpr struct { miniExpr - sym *types.Sym // TODO: Remove + Sym_ *types.Sym // TODO: Remove } func NewNilExpr(pos src.XPos) *NilExpr { @@ -530,8 +566,8 @@ func NewNilExpr(pos src.XPos) *NilExpr { return n } -func (n *NilExpr) Sym() *types.Sym { return n.sym } -func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x } +func (n *NilExpr) Sym() *types.Sym { return n.Sym_ } +func (n *NilExpr) SetSym(x *types.Sym) { n.Sym_ = x } // A ParenExpr is a parenthesized expression (X). // It may end up being a value or a type. @@ -563,34 +599,34 @@ func (n *ParenExpr) SetOTYPE(t *types.Type) { // A ResultExpr represents a direct access to a result slot on the stack frame. type ResultExpr struct { miniExpr - offset int64 + Offset_ int64 } func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr { - n := &ResultExpr{offset: offset} + n := &ResultExpr{Offset_: offset} n.pos = pos n.op = ORESULT n.typ = typ return n } -func (n *ResultExpr) Offset() int64 { return n.offset } -func (n *ResultExpr) SetOffset(x int64) { n.offset = x } +func (n *ResultExpr) Offset() int64 { return n.Offset_ } +func (n *ResultExpr) SetOffset(x int64) { n.Offset_ = x } // A SelectorExpr is a selector expression X.Sym. type SelectorExpr struct { miniExpr X Node Sel *types.Sym - offset int64 + Offset_ int64 Selection *types.Field } -func NewSelectorExpr(pos src.XPos, x Node, sel *types.Sym) *SelectorExpr { +func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr { n := &SelectorExpr{X: x, Sel: sel} n.pos = pos - n.op = OXDOT - n.offset = types.BADWIDTH + n.Offset_ = types.BADWIDTH + n.SetOp(op) return n } @@ -607,8 +643,8 @@ func (n *SelectorExpr) Left() Node { return n.X } func (n *SelectorExpr) SetLeft(x Node) { n.X = x } func (n *SelectorExpr) Sym() *types.Sym { return n.Sel } func (n *SelectorExpr) SetSym(x *types.Sym) { n.Sel = x } -func (n *SelectorExpr) Offset() int64 { return n.offset } -func (n *SelectorExpr) SetOffset(x int64) { n.offset = x } +func (n *SelectorExpr) Offset() int64 { return n.Offset_ } +func (n *SelectorExpr) SetOffset(x int64) { n.Offset_ = x } // Before type-checking, bytes.Buffer is a SelectorExpr. // After type-checking it becomes a Name. diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 319c40e4e9..4cf12f2c5d 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -132,6 +132,14 @@ func NewNameAt(pos src.XPos, sym *types.Sym) *Name { return newNameAt(pos, ONAME, sym) } +// NewIota returns a new OIOTA Node. +func NewIota(pos src.XPos, sym *types.Sym) *Name { + if sym == nil { + base.Fatalf("NewIota nil") + } + return newNameAt(pos, OIOTA, sym) +} + // NewDeclNameAt returns a new ONONAME Node associated with symbol s at position pos. // The caller is responsible for setting Curfn. func NewDeclNameAt(pos src.XPos, sym *types.Sym) *Name { diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index d6dab0b9e2..0191014133 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -681,30 +681,31 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { switch op { default: panic("NodAt " + op.String()) - case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, - OLSH, OLT, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSUB, OXOR, + case OADD, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, + OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR, OCOPY, OCOMPLEX, OEFACE: return NewBinaryExpr(pos, op, nleft, nright) - case OADDR, OPTRLIT: + case OADDR: return NewAddrExpr(pos, nleft) case OADDSTR: return NewAddStringExpr(pos, nil) + case OANDAND, OOROR: + return NewLogicalExpr(pos, op, nleft, nright) case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT: var typ Ntype if nright != nil { typ = nright.(Ntype) } - n := NewCompLitExpr(pos, typ, nil) - n.SetOp(op) - return n + return NewCompLitExpr(pos, op, typ, nil) case OAS, OSELRECV: n := NewAssignStmt(pos, nleft, nright) - n.SetOp(op) + if op != OAS { + n.SetOp(op) + } return n case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2: - n := NewAssignListStmt(pos, nil, nil) - n.SetOp(op) + n := NewAssignListStmt(pos, op, nil, nil) return n case OASOP: return NewAssignOpStmt(pos, OXXX, nleft, nright) @@ -722,9 +723,7 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { return NewBranchStmt(pos, op, nil) case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER: - n := NewCallExpr(pos, nleft, nil) - n.SetOp(op) - return n + return NewCallExpr(pos, op, nleft, nil) case OCASE: return NewCaseStmt(pos, nil, nil) case OCONV, OCONVIFACE, OCONVNOP, ORUNESTR: @@ -733,38 +732,38 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { return NewDecl(pos, op, nleft) case ODCLFUNC: return NewFunc(pos) - case ODEFER: - return NewDeferStmt(pos, nleft) + case ODEFER, OGO: + return NewGoDeferStmt(pos, op, nleft) case ODEREF: return NewStarExpr(pos, nleft) case ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT: - n := NewSelectorExpr(pos, nleft, nil) - n.SetOp(op) - return n + return NewSelectorExpr(pos, op, nleft, nil) case ODOTTYPE, ODOTTYPE2: var typ Ntype if nright != nil { typ = nright.(Ntype) } n := NewTypeAssertExpr(pos, nleft, typ) - n.SetOp(op) + if op != ODOTTYPE { + n.SetOp(op) + } return n case OFOR: return NewForStmt(pos, nil, nleft, nright, nil) - case OGO: - return NewGoStmt(pos, nleft) case OIF: return NewIfStmt(pos, nleft, nil, nil) case OINDEX, OINDEXMAP: n := NewIndexExpr(pos, nleft, nright) - n.SetOp(op) + if op != OINDEX { + n.SetOp(op) + } return n case OINLMARK: return NewInlineMarkStmt(pos, types.BADWIDTH) - case OKEY, OSTRUCTKEY: - n := NewKeyExpr(pos, nleft, nright) - n.SetOp(op) - return n + case OKEY: + return NewKeyExpr(pos, nleft, nright) + case OSTRUCTKEY: + return NewStructKeyExpr(pos, nil, nleft) case OLABEL: return NewLabelStmt(pos, nil) case OLITERAL, OTYPE, OIOTA: @@ -772,7 +771,7 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY: return NewMakeExpr(pos, op, nleft, nright) case OMETHEXPR: - return NewMethodExpr(pos, op, nleft, nright) + return NewMethodExpr(pos, nleft, nright) case ONIL: return NewNilExpr(pos) case OPACK: diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index b3fd89c367..4eedcfdd29 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -280,19 +280,19 @@ func (n *ClosureExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *ClosureRead) String() string { return fmt.Sprint(n) } -func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *ClosureRead) copy() Node { +func (n *ClosureReadExpr) String() string { return fmt.Sprint(n) } +func (n *ClosureReadExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *ClosureReadExpr) copy() Node { c := *n c.init = c.init.Copy() return &c } -func (n *ClosureRead) doChildren(do func(Node) error) error { +func (n *ClosureReadExpr) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) return err } -func (n *ClosureRead) editChildren(edit func(Node) Node) { +func (n *ClosureReadExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) } @@ -366,24 +366,6 @@ func (n *Decl) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } -func (n *DeferStmt) String() string { return fmt.Sprint(n) } -func (n *DeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *DeferStmt) copy() Node { - c := *n - c.init = c.init.Copy() - return &c -} -func (n *DeferStmt) doChildren(do func(Node) error) error { - var err error - err = maybeDoList(n.init, err, do) - err = maybeDo(n.Call, err, do) - return err -} -func (n *DeferStmt) editChildren(edit func(Node) Node) { - editList(n.init, edit) - n.Call = maybeEdit(n.Call, edit) -} - func (n *ForStmt) String() string { return fmt.Sprint(n) } func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ForStmt) copy() Node { @@ -450,20 +432,20 @@ func (n *FuncType) editChildren(edit func(Node) Node) { editFields(n.Results, edit) } -func (n *GoStmt) String() string { return fmt.Sprint(n) } -func (n *GoStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } -func (n *GoStmt) copy() Node { +func (n *GoDeferStmt) String() string { return fmt.Sprint(n) } +func (n *GoDeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *GoDeferStmt) copy() Node { c := *n c.init = c.init.Copy() return &c } -func (n *GoStmt) doChildren(do func(Node) error) error { +func (n *GoDeferStmt) doChildren(do func(Node) error) error { var err error err = maybeDoList(n.init, err, do) err = maybeDo(n.Call, err, do) return err } -func (n *GoStmt) editChildren(edit func(Node) Node) { +func (n *GoDeferStmt) editChildren(edit func(Node) Node) { editList(n.init, edit) n.Call = maybeEdit(n.Call, edit) } @@ -602,6 +584,26 @@ func (n *LabelStmt) editChildren(edit func(Node) Node) { editList(n.init, edit) } +func (n *LogicalExpr) String() string { return fmt.Sprint(n) } +func (n *LogicalExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *LogicalExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *LogicalExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.X, err, do) + err = maybeDo(n.Y, err, do) + return err +} +func (n *LogicalExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.X = maybeEdit(n.X, edit) + n.Y = maybeEdit(n.Y, edit) +} + func (n *MakeExpr) String() string { return fmt.Sprint(n) } func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *MakeExpr) copy() Node { @@ -913,6 +915,24 @@ func (n *StarExpr) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } +func (n *StructKeyExpr) String() string { return fmt.Sprint(n) } +func (n *StructKeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *StructKeyExpr) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *StructKeyExpr) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + err = maybeDo(n.Value, err, do) + return err +} +func (n *StructKeyExpr) editChildren(edit func(Node) Node) { + editList(n.init, edit) + n.Value = maybeEdit(n.Value, edit) +} + func (n *StructType) String() string { return fmt.Sprint(n) } func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *StructType) copy() Node { diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 68f9b0bd7c..28c40c0781 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -63,19 +63,19 @@ func (n *miniStmt) SetHasCall(b bool) { n.bits.set(miniHasCall, b) } // If Def is true, the assignment is a :=. type AssignListStmt struct { miniStmt - Lhs Nodes - Def bool - Rhs Nodes - offset int64 // for initorder + Lhs Nodes + Def bool + Rhs Nodes + Offset_ int64 // for initorder } -func NewAssignListStmt(pos src.XPos, lhs, rhs []Node) *AssignListStmt { +func NewAssignListStmt(pos src.XPos, op Op, lhs, rhs []Node) *AssignListStmt { n := &AssignListStmt{} n.pos = pos - n.op = OAS2 + n.SetOp(op) n.Lhs.Set(lhs) n.Rhs.Set(rhs) - n.offset = types.BADWIDTH + n.Offset_ = types.BADWIDTH return n } @@ -87,8 +87,8 @@ func (n *AssignListStmt) PtrRlist() *Nodes { return &n.Rhs } func (n *AssignListStmt) SetRlist(x Nodes) { n.Rhs = x } func (n *AssignListStmt) Colas() bool { return n.Def } func (n *AssignListStmt) SetColas(x bool) { n.Def = x } -func (n *AssignListStmt) Offset() int64 { return n.offset } -func (n *AssignListStmt) SetOffset(x int64) { n.offset = x } +func (n *AssignListStmt) Offset() int64 { return n.Offset_ } +func (n *AssignListStmt) SetOffset(x int64) { n.Offset_ = x } func (n *AssignListStmt) SetOp(op Op) { switch op { @@ -103,17 +103,17 @@ func (n *AssignListStmt) SetOp(op Op) { // If Def is true, the assignment is a :=. type AssignStmt struct { miniStmt - X Node - Def bool - Y Node - offset int64 // for initorder + X Node + Def bool + Y Node + Offset_ int64 // for initorder } func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt { n := &AssignStmt{X: x, Y: y} n.pos = pos n.op = OAS - n.offset = types.BADWIDTH + n.Offset_ = types.BADWIDTH return n } @@ -123,8 +123,8 @@ func (n *AssignStmt) Right() Node { return n.Y } func (n *AssignStmt) SetRight(y Node) { n.Y = y } func (n *AssignStmt) Colas() bool { return n.Def } func (n *AssignStmt) SetColas(x bool) { n.Def = x } -func (n *AssignStmt) Offset() int64 { return n.offset } -func (n *AssignStmt) SetOffset(x int64) { n.offset = x } +func (n *AssignStmt) Offset() int64 { return n.Offset_ } +func (n *AssignStmt) SetOffset(x int64) { n.Offset_ = x } func (n *AssignStmt) SetOp(op Op) { switch op { @@ -236,32 +236,16 @@ func (n *CaseStmt) SetRlist(x Nodes) { n.Vars = x } func (n *CaseStmt) Left() Node { return n.Comm } func (n *CaseStmt) SetLeft(x Node) { n.Comm = x } -// A DeferStmt is a defer statement: defer Call. -type DeferStmt struct { - miniStmt - Call Node -} - -func NewDeferStmt(pos src.XPos, call Node) *DeferStmt { - n := &DeferStmt{Call: call} - n.pos = pos - n.op = ODEFER - return n -} - -func (n *DeferStmt) Left() Node { return n.Call } -func (n *DeferStmt) SetLeft(x Node) { n.Call = x } - // A ForStmt is a non-range for loop: for Init; Cond; Post { Body } // Op can be OFOR or OFORUNTIL (!Cond). type ForStmt struct { miniStmt - Label *types.Sym - Cond Node - Late Nodes - Post Node - Body_ Nodes - hasBreak bool + Label *types.Sym + Cond Node + Late Nodes + Post Node + Body_ Nodes + HasBreak_ bool } func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStmt { @@ -285,8 +269,8 @@ func (n *ForStmt) SetBody(x Nodes) { n.Body_ = x } func (n *ForStmt) List() Nodes { return n.Late } func (n *ForStmt) PtrList() *Nodes { return &n.Late } func (n *ForStmt) SetList(x Nodes) { n.Late = x } -func (n *ForStmt) HasBreak() bool { return n.hasBreak } -func (n *ForStmt) SetHasBreak(b bool) { n.hasBreak = b } +func (n *ForStmt) HasBreak() bool { return n.HasBreak_ } +func (n *ForStmt) SetHasBreak(b bool) { n.HasBreak_ = b } func (n *ForStmt) SetOp(op Op) { if op != OFOR && op != OFORUNTIL { @@ -295,29 +279,38 @@ func (n *ForStmt) SetOp(op Op) { n.op = op } -// A GoStmt is a go statement: go Call. -type GoStmt struct { +// A GoDeferStmt is a go or defer statement: go Call / defer Call. +// +// The two opcodes use a signle syntax because the implementations +// are very similar: both are concerned with saving Call and running it +// in a different context (a separate goroutine or a later time). +type GoDeferStmt struct { miniStmt Call Node } -func NewGoStmt(pos src.XPos, call Node) *GoStmt { - n := &GoStmt{Call: call} +func NewGoDeferStmt(pos src.XPos, op Op, call Node) *GoDeferStmt { + n := &GoDeferStmt{Call: call} n.pos = pos - n.op = OGO + switch op { + case ODEFER, OGO: + n.op = op + default: + panic("NewGoDeferStmt " + op.String()) + } return n } -func (n *GoStmt) Left() Node { return n.Call } -func (n *GoStmt) SetLeft(x Node) { n.Call = x } +func (n *GoDeferStmt) Left() Node { return n.Call } +func (n *GoDeferStmt) SetLeft(x Node) { n.Call = x } // A IfStmt is a return statement: if Init; Cond { Then } else { Else }. type IfStmt struct { miniStmt - Cond Node - Body_ Nodes - Else Nodes - likely bool // code layout hint + Cond Node + Body_ Nodes + Else Nodes + Likely_ bool // code layout hint } func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt { @@ -337,8 +330,8 @@ func (n *IfStmt) SetBody(x Nodes) { n.Body_ = x } func (n *IfStmt) Rlist() Nodes { return n.Else } func (n *IfStmt) PtrRlist() *Nodes { return &n.Else } func (n *IfStmt) SetRlist(x Nodes) { n.Else = x } -func (n *IfStmt) Likely() bool { return n.likely } -func (n *IfStmt) SetLikely(x bool) { n.likely = x } +func (n *IfStmt) Likely() bool { return n.Likely_ } +func (n *IfStmt) SetLikely(x bool) { n.Likely_ = x } // An InlineMarkStmt is a marker placed just before an inlined body. type InlineMarkStmt struct { @@ -376,13 +369,13 @@ func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x } // Op can be OFOR or OFORUNTIL (!Cond). type RangeStmt struct { miniStmt - Label *types.Sym - Vars Nodes // TODO(rsc): Replace with Key, Value Node - Def bool - X Node - Body_ Nodes - hasBreak bool - typ *types.Type // TODO(rsc): Remove - use X.Type() instead + Label *types.Sym + Vars Nodes // TODO(rsc): Replace with Key, Value Node + Def bool + X Node + Body_ Nodes + HasBreak_ bool + typ *types.Type // TODO(rsc): Remove - use X.Type() instead } func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt { @@ -404,8 +397,8 @@ func (n *RangeStmt) SetBody(x Nodes) { n.Body_ = x } func (n *RangeStmt) List() Nodes { return n.Vars } func (n *RangeStmt) PtrList() *Nodes { return &n.Vars } func (n *RangeStmt) SetList(x Nodes) { n.Vars = x } -func (n *RangeStmt) HasBreak() bool { return n.hasBreak } -func (n *RangeStmt) SetHasBreak(b bool) { n.hasBreak = b } +func (n *RangeStmt) HasBreak() bool { return n.HasBreak_ } +func (n *RangeStmt) SetHasBreak(b bool) { n.HasBreak_ = b } func (n *RangeStmt) Colas() bool { return n.Def } func (n *RangeStmt) SetColas(b bool) { n.Def = b } func (n *RangeStmt) Type() *types.Type { return n.typ } @@ -437,9 +430,9 @@ func (n *ReturnStmt) IsDDD() bool { return false } // typecheckargs asks // A SelectStmt is a block: { Cases }. type SelectStmt struct { miniStmt - Label *types.Sym - Cases Nodes - hasBreak bool + Label *types.Sym + Cases Nodes + HasBreak_ bool // TODO(rsc): Instead of recording here, replace with a block? Compiled Nodes // compiled form, after walkswitch @@ -458,8 +451,8 @@ func (n *SelectStmt) PtrList() *Nodes { return &n.Cases } func (n *SelectStmt) SetList(x Nodes) { n.Cases = x } func (n *SelectStmt) Sym() *types.Sym { return n.Label } func (n *SelectStmt) SetSym(x *types.Sym) { n.Label = x } -func (n *SelectStmt) HasBreak() bool { return n.hasBreak } -func (n *SelectStmt) SetHasBreak(x bool) { n.hasBreak = x } +func (n *SelectStmt) HasBreak() bool { return n.HasBreak_ } +func (n *SelectStmt) SetHasBreak(x bool) { n.HasBreak_ = x } func (n *SelectStmt) Body() Nodes { return n.Compiled } func (n *SelectStmt) PtrBody() *Nodes { return &n.Compiled } func (n *SelectStmt) SetBody(x Nodes) { n.Compiled = x } @@ -486,10 +479,10 @@ func (n *SendStmt) SetRight(y Node) { n.Value = y } // A SwitchStmt is a switch statement: switch Init; Expr { Cases }. type SwitchStmt struct { miniStmt - Tag Node - Cases Nodes // list of *CaseStmt - Label *types.Sym - hasBreak bool + Tag Node + Cases Nodes // list of *CaseStmt + Label *types.Sym + HasBreak_ bool // TODO(rsc): Instead of recording here, replace with a block? Compiled Nodes // compiled form, after walkswitch @@ -513,8 +506,8 @@ func (n *SwitchStmt) PtrBody() *Nodes { return &n.Compiled } func (n *SwitchStmt) SetBody(x Nodes) { n.Compiled = x } func (n *SwitchStmt) Sym() *types.Sym { return n.Label } func (n *SwitchStmt) SetSym(x *types.Sym) { n.Label = x } -func (n *SwitchStmt) HasBreak() bool { return n.hasBreak } -func (n *SwitchStmt) SetHasBreak(x bool) { n.hasBreak = x } +func (n *SwitchStmt) HasBreak() bool { return n.HasBreak_ } +func (n *SwitchStmt) SetHasBreak(x bool) { n.HasBreak_ = x } // A TypeSwitchGuard is the [Name :=] X.(type) in a type switch. type TypeSwitchGuard struct { diff --git a/src/cmd/compile/internal/ir/val.go b/src/cmd/compile/internal/ir/val.go index ad0df5508d..5b0506c0d0 100644 --- a/src/cmd/compile/internal/ir/val.go +++ b/src/cmd/compile/internal/ir/val.go @@ -92,7 +92,7 @@ func ValidTypeForConst(t *types.Type, v constant.Value) bool { // nodlit returns a new untyped constant with value v. func NewLiteral(v constant.Value) Node { - n := Nod(OLITERAL, nil, nil) + n := newNameAt(base.Pos, OLITERAL, nil) if k := v.Kind(); k != constant.Unknown { n.SetType(idealType(k)) n.SetVal(v) From eae8fd519b2cbfa253f2f9068587e0ce765efced Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 8 Dec 2020 01:28:57 -0800 Subject: [PATCH 202/212] [dev.regabi] cmd/compile: iexport debug crumbs for toolstash Prints offsets for declarations, inline bodies, and strings when -v is used. Still not much, but hopefully useful for narrowing down the cause of export data differences. Change-Id: I9b2e4a3d55b92823fa45a39923e8c4b25303693c Reviewed-on: https://go-review.googlesource.com/c/go/+/276112 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/iexport.go | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index b1cc9a3dd9..14356013de 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -290,6 +290,10 @@ func iexport(out *bufio.Writer) { w.writeIndex(p.inlineIndex, false) w.flush() + if *base.Flag.LowerV { + fmt.Printf("export: hdr strings %v, data %v, index %v\n", p.strings.Len(), dataLen, p.data0.Len()) + } + // Assemble header. var hdr intWriter hdr.WriteByte('i') @@ -389,6 +393,10 @@ func (p *iexporter) stringOff(s string) uint64 { off = uint64(p.strings.Len()) p.stringIndex[s] = off + if *base.Flag.LowerV { + fmt.Printf("export: str %v %.40q\n", off, s) + } + p.strings.uint64(uint64(len(s))) p.strings.WriteString(s) } @@ -511,20 +519,28 @@ func (p *iexporter) doDecl(n *ir.Name) { base.Fatalf("unexpected node: %v", n) } - p.declIndex[n.Sym()] = w.flush() + w.finish("dcl", p.declIndex, n.Sym()) } func (w *exportWriter) tag(tag byte) { w.data.WriteByte(tag) } +func (w *exportWriter) finish(what string, index map[*types.Sym]uint64, sym *types.Sym) { + off := w.flush() + if *base.Flag.LowerV { + fmt.Printf("export: %v %v %v\n", what, off, sym) + } + index[sym] = off +} + func (p *iexporter) doInline(f *ir.Name) { w := p.newWriter() w.setPkg(fnpkg(f), false) w.stmtList(ir.AsNodes(f.Func().Inl.Body)) - p.inlineIndex[f.Sym()] = w.flush() + w.finish("inl", p.inlineIndex, f.Sym()) } func (w *exportWriter) pos(pos src.XPos) { @@ -625,7 +641,11 @@ func (p *iexporter) typOff(t *types.Type) uint64 { if !ok { w := p.newWriter() w.doTyp(t) - off = predeclReserved + w.flush() + rawOff := w.flush() + if *base.Flag.LowerV { + fmt.Printf("export: typ %v %v\n", rawOff, t) + } + off = predeclReserved + rawOff p.typIndex[t] = off } return off From 63bc23b5452f6605df3e40ce7ecdd8b0348792af Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 7 Dec 2020 21:56:58 -0800 Subject: [PATCH 203/212] [dev.regabi] cmd/compile: first start towards using Ident This CL adds Ident, which will eventually replace *Name and *PkgName within the AST for representing uses of declared names. (Originally, I intended to call it "IdentExpr", but neither go/ast nor cmd/compile/internal/syntax include the "Expr" suffix for their respective types.) To start, this CL converts two uses of *Name to *Ident: the tag identifier in a TypeSwitchGuard (which doesn't actually declare a variable by itself), and the not-yet-known placeholder ONONAME returned by oldname to stand-in for identifiers that might be declared later in the package. The TypeSwitchGuard's Name's Used flag was previously used for detecting whether none of the per-clause variables were used. To avoid bloating all Idents for this rare use, a "Used" bool is added to TypeSwitchGuard instead. Eventually it could maybe be packed into miniNode.bits, but for now this is good enough. Passes buildall w/ toolstash -cmp. Change-Id: I393284d86757cbbebd26e1320c7354e2bdcb30b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/276113 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/dcl.go | 2 +- src/cmd/compile/internal/gc/iimport.go | 10 +++++----- src/cmd/compile/internal/gc/noder.go | 10 +++++----- src/cmd/compile/internal/gc/typecheck.go | 8 ++++++-- src/cmd/compile/internal/gc/walk.go | 10 +++++----- src/cmd/compile/internal/ir/mknode.go | 8 ++++---- src/cmd/compile/internal/ir/name.go | 19 +++++++++++++++++++ src/cmd/compile/internal/ir/node.go | 2 -- src/cmd/compile/internal/ir/node_gen.go | 24 ++++++++++++++++++++---- src/cmd/compile/internal/ir/stmt.go | 20 +++++++++----------- 10 files changed, 74 insertions(+), 39 deletions(-) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 1c23c5a92f..1ebadd9213 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -215,7 +215,7 @@ func oldname(s *types.Sym) ir.Node { // Maybe a top-level declaration will come along later to // define s. resolve will check s.Def again once all input // source has been processed. - return ir.NewDeclNameAt(base.Pos, s) + return ir.NewIdent(base.Pos, s) } if Curfn != nil && n.Op() == ir.ONAME && n.Name().Curfn != nil && n.Name().Curfn != Curfn { diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 1f75393b3e..3c9693e5fc 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -833,13 +833,13 @@ func (r *importReader) node() ir.Node { return ir.TypeNode(r.typ()) case ir.OTYPESW: - n := ir.NodAt(r.pos(), ir.OTYPESW, nil, nil) + pos := r.pos() + var tag *ir.Ident if s := r.ident(); s != nil { - n.SetLeft(ir.NewDeclNameAt(n.Pos(), s)) + tag = ir.NewIdent(pos, s) } - right, _ := r.exprsOrNil() - n.SetRight(right) - return n + expr, _ := r.exprsOrNil() + return ir.NewTypeSwitchGuard(pos, tag, expr) // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC: // unreachable - should have been resolved by typechecking diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index f39bf2ff3c..8c765f9dfc 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -751,14 +751,14 @@ func (p *noder) expr(expr syntax.Expr) ir.Node { p.typeExpr(expr.Elem), p.chanDir(expr.Dir)) case *syntax.TypeSwitchGuard: - n := p.nod(expr, ir.OTYPESW, nil, p.expr(expr.X)) + var tag *ir.Ident if expr.Lhs != nil { - n.SetLeft(p.declName(expr.Lhs)) - if ir.IsBlank(n.Left()) { - base.Errorf("invalid variable name %v in type switch", n.Left()) + tag = ir.NewIdent(p.pos(expr.Lhs), p.name(expr.Lhs)) + if ir.IsBlank(tag) { + base.Errorf("invalid variable name %v in type switch", tag) } } - return n + return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X)) } panic("unhandled Expr") } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 36526d4c2d..d88989f83c 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -90,12 +90,16 @@ func resolve(n ir.Node) (res ir.Node) { defer tracePrint("resolve", n)(&res) } - if n.Sym().Pkg != types.LocalPkg { + // Stub ir.Name left for us by iimport. + if n, ok := n.(*ir.Name); ok { + if n.Sym().Pkg == types.LocalPkg { + base.Fatalf("unexpected Name: %+v", n) + } if inimport { base.Fatalf("recursive inimport") } inimport = true - expandDecl(n.(*ir.Name)) + expandDecl(n) inimport = false return n } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index f35e9d768b..390719e441 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -44,7 +44,7 @@ func walk(fn *ir.Func) { // Propagate the used flag for typeswitch variables up to the NONAME in its definition. for _, ln := range fn.Dcl { if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) && ln.Defn != nil && ln.Defn.Op() == ir.OTYPESW && ln.Used() { - ln.Defn.Left().Name().SetUsed(true) + ln.Defn.(*ir.TypeSwitchGuard).Used = true } } @@ -52,12 +52,12 @@ func walk(fn *ir.Func) { if ln.Op() != ir.ONAME || (ln.Class() != ir.PAUTO && ln.Class() != ir.PAUTOHEAP) || ln.Sym().Name[0] == '&' || ln.Used() { continue } - if defn := ln.Defn; defn != nil && defn.Op() == ir.OTYPESW { - if defn.Left().Name().Used() { + if defn, ok := ln.Defn.(*ir.TypeSwitchGuard); ok { + if defn.Used { continue } - base.ErrorfAt(defn.Left().Pos(), "%v declared but not used", ln.Sym()) - defn.Left().Name().SetUsed(true) // suppress repeats + base.ErrorfAt(defn.Tag.Pos(), "%v declared but not used", ln.Sym()) + defn.Used = true // suppress repeats } else { base.ErrorfAt(ln.Pos(), "%v declared but not used", ln.Sym()) } diff --git a/src/cmd/compile/internal/ir/mknode.go b/src/cmd/compile/internal/ir/mknode.go index 72034022cb..18d768ceb1 100644 --- a/src/cmd/compile/internal/ir/mknode.go +++ b/src/cmd/compile/internal/ir/mknode.go @@ -39,7 +39,7 @@ func main() { nodesType := lookup("Nodes") ptrFieldType := types.NewPointer(lookup("Field")) slicePtrFieldType := types.NewSlice(ptrFieldType) - ptrNameType := types.NewPointer(lookup("Name")) + ptrIdentType := types.NewPointer(lookup("Ident")) var buf bytes.Buffer fmt.Fprintln(&buf, "// Code generated by mknode.go. DO NOT EDIT.") @@ -84,7 +84,7 @@ func main() { fmt.Fprintf(&buf, "func (n *%s) doChildren(do func(Node) error) error { var err error\n", name) forNodeFields(typName, typ, func(name string, is func(types.Type) bool) { switch { - case is(ptrNameType): + case is(ptrIdentType): fmt.Fprintf(&buf, "if n.%s != nil { err = maybeDo(n.%s, err, do) }\n", name, name) case is(nodeType), is(ntypeType): fmt.Fprintf(&buf, "err = maybeDo(n.%s, err, do)\n", name) @@ -101,8 +101,8 @@ func main() { fmt.Fprintf(&buf, "func (n *%s) editChildren(edit func(Node) Node) {\n", name) forNodeFields(typName, typ, func(name string, is func(types.Type) bool) { switch { - case is(ptrNameType): - fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Name) }\n", name, name, name) + case is(ptrIdentType): + fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Ident) }\n", name, name, name) case is(nodeType): fmt.Fprintf(&buf, "n.%s = maybeEdit(n.%s, edit)\n", name, name) case is(ntypeType): diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 4cf12f2c5d..2330838f1c 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -13,6 +13,25 @@ import ( "go/constant" ) +// An Ident is an identifier, possibly qualified. +type Ident struct { + miniExpr + sym *types.Sym + Used bool +} + +func NewIdent(pos src.XPos, sym *types.Sym) *Ident { + n := new(Ident) + n.op = ONONAME + n.pos = pos + n.sym = sym + return n +} + +func (n *Ident) Sym() *types.Sym { return n.sym } + +func (*Ident) CanBeNtype() {} + // Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL). type Name struct { miniExpr diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 0191014133..598659a3db 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -794,8 +794,6 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node { return NewSliceHeaderExpr(pos, nil, nleft, nil, nil) case OSWITCH: return NewSwitchStmt(pos, nleft, nil) - case OTYPESW: - return NewTypeSwitchGuard(pos, nleft, nright) case OINLCALL: return NewInlinedCallExpr(pos, nil, nil) } diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index 4eedcfdd29..264171e797 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -450,6 +450,22 @@ func (n *GoDeferStmt) editChildren(edit func(Node) Node) { n.Call = maybeEdit(n.Call, edit) } +func (n *Ident) String() string { return fmt.Sprint(n) } +func (n *Ident) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } +func (n *Ident) copy() Node { + c := *n + c.init = c.init.Copy() + return &c +} +func (n *Ident) doChildren(do func(Node) error) error { + var err error + err = maybeDoList(n.init, err, do) + return err +} +func (n *Ident) editChildren(edit func(Node) Node) { + editList(n.init, edit) +} + func (n *IfStmt) String() string { return fmt.Sprint(n) } func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *IfStmt) copy() Node { @@ -1004,15 +1020,15 @@ func (n *TypeSwitchGuard) copy() Node { } func (n *TypeSwitchGuard) doChildren(do func(Node) error) error { var err error - if n.Name_ != nil { - err = maybeDo(n.Name_, err, do) + if n.Tag != nil { + err = maybeDo(n.Tag, err, do) } err = maybeDo(n.X, err, do) return err } func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) { - if n.Name_ != nil { - n.Name_ = edit(n.Name_).(*Name) + if n.Tag != nil { + n.Tag = edit(n.Tag).(*Ident) } n.X = maybeEdit(n.X, edit) } diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 28c40c0781..f41c50c92b 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -512,32 +512,30 @@ func (n *SwitchStmt) SetHasBreak(x bool) { n.HasBreak_ = x } // A TypeSwitchGuard is the [Name :=] X.(type) in a type switch. type TypeSwitchGuard struct { miniNode - Name_ *Name - X Node + Tag *Ident + X Node + Used bool } -func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard { - n := &TypeSwitchGuard{X: x} - if name != nil { - n.Name_ = name.(*Name) - } +func NewTypeSwitchGuard(pos src.XPos, tag *Ident, x Node) *TypeSwitchGuard { + n := &TypeSwitchGuard{Tag: tag, X: x} n.pos = pos n.op = OTYPESW return n } func (n *TypeSwitchGuard) Left() Node { - if n.Name_ == nil { + if n.Tag == nil { return nil } - return n.Name_ + return n.Tag } func (n *TypeSwitchGuard) SetLeft(x Node) { if x == nil { - n.Name_ = nil + n.Tag = nil return } - n.Name_ = x.(*Name) + n.Tag = x.(*Ident) } func (n *TypeSwitchGuard) Right() Node { return n.X } func (n *TypeSwitchGuard) SetRight(x Node) { n.X = x } From 4f1b0a44cb46f3df28f5ef82e5769ebeac1bc493 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 29 Oct 2020 14:17:47 -0400 Subject: [PATCH 204/212] all: update to use os.ReadFile, os.WriteFile, os.CreateTemp, os.MkdirTemp As part of #42026, these helpers from io/ioutil were moved to os. (ioutil.TempFile and TempDir became os.CreateTemp and MkdirTemp.) Update the Go tree to use the preferred names. As usual, code compiled with the Go 1.4 bootstrap toolchain and code vendored from other sources is excluded. ReadDir changes are in a separate CL, because they are not a simple search and replace. For #42026. Change-Id: If318df0216d57e95ea0c4093b89f65e5b0ababb3 Reviewed-on: https://go-review.googlesource.com/c/go/+/266365 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/archive/tar/reader_test.go | 3 +- src/archive/tar/tar_test.go | 3 +- src/archive/tar/writer_test.go | 3 +- src/archive/zip/reader_test.go | 11 +++-- src/archive/zip/writer_test.go | 4 +- src/cmd/addr2line/addr2line_test.go | 7 ++-- src/cmd/api/goapi.go | 3 +- src/cmd/api/goapi_test.go | 3 +- src/cmd/cover/cover.go | 3 +- src/cmd/cover/cover_test.go | 31 +++++++------- src/cmd/cover/html.go | 5 +-- src/cmd/fix/main.go | 3 +- src/cmd/fix/typecheck.go | 7 ++-- src/cmd/go/go_test.go | 19 ++++----- src/cmd/go/go_windows_test.go | 5 +-- src/cmd/go/help_test.go | 4 +- src/cmd/go/internal/auth/netrc.go | 3 +- src/cmd/go/internal/bug/bug.go | 5 +-- src/cmd/go/internal/cache/cache.go | 5 +-- src/cmd/go/internal/cache/cache_test.go | 13 +++--- src/cmd/go/internal/cache/default.go | 3 +- src/cmd/go/internal/cache/hash_test.go | 3 +- src/cmd/go/internal/cfg/cfg.go | 3 +- src/cmd/go/internal/envcmd/env.go | 7 ++-- src/cmd/go/internal/fsys/fsys.go | 2 +- src/cmd/go/internal/fsys/fsys_test.go | 3 +- src/cmd/go/internal/generate/generate.go | 3 +- src/cmd/go/internal/imports/scan_test.go | 5 ++- src/cmd/go/internal/load/pkg.go | 4 +- .../internal/filelock/filelock_test.go | 5 +-- .../go/internal/lockedfile/lockedfile_test.go | 9 ++-- src/cmd/go/internal/modcmd/vendor.go | 2 +- src/cmd/go/internal/modcmd/verify.go | 3 +- src/cmd/go/internal/modconv/convert_test.go | 5 +-- src/cmd/go/internal/modconv/modconv_test.go | 6 +-- src/cmd/go/internal/modfetch/cache_test.go | 3 +- .../go/internal/modfetch/codehost/codehost.go | 5 +-- .../go/internal/modfetch/codehost/git_test.go | 3 +- .../go/internal/modfetch/codehost/shell.go | 3 +- src/cmd/go/internal/modfetch/codehost/vcs.go | 3 +- src/cmd/go/internal/modfetch/coderepo.go | 3 +- src/cmd/go/internal/modfetch/coderepo_test.go | 13 +++--- src/cmd/go/internal/modfetch/fetch.go | 5 +-- .../modfetch/zip_sum_test/zip_sum_test.go | 3 +- src/cmd/go/internal/modload/init.go | 8 ++-- src/cmd/go/internal/modload/query_test.go | 3 +- src/cmd/go/internal/modload/vendor.go | 4 +- src/cmd/go/internal/renameio/renameio.go | 4 +- src/cmd/go/internal/renameio/renameio_test.go | 3 +- src/cmd/go/internal/renameio/umask_test.go | 3 +- src/cmd/go/internal/robustio/robustio.go | 2 +- .../go/internal/robustio/robustio_flaky.go | 5 +-- .../go/internal/robustio/robustio_other.go | 3 +- src/cmd/go/internal/test/test.go | 4 +- src/cmd/go/internal/txtar/archive.go | 4 +- src/cmd/go/internal/vcs/vcs_test.go | 3 +- src/cmd/go/internal/web/file_test.go | 3 +- src/cmd/go/internal/work/action.go | 3 +- src/cmd/go/internal/work/build_test.go | 9 ++-- src/cmd/go/internal/work/buildid.go | 3 +- src/cmd/go/internal/work/exec.go | 17 ++++---- src/cmd/go/internal/work/gc.go | 7 ++-- src/cmd/go/internal/work/gccgo.go | 3 +- src/cmd/go/script_test.go | 23 +++++----- src/cmd/go/testdata/addmod.go | 13 +++--- src/cmd/go/testdata/savedir.go | 3 +- .../go/testdata/script/build_issue6480.txt | 5 +-- src/cmd/go/testdata/script/build_trimpath.txt | 3 +- src/cmd/go/testdata/script/cover_error.txt | 5 +-- .../go/testdata/script/gopath_moved_repo.txt | 5 +-- .../script/mod_download_concurrent_read.txt | 3 +- src/cmd/go/testdata/script/mod_modinfo.txt | 3 +- .../go/testdata/script/mod_test_cached.txt | 7 ++-- .../testdata/script/test_compile_tempfile.txt | 2 +- .../testdata/script/test_generated_main.txt | 3 +- .../testdata/script/test_race_install_cgo.txt | 8 ++-- src/cmd/gofmt/gofmt.go | 5 +-- src/cmd/gofmt/gofmt_test.go | 13 +++--- src/cmd/nm/nm_test.go | 9 ++-- src/cmd/objdump/objdump_test.go | 5 +-- src/cmd/pack/pack_test.go | 13 +++--- src/cmd/trace/annotations_test.go | 4 +- src/cmd/trace/pprof.go | 3 +- src/cmd/vet/vet_test.go | 5 +-- src/compress/bzip2/bzip2_test.go | 4 +- src/compress/flate/deflate_test.go | 6 +-- src/compress/flate/huffman_bit_writer_test.go | 29 +++++++------ src/compress/flate/reader_test.go | 4 +- src/compress/lzw/reader_test.go | 4 +- src/compress/lzw/writer_test.go | 3 +- src/compress/zlib/writer_test.go | 3 +- src/crypto/md5/gen.go | 4 +- src/crypto/tls/handshake_test.go | 3 +- src/crypto/tls/link_test.go | 3 +- src/crypto/tls/tls.go | 6 +-- src/crypto/x509/name_constraints_test.go | 3 +- src/crypto/x509/root_ios_gen.go | 4 +- src/crypto/x509/root_plan9.go | 3 +- src/crypto/x509/root_unix.go | 4 +- src/crypto/x509/root_unix_test.go | 5 +-- src/debug/dwarf/dwarf5ranges_test.go | 4 +- src/debug/gosym/pclntab_test.go | 5 +-- src/debug/pe/file_test.go | 13 +++--- src/embed/internal/embedtest/embedx_test.go | 4 +- src/go/build/build_test.go | 11 +++-- src/go/doc/doc_test.go | 6 +-- src/go/format/benchmark_test.go | 4 +- src/go/format/format_test.go | 6 +-- src/go/importer/importer_test.go | 3 +- .../internal/gccgoimporter/importer_test.go | 5 +-- src/go/internal/gcimporter/gcimporter_test.go | 6 +-- src/go/internal/srcimporter/srcimporter.go | 3 +- src/go/parser/interface.go | 3 +- src/go/parser/performance_test.go | 4 +- src/go/printer/performance_test.go | 4 +- src/go/printer/printer_test.go | 12 +++--- src/go/scanner/scanner_test.go | 3 +- src/go/types/check_test.go | 3 +- src/go/types/hilbert_test.go | 4 +- src/hash/crc32/gen_const_ppc64le.go | 4 +- src/html/template/examplefiles_test.go | 3 +- src/html/template/template.go | 4 +- src/image/color/palette/gen.go | 4 +- src/image/gif/reader_test.go | 4 +- src/image/internal/imageutil/gen.go | 3 +- src/image/jpeg/reader_test.go | 7 ++-- src/image/png/reader_test.go | 3 +- src/index/suffixarray/gen.go | 6 +-- src/index/suffixarray/suffixarray_test.go | 6 +-- src/internal/cpu/cpu_s390x_test.go | 4 +- .../obscuretestdata/obscuretestdata.go | 3 +- src/internal/poll/read_test.go | 3 +- src/internal/testenv/testenv_windows.go | 3 +- src/internal/trace/gc_test.go | 6 +-- src/internal/trace/parser_test.go | 2 +- src/log/syslog/syslog_test.go | 5 +-- src/math/big/link_test.go | 4 +- src/math/bits/make_examples.go | 4 +- src/math/bits/make_tables.go | 4 +- src/mime/multipart/formdata.go | 3 +- src/net/dnsclient_unix_test.go | 3 +- src/net/error_test.go | 3 +- src/net/http/filetransport_test.go | 5 +-- src/net/http/fs_test.go | 8 ++-- src/net/http/request_test.go | 3 +- src/net/http/transfer_test.go | 3 +- src/net/http/transport_test.go | 3 +- src/net/mockserver_test.go | 5 +-- src/net/net_windows_test.go | 7 ++-- src/net/unixsock_test.go | 3 +- src/os/error_test.go | 9 ++-- src/os/exec/exec_test.go | 2 +- src/os/exec/lp_unix_test.go | 3 +- src/os/exec/lp_windows_test.go | 7 ++-- src/os/fifo_test.go | 3 +- src/os/os_test.go | 42 +++++++++---------- src/os/os_unix_test.go | 4 +- src/os/os_windows_test.go | 29 +++++++------ src/os/path_test.go | 4 +- src/os/path_windows_test.go | 3 +- src/os/pipe_test.go | 3 +- src/os/readfrom_linux_test.go | 4 +- src/os/removeall_test.go | 20 ++++----- src/os/signal/signal_test.go | 3 +- src/os/signal/signal_windows_test.go | 3 +- src/os/stat_test.go | 9 ++-- src/os/timeout_test.go | 3 +- src/os/user/lookup_plan9.go | 3 +- src/path/filepath/example_unix_walk_test.go | 3 +- src/path/filepath/match_test.go | 7 ++-- src/path/filepath/path_test.go | 33 +++++++-------- src/path/filepath/path_windows_test.go | 19 ++++----- src/runtime/crash_test.go | 3 +- src/runtime/crash_unix_test.go | 5 +-- src/runtime/debug/heapdump_test.go | 5 +-- src/runtime/debug_test.go | 4 +- src/runtime/env_plan9.go | 4 +- src/runtime/internal/sys/gengoos.go | 8 ++-- src/runtime/memmove_linux_amd64_test.go | 3 +- src/runtime/mkduff.go | 4 +- src/runtime/mkfastlog2table.go | 4 +- src/runtime/mksizeclasses.go | 3 +- src/runtime/pprof/pprof_test.go | 5 +-- src/runtime/pprof/proto.go | 4 +- src/runtime/pprof/proto_test.go | 3 +- src/runtime/race/output_test.go | 5 +-- src/runtime/race/testdata/io_test.go | 3 +- src/runtime/runtime-gdb_test.go | 25 ++++++----- src/runtime/runtime-lldb_test.go | 9 ++-- src/runtime/signal_windows_test.go | 5 +-- src/runtime/syscall_windows_test.go | 25 ++++++----- src/runtime/testdata/testprog/memprof.go | 3 +- .../testdata/testprog/syscalls_linux.go | 3 +- src/runtime/testdata/testprog/timeprof.go | 3 +- src/runtime/testdata/testprog/vdso.go | 3 +- src/runtime/testdata/testprogcgo/pprof.go | 3 +- .../testdata/testprogcgo/threadpprof.go | 3 +- src/runtime/trace/trace_test.go | 3 +- src/runtime/wincallback.go | 7 ++-- src/sort/genzfunc.go | 4 +- src/strconv/makeisprint.go | 4 +- src/syscall/dirent_test.go | 9 ++-- src/syscall/exec_linux_test.go | 15 ++++--- src/syscall/getdirentries_test.go | 5 +-- src/syscall/mkasm_darwin.go | 9 ++-- src/syscall/syscall_linux_test.go | 11 +++-- src/syscall/syscall_unix_test.go | 7 ++-- src/syscall/syscall_windows_test.go | 3 +- src/testing/testing.go | 5 +-- src/text/template/examplefiles_test.go | 3 +- src/text/template/helper.go | 4 +- src/text/template/link_test.go | 7 ++-- src/time/genzabbrs.go | 4 +- src/time/tzdata/generate_zipdata.go | 3 +- src/time/zoneinfo_read.go | 2 +- 215 files changed, 556 insertions(+), 704 deletions(-) diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go index 411d1e0b99..789ddc1bc0 100644 --- a/src/archive/tar/reader_test.go +++ b/src/archive/tar/reader_test.go @@ -10,7 +10,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "math" "os" "path" @@ -773,7 +772,7 @@ func TestReadTruncation(t *testing.T) { "testdata/pax-path-hdr.tar", "testdata/sparse-formats.tar", } { - buf, err := ioutil.ReadFile(p) + buf, err := os.ReadFile(p) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/src/archive/tar/tar_test.go b/src/archive/tar/tar_test.go index d4a3d42312..91b38401b6 100644 --- a/src/archive/tar/tar_test.go +++ b/src/archive/tar/tar_test.go @@ -11,7 +11,6 @@ import ( "internal/testenv" "io" "io/fs" - "io/ioutil" "math" "os" "path" @@ -263,7 +262,7 @@ func TestFileInfoHeaderDir(t *testing.T) { func TestFileInfoHeaderSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := ioutil.TempDir("", "TestFileInfoHeaderSymlink") + tmpdir, err := os.MkdirTemp("", "TestFileInfoHeaderSymlink") if err != nil { t.Fatal(err) } diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go index 30556d27d0..a00f02d8fa 100644 --- a/src/archive/tar/writer_test.go +++ b/src/archive/tar/writer_test.go @@ -9,7 +9,6 @@ import ( "encoding/hex" "errors" "io" - "io/ioutil" "os" "path" "reflect" @@ -520,7 +519,7 @@ func TestWriter(t *testing.T) { } if v.file != "" { - want, err := ioutil.ReadFile(v.file) + want, err := os.ReadFile(v.file) if err != nil { t.Fatalf("ReadFile() = %v, want nil", err) } diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index b7a7d7a757..34e96f7da4 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -11,7 +11,6 @@ import ( "internal/obscuretestdata" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "regexp" @@ -629,7 +628,7 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { var c []byte if ft.Content != nil { c = ft.Content - } else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil { + } else if c, err = os.ReadFile("testdata/" + ft.File); err != nil { t.Error(err) return } @@ -685,7 +684,7 @@ func TestInvalidFiles(t *testing.T) { } func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) { - data, err := ioutil.ReadFile(filepath.Join("testdata", fileName)) + data, err := os.ReadFile(filepath.Join("testdata", fileName)) if err != nil { panic("Error reading " + fileName + ": " + err.Error()) } @@ -792,17 +791,17 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) { // // func main() { // bigZip := makeZip("big.file", io.LimitReader(zeros{}, 1<<32-1)) -// if err := ioutil.WriteFile("/tmp/big.zip", bigZip, 0666); err != nil { +// if err := os.WriteFile("/tmp/big.zip", bigZip, 0666); err != nil { // log.Fatal(err) // } // // biggerZip := makeZip("big.zip", bytes.NewReader(bigZip)) -// if err := ioutil.WriteFile("/tmp/bigger.zip", biggerZip, 0666); err != nil { +// if err := os.WriteFile("/tmp/bigger.zip", biggerZip, 0666); err != nil { // log.Fatal(err) // } // // biggestZip := makeZip("bigger.zip", bytes.NewReader(biggerZip)) -// if err := ioutil.WriteFile("/tmp/biggest.zip", biggestZip, 0666); err != nil { +// if err := os.WriteFile("/tmp/biggest.zip", biggestZip, 0666); err != nil { // log.Fatal(err) // } // } diff --git a/src/archive/zip/writer_test.go b/src/archive/zip/writer_test.go index 2c32eaf4a5..5985144e5c 100644 --- a/src/archive/zip/writer_test.go +++ b/src/archive/zip/writer_test.go @@ -10,8 +10,8 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "math/rand" + "os" "strings" "testing" "time" @@ -237,7 +237,7 @@ func TestWriterTime(t *testing.T) { t.Fatalf("unexpected Close error: %v", err) } - want, err := ioutil.ReadFile("testdata/time-go.zip") + want, err := os.ReadFile("testdata/time-go.zip") if err != nil { t.Fatalf("unexpected ReadFile error: %v", err) } diff --git a/src/cmd/addr2line/addr2line_test.go b/src/cmd/addr2line/addr2line_test.go index 7973aa2fe1..992d7ac11e 100644 --- a/src/cmd/addr2line/addr2line_test.go +++ b/src/cmd/addr2line/addr2line_test.go @@ -8,7 +8,6 @@ import ( "bufio" "bytes" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -98,8 +97,8 @@ func testAddr2Line(t *testing.T, exepath, addr string) { if !os.SameFile(fi1, fi2) { t.Fatalf("addr2line_test.go and %s are not same file", srcPath) } - if srcLineNo != "107" { - t.Fatalf("line number = %v; want 107", srcLineNo) + if srcLineNo != "106" { + t.Fatalf("line number = %v; want 106", srcLineNo) } } @@ -107,7 +106,7 @@ func testAddr2Line(t *testing.T, exepath, addr string) { func TestAddr2Line(t *testing.T) { testenv.MustHaveGoBuild(t) - tmpDir, err := ioutil.TempDir("", "TestAddr2Line") + tmpDir, err := os.MkdirTemp("", "TestAddr2Line") if err != nil { t.Fatal("TempDir failed: ", err) } diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index b14d57c236..ba42812fa6 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -17,7 +17,6 @@ import ( "go/token" "go/types" "io" - "io/ioutil" "log" "os" "os/exec" @@ -342,7 +341,7 @@ func fileFeatures(filename string) []string { if filename == "" { return nil } - bs, err := ioutil.ReadFile(filename) + bs, err := os.ReadFile(filename) if err != nil { log.Fatalf("Error reading file %s: %v", filename, err) } diff --git a/src/cmd/api/goapi_test.go b/src/cmd/api/goapi_test.go index 24620a94af..16e0058e5e 100644 --- a/src/cmd/api/goapi_test.go +++ b/src/cmd/api/goapi_test.go @@ -9,7 +9,6 @@ import ( "flag" "fmt" "go/build" - "io/ioutil" "os" "path/filepath" "sort" @@ -75,7 +74,7 @@ func TestGolden(t *testing.T) { f.Close() } - bs, err := ioutil.ReadFile(goldenFile) + bs, err := os.ReadFile(goldenFile) if err != nil { t.Fatalf("opening golden.txt for package %q: %v", fi.Name(), err) } diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go index 360f9aeb06..7ee000861b 100644 --- a/src/cmd/cover/cover.go +++ b/src/cmd/cover/cover.go @@ -12,7 +12,6 @@ import ( "go/parser" "go/token" "io" - "io/ioutil" "log" "os" "sort" @@ -304,7 +303,7 @@ func (f *File) Visit(node ast.Node) ast.Visitor { func annotate(name string) { fset := token.NewFileSet() - content, err := ioutil.ReadFile(name) + content, err := os.ReadFile(name) if err != nil { log.Fatalf("cover: %s: %s", name, err) } diff --git a/src/cmd/cover/cover_test.go b/src/cmd/cover/cover_test.go index 1c252e6e45..86c95d15c5 100644 --- a/src/cmd/cover/cover_test.go +++ b/src/cmd/cover/cover_test.go @@ -13,7 +13,6 @@ import ( "go/parser" "go/token" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -81,7 +80,7 @@ var debug = flag.Bool("debug", false, "keep rewritten files for debugging") // We use TestMain to set up a temporary directory and remove it when // the tests are done. func TestMain(m *testing.M) { - dir, err := ioutil.TempDir("", "go-testcover") + dir, err := os.MkdirTemp("", "go-testcover") if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) @@ -173,7 +172,7 @@ func TestCover(t *testing.T) { buildCover(t) // Read in the test file (testTest) and write it, with LINEs specified, to coverInput. - file, err := ioutil.ReadFile(testTest) + file, err := os.ReadFile(testTest) if err != nil { t.Fatal(err) } @@ -192,7 +191,7 @@ func TestCover(t *testing.T) { []byte("}")) lines = append(lines, []byte("func unFormatted2(b bool) {if b{}else{}}")) - if err := ioutil.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666); err != nil { + if err := os.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666); err != nil { t.Fatal(err) } @@ -208,11 +207,11 @@ func TestCover(t *testing.T) { // Copy testmain to testTempDir, so that it is in the same directory // as coverOutput. - b, err := ioutil.ReadFile(testMain) + b, err := os.ReadFile(testMain) if err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(tmpTestMain, b, 0444); err != nil { + if err := os.WriteFile(tmpTestMain, b, 0444); err != nil { t.Fatal(err) } @@ -220,7 +219,7 @@ func TestCover(t *testing.T) { cmd = exec.Command(testenv.GoToolPath(t), "run", tmpTestMain, coverOutput) run(cmd, t) - file, err = ioutil.ReadFile(coverOutput) + file, err = os.ReadFile(coverOutput) if err != nil { t.Fatal(err) } @@ -251,7 +250,7 @@ func TestDirectives(t *testing.T) { // Read the source file and find all the directives. We'll keep // track of whether each one has been seen in the output. testDirectives := filepath.Join(testdata, "directives.go") - source, err := ioutil.ReadFile(testDirectives) + source, err := os.ReadFile(testDirectives) if err != nil { t.Fatal(err) } @@ -398,7 +397,7 @@ func TestCoverHTML(t *testing.T) { // Extract the parts of the HTML with comment markers, // and compare against a golden file. - entireHTML, err := ioutil.ReadFile(htmlHTML) + entireHTML, err := os.ReadFile(htmlHTML) if err != nil { t.Fatal(err) } @@ -420,7 +419,7 @@ func TestCoverHTML(t *testing.T) { if scan.Err() != nil { t.Error(scan.Err()) } - golden, err := ioutil.ReadFile(htmlGolden) + golden, err := os.ReadFile(htmlGolden) if err != nil { t.Fatalf("reading golden file: %v", err) } @@ -457,7 +456,7 @@ func TestHtmlUnformatted(t *testing.T) { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(htmlUDir, "go.mod"), []byte("module htmlunformatted\n"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(htmlUDir, "go.mod"), []byte("module htmlunformatted\n"), 0666); err != nil { t.Fatal(err) } @@ -474,10 +473,10 @@ lab: const htmlUTestContents = `package htmlunformatted` - if err := ioutil.WriteFile(htmlU, []byte(htmlUContents), 0444); err != nil { + if err := os.WriteFile(htmlU, []byte(htmlUContents), 0444); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(htmlUTest, []byte(htmlUTestContents), 0444); err != nil { + if err := os.WriteFile(htmlUTest, []byte(htmlUTestContents), 0444); err != nil { t.Fatal(err) } @@ -540,13 +539,13 @@ func TestFuncWithDuplicateLines(t *testing.T) { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(lineDupDir, "go.mod"), []byte("module linedup\n"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(lineDupDir, "go.mod"), []byte("module linedup\n"), 0666); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(lineDupGo, []byte(lineDupContents), 0444); err != nil { + if err := os.WriteFile(lineDupGo, []byte(lineDupContents), 0444); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(lineDupTestGo, []byte(lineDupTestContents), 0444); err != nil { + if err := os.WriteFile(lineDupTestGo, []byte(lineDupTestContents), 0444); err != nil { t.Fatal(err) } diff --git a/src/cmd/cover/html.go b/src/cmd/cover/html.go index f76ea03cf5..b2865c427c 100644 --- a/src/cmd/cover/html.go +++ b/src/cmd/cover/html.go @@ -11,7 +11,6 @@ import ( "fmt" "html/template" "io" - "io/ioutil" "math" "os" "path/filepath" @@ -43,7 +42,7 @@ func htmlOutput(profile, outfile string) error { if err != nil { return err } - src, err := ioutil.ReadFile(file) + src, err := os.ReadFile(file) if err != nil { return fmt.Errorf("can't read %q: %v", fn, err) } @@ -62,7 +61,7 @@ func htmlOutput(profile, outfile string) error { var out *os.File if outfile == "" { var dir string - dir, err = ioutil.TempDir("", "cover") + dir, err = os.MkdirTemp("", "cover") if err != nil { return err } diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go index 1cedf992cf..d055929aac 100644 --- a/src/cmd/fix/main.go +++ b/src/cmd/fix/main.go @@ -15,7 +15,6 @@ import ( "go/token" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "sort" @@ -217,7 +216,7 @@ func processFile(filename string, useStdin bool) error { return nil } - return ioutil.WriteFile(f.Name(), newSrc, 0) + return os.WriteFile(f.Name(), newSrc, 0) } func gofmt(n interface{}) string { diff --git a/src/cmd/fix/typecheck.go b/src/cmd/fix/typecheck.go index f45155b06d..40b2287f26 100644 --- a/src/cmd/fix/typecheck.go +++ b/src/cmd/fix/typecheck.go @@ -9,7 +9,6 @@ import ( "go/ast" "go/parser" "go/token" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -162,12 +161,12 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass if err != nil { return err } - dir, err := ioutil.TempDir(os.TempDir(), "fix_cgo_typecheck") + dir, err := os.MkdirTemp(os.TempDir(), "fix_cgo_typecheck") if err != nil { return err } defer os.RemoveAll(dir) - err = ioutil.WriteFile(filepath.Join(dir, "in.go"), txt, 0600) + err = os.WriteFile(filepath.Join(dir, "in.go"), txt, 0600) if err != nil { return err } @@ -176,7 +175,7 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass if err != nil { return err } - out, err := ioutil.ReadFile(filepath.Join(dir, "_cgo_gotypes.go")) + out, err := os.ReadFile(filepath.Join(dir, "_cgo_gotypes.go")) if err != nil { return err } diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 1b8a21ecfa..19764bfc60 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -17,7 +17,6 @@ import ( "internal/testenv" "io" "io/fs" - "io/ioutil" "log" "os" "os/exec" @@ -100,7 +99,7 @@ func TestMain(m *testing.M) { // Run with a temporary TMPDIR to check that the tests don't // leave anything behind. - topTmpdir, err := ioutil.TempDir("", "cmd-go-test-") + topTmpdir, err := os.MkdirTemp("", "cmd-go-test-") if err != nil { log.Fatal(err) } @@ -109,7 +108,7 @@ func TestMain(m *testing.M) { } os.Setenv(tempEnvName(), topTmpdir) - dir, err := ioutil.TempDir(topTmpdir, "tmpdir") + dir, err := os.MkdirTemp(topTmpdir, "tmpdir") if err != nil { log.Fatal(err) } @@ -616,7 +615,7 @@ func (tg *testgoData) makeTempdir() { tg.t.Helper() if tg.tempdir == "" { var err error - tg.tempdir, err = ioutil.TempDir("", "gotest") + tg.tempdir, err = os.MkdirTemp("", "gotest") tg.must(err) } } @@ -633,7 +632,7 @@ func (tg *testgoData) tempFile(path, contents string) { bytes = formatted } } - tg.must(ioutil.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644)) + tg.must(os.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644)) } // tempDir adds a temporary directory for a run of testgo. @@ -833,7 +832,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { return err } dest := filepath.Join("goroot", copydir, srcrel) - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return err } @@ -850,18 +849,18 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { tg.setenv("GOROOT", tg.path("goroot")) addVar := func(name string, idx int) (restore func()) { - data, err := ioutil.ReadFile(name) + data, err := os.ReadFile(name) if err != nil { t.Fatal(err) } old := data data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...) - if err := ioutil.WriteFile(name, append(data, '\n'), 0666); err != nil { + if err := os.WriteFile(name, append(data, '\n'), 0666); err != nil { t.Fatal(err) } tg.sleep() return func() { - if err := ioutil.WriteFile(name, old, 0666); err != nil { + if err := os.WriteFile(name, old, 0666); err != nil { t.Fatal(err) } } @@ -2674,7 +2673,7 @@ echo $* >>`+tg.path("pkg-config.out")) tg.setenv("GOPATH", tg.path(".")) tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh")) tg.run("build", "x") - out, err := ioutil.ReadFile(tg.path("pkg-config.out")) + out, err := os.ReadFile(tg.path("pkg-config.out")) tg.must(err) out = bytes.TrimSpace(out) want := "--cflags --static --static -- a a\n--libs --static --static -- a a" diff --git a/src/cmd/go/go_windows_test.go b/src/cmd/go/go_windows_test.go index 02634f19f5..3094212bae 100644 --- a/src/cmd/go/go_windows_test.go +++ b/src/cmd/go/go_windows_test.go @@ -5,7 +5,6 @@ package main_test import ( - "io/ioutil" "os" "os/exec" "path/filepath" @@ -20,14 +19,14 @@ func TestAbsolutePath(t *testing.T) { defer tg.cleanup() tg.parallel() - tmp, err := ioutil.TempDir("", "TestAbsolutePath") + tmp, err := os.MkdirTemp("", "TestAbsolutePath") if err != nil { t.Fatal(err) } defer robustio.RemoveAll(tmp) file := filepath.Join(tmp, "a.go") - err = ioutil.WriteFile(file, []byte{}, 0644) + err = os.WriteFile(file, []byte{}, 0644) if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/help_test.go b/src/cmd/go/help_test.go index 78d63ff05e..abfc3db993 100644 --- a/src/cmd/go/help_test.go +++ b/src/cmd/go/help_test.go @@ -6,7 +6,7 @@ package main_test import ( "bytes" - "io/ioutil" + "os" "testing" "cmd/go/internal/help" @@ -23,7 +23,7 @@ func TestDocsUpToDate(t *testing.T) { buf := new(bytes.Buffer) // Match the command in mkalldocs.sh that generates alldocs.go. help.Help(buf, []string{"documentation"}) - data, err := ioutil.ReadFile("alldocs.go") + data, err := os.ReadFile("alldocs.go") if err != nil { t.Fatalf("error reading alldocs.go: %v", err) } diff --git a/src/cmd/go/internal/auth/netrc.go b/src/cmd/go/internal/auth/netrc.go index 7a9bdbb72c..0107f20d7a 100644 --- a/src/cmd/go/internal/auth/netrc.go +++ b/src/cmd/go/internal/auth/netrc.go @@ -5,7 +5,6 @@ package auth import ( - "io/ioutil" "os" "path/filepath" "runtime" @@ -99,7 +98,7 @@ func readNetrc() { return } - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { if !os.IsNotExist(err) { netrcErr = err diff --git a/src/cmd/go/internal/bug/bug.go b/src/cmd/go/internal/bug/bug.go index 07e3516855..1085feaaee 100644 --- a/src/cmd/go/internal/bug/bug.go +++ b/src/cmd/go/internal/bug/bug.go @@ -10,7 +10,6 @@ import ( "context" "fmt" "io" - "io/ioutil" urlpkg "net/url" "os" "os/exec" @@ -117,7 +116,7 @@ func printOSDetails(w io.Writer) { case "illumos", "solaris": // Be sure to use the OS-supplied uname, in "/usr/bin": printCmdOut(w, "uname -srv: ", "/usr/bin/uname", "-srv") - out, err := ioutil.ReadFile("/etc/release") + out, err := os.ReadFile("/etc/release") if err == nil { fmt.Fprintf(w, "/etc/release: %s\n", out) } else { @@ -177,7 +176,7 @@ func printGlibcVersion(w io.Writer) { src := []byte(`int main() {}`) srcfile := filepath.Join(tempdir, "go-bug.c") outfile := filepath.Join(tempdir, "go-bug") - err := ioutil.WriteFile(srcfile, src, 0644) + err := os.WriteFile(srcfile, src, 0644) if err != nil { return } diff --git a/src/cmd/go/internal/cache/cache.go b/src/cmd/go/internal/cache/cache.go index 5464fe5685..41f921641d 100644 --- a/src/cmd/go/internal/cache/cache.go +++ b/src/cmd/go/internal/cache/cache.go @@ -13,7 +13,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "strconv" @@ -239,7 +238,7 @@ func (c *Cache) GetBytes(id ActionID) ([]byte, Entry, error) { if err != nil { return nil, entry, err } - data, _ := ioutil.ReadFile(c.OutputFile(entry.OutputID)) + data, _ := os.ReadFile(c.OutputFile(entry.OutputID)) if sha256.Sum256(data) != entry.OutputID { return nil, entry, &entryNotFoundError{Err: errors.New("bad checksum")} } @@ -378,7 +377,7 @@ func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify // Truncate the file only *after* writing it. // (This should be a no-op, but truncate just in case of previous corruption.) // - // This differs from ioutil.WriteFile, which truncates to 0 *before* writing + // This differs from os.WriteFile, which truncates to 0 *before* writing // via os.O_TRUNC. Truncating only after writing ensures that a second write // of the same content to the same file is idempotent, and does not — even // temporarily! — undo the effect of the first write. diff --git a/src/cmd/go/internal/cache/cache_test.go b/src/cmd/go/internal/cache/cache_test.go index 1988c34502..a865b97018 100644 --- a/src/cmd/go/internal/cache/cache_test.go +++ b/src/cmd/go/internal/cache/cache_test.go @@ -8,7 +8,6 @@ import ( "bytes" "encoding/binary" "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -20,7 +19,7 @@ func init() { } func TestBasic(t *testing.T) { - dir, err := ioutil.TempDir("", "cachetest-") + dir, err := os.MkdirTemp("", "cachetest-") if err != nil { t.Fatal(err) } @@ -65,7 +64,7 @@ func TestBasic(t *testing.T) { } func TestGrowth(t *testing.T) { - dir, err := ioutil.TempDir("", "cachetest-") + dir, err := os.MkdirTemp("", "cachetest-") if err != nil { t.Fatal(err) } @@ -118,7 +117,7 @@ func TestVerifyPanic(t *testing.T) { t.Fatal("initEnv did not set verify") } - dir, err := ioutil.TempDir("", "cachetest-") + dir, err := os.MkdirTemp("", "cachetest-") if err != nil { t.Fatal(err) } @@ -151,7 +150,7 @@ func dummyID(x int) [HashSize]byte { } func TestCacheTrim(t *testing.T) { - dir, err := ioutil.TempDir("", "cachetest-") + dir, err := os.MkdirTemp("", "cachetest-") if err != nil { t.Fatal(err) } @@ -207,7 +206,7 @@ func TestCacheTrim(t *testing.T) { t.Fatal(err) } c.OutputFile(entry.OutputID) - data, err := ioutil.ReadFile(filepath.Join(dir, "trim.txt")) + data, err := os.ReadFile(filepath.Join(dir, "trim.txt")) if err != nil { t.Fatal(err) } @@ -220,7 +219,7 @@ func TestCacheTrim(t *testing.T) { t.Fatal(err) } c.OutputFile(entry.OutputID) - data2, err := ioutil.ReadFile(filepath.Join(dir, "trim.txt")) + data2, err := os.ReadFile(filepath.Join(dir, "trim.txt")) if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/cache/default.go b/src/cmd/go/internal/cache/default.go index 9f8dd8af4b..0b1c1e0c20 100644 --- a/src/cmd/go/internal/cache/default.go +++ b/src/cmd/go/internal/cache/default.go @@ -6,7 +6,6 @@ package cache import ( "fmt" - "io/ioutil" "os" "path/filepath" "sync" @@ -49,7 +48,7 @@ func initDefaultCache() { } if _, err := os.Stat(filepath.Join(dir, "README")); err != nil { // Best effort. - ioutil.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666) + os.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666) } c, err := Open(dir) diff --git a/src/cmd/go/internal/cache/hash_test.go b/src/cmd/go/internal/cache/hash_test.go index 3bf7143039..a0356771ca 100644 --- a/src/cmd/go/internal/cache/hash_test.go +++ b/src/cmd/go/internal/cache/hash_test.go @@ -6,7 +6,6 @@ package cache import ( "fmt" - "io/ioutil" "os" "testing" ) @@ -28,7 +27,7 @@ func TestHash(t *testing.T) { } func TestHashFile(t *testing.T) { - f, err := ioutil.TempFile("", "cmd-go-test-") + f, err := os.CreateTemp("", "cmd-go-test-") if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 9bc48132ae..c48904eacc 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -12,7 +12,6 @@ import ( "go/build" "internal/cfg" "io" - "io/ioutil" "os" "path/filepath" "runtime" @@ -187,7 +186,7 @@ func initEnvCache() { if file == "" { return } - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) if err != nil { return } diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 46af36eb11..6937187522 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -10,7 +10,6 @@ import ( "encoding/json" "fmt" "go/build" - "io/ioutil" "os" "path/filepath" "runtime" @@ -452,7 +451,7 @@ func updateEnvFile(add map[string]string, del map[string]bool) { if file == "" { base.Fatalf("go env: cannot find go env config: %v", err) } - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) if err != nil && (!os.IsNotExist(err) || len(add) == 0) { base.Fatalf("go env: reading go env config: %v", err) } @@ -506,11 +505,11 @@ func updateEnvFile(add map[string]string, del map[string]bool) { } data = []byte(strings.Join(lines, "")) - err = ioutil.WriteFile(file, data, 0666) + err = os.WriteFile(file, data, 0666) if err != nil { // Try creating directory. os.MkdirAll(filepath.Dir(file), 0777) - err = ioutil.WriteFile(file, data, 0666) + err = os.WriteFile(file, data, 0666) if err != nil { base.Fatalf("go env: writing go env config: %v", err) } diff --git a/src/cmd/go/internal/fsys/fsys.go b/src/cmd/go/internal/fsys/fsys.go index 0264786e5b..7b06c3c7f3 100644 --- a/src/cmd/go/internal/fsys/fsys.go +++ b/src/cmd/go/internal/fsys/fsys.go @@ -86,7 +86,7 @@ func Init(wd string) error { return nil } - b, err := ioutil.ReadFile(OverlayFile) + b, err := os.ReadFile(OverlayFile) if err != nil { return fmt.Errorf("reading overlay file: %v", err) } diff --git a/src/cmd/go/internal/fsys/fsys_test.go b/src/cmd/go/internal/fsys/fsys_test.go index 90a69de14a..7f175c7031 100644 --- a/src/cmd/go/internal/fsys/fsys_test.go +++ b/src/cmd/go/internal/fsys/fsys_test.go @@ -8,7 +8,6 @@ import ( "internal/testenv" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "reflect" @@ -47,7 +46,7 @@ func initOverlay(t *testing.T, config string) { if err := os.MkdirAll(filepath.Dir(name), 0777); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(name, f.Data, 0666); err != nil { + if err := os.WriteFile(name, f.Data, 0666); err != nil { t.Fatal(err) } } diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go index 98c17bba8c..c7401948b8 100644 --- a/src/cmd/go/internal/generate/generate.go +++ b/src/cmd/go/internal/generate/generate.go @@ -13,7 +13,6 @@ import ( "go/parser" "go/token" "io" - "io/ioutil" "log" "os" "os/exec" @@ -201,7 +200,7 @@ func runGenerate(ctx context.Context, cmd *base.Command, args []string) { // generate runs the generation directives for a single file. func generate(absFile string) bool { - src, err := ioutil.ReadFile(absFile) + src, err := os.ReadFile(absFile) if err != nil { log.Fatalf("generate: %s", err) } diff --git a/src/cmd/go/internal/imports/scan_test.go b/src/cmd/go/internal/imports/scan_test.go index e424656cae..5ba3201968 100644 --- a/src/cmd/go/internal/imports/scan_test.go +++ b/src/cmd/go/internal/imports/scan_test.go @@ -8,6 +8,7 @@ import ( "bytes" "internal/testenv" "io/ioutil" + "os" "path" "path/filepath" "runtime" @@ -66,7 +67,7 @@ func TestScanDir(t *testing.T) { continue } t.Run(dir.Name(), func(t *testing.T) { - tagsData, err := ioutil.ReadFile(filepath.Join("testdata", dir.Name(), "tags.txt")) + tagsData, err := os.ReadFile(filepath.Join("testdata", dir.Name(), "tags.txt")) if err != nil { t.Fatalf("error reading tags: %v", err) } @@ -75,7 +76,7 @@ func TestScanDir(t *testing.T) { tags[t] = true } - wantData, err := ioutil.ReadFile(filepath.Join("testdata", dir.Name(), "want.txt")) + wantData, err := os.ReadFile(filepath.Join("testdata", dir.Name(), "want.txt")) if err != nil { t.Fatalf("error reading want: %v", err) } diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index cbc683da2b..da3e0b895c 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -1147,7 +1147,7 @@ var ( // goModPath returns the module path in the go.mod in dir, if any. func goModPath(dir string) (path string) { return goModPathCache.Do(dir, func() interface{} { - data, err := ioutil.ReadFile(filepath.Join(dir, "go.mod")) + data, err := os.ReadFile(filepath.Join(dir, "go.mod")) if err != nil { return "" } @@ -1728,7 +1728,7 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor // not work for any package that lacks a Target — such as a non-main // package in module mode. We should probably fix that. shlibnamefile := p.Target[:len(p.Target)-2] + ".shlibname" - shlib, err := ioutil.ReadFile(shlibnamefile) + shlib, err := os.ReadFile(shlibnamefile) if err != nil && !os.IsNotExist(err) { base.Fatalf("reading shlibname: %v", err) } diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go index 8301fb6b6e..2ac2052b8f 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go @@ -9,7 +9,6 @@ package filelock_test import ( "fmt" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -51,9 +50,9 @@ func mustTempFile(t *testing.T) (f *os.File, remove func()) { t.Helper() base := filepath.Base(t.Name()) - f, err := ioutil.TempFile("", base) + f, err := os.CreateTemp("", base) if err != nil { - t.Fatalf(`ioutil.TempFile("", %q) = %v`, base, err) + t.Fatalf(`os.CreateTemp("", %q) = %v`, base, err) } t.Logf("fd %d = %s", f.Fd(), f.Name()) diff --git a/src/cmd/go/internal/lockedfile/lockedfile_test.go b/src/cmd/go/internal/lockedfile/lockedfile_test.go index 416c69d83b..34327dd841 100644 --- a/src/cmd/go/internal/lockedfile/lockedfile_test.go +++ b/src/cmd/go/internal/lockedfile/lockedfile_test.go @@ -10,7 +10,6 @@ package lockedfile_test import ( "fmt" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -23,7 +22,7 @@ import ( func mustTempDir(t *testing.T) (dir string, remove func()) { t.Helper() - dir, err := ioutil.TempDir("", filepath.Base(t.Name())) + dir, err := os.MkdirTemp("", filepath.Base(t.Name())) if err != nil { t.Fatal(err) } @@ -155,8 +154,8 @@ func TestCanLockExistingFile(t *testing.T) { defer remove() path := filepath.Join(dir, "existing.txt") - if err := ioutil.WriteFile(path, []byte("ok"), 0777); err != nil { - t.Fatalf("ioutil.WriteFile: %v", err) + if err := os.WriteFile(path, []byte("ok"), 0777); err != nil { + t.Fatalf("os.WriteFile: %v", err) } f, err := lockedfile.Edit(path) @@ -201,7 +200,7 @@ func TestSpuriousEDEADLK(t *testing.T) { } defer b.Close() - if err := ioutil.WriteFile(filepath.Join(dir, "locked"), []byte("ok"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(dir, "locked"), []byte("ok"), 0666); err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 38c473d36b..390a195547 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -155,7 +155,7 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go mod vendor: %v", err) } - if err := ioutil.WriteFile(filepath.Join(vdir, "modules.txt"), buf.Bytes(), 0666); err != nil { + if err := os.WriteFile(filepath.Join(vdir, "modules.txt"), buf.Bytes(), 0666); err != nil { base.Fatalf("go mod vendor: %v", err) } } diff --git a/src/cmd/go/internal/modcmd/verify.go b/src/cmd/go/internal/modcmd/verify.go index ce24793929..c83e70076a 100644 --- a/src/cmd/go/internal/modcmd/verify.go +++ b/src/cmd/go/internal/modcmd/verify.go @@ -10,7 +10,6 @@ import ( "errors" "fmt" "io/fs" - "io/ioutil" "os" "runtime" @@ -87,7 +86,7 @@ func verifyMod(mod module.Version) []error { _, zipErr = os.Stat(zip) } dir, dirErr := modfetch.DownloadDir(mod) - data, err := ioutil.ReadFile(zip + "hash") + data, err := os.ReadFile(zip + "hash") if err != nil { if zipErr != nil && errors.Is(zipErr, fs.ErrNotExist) && dirErr != nil && errors.Is(dirErr, fs.ErrNotExist) { diff --git a/src/cmd/go/internal/modconv/convert_test.go b/src/cmd/go/internal/modconv/convert_test.go index faa2b4c606..66b9ff4f38 100644 --- a/src/cmd/go/internal/modconv/convert_test.go +++ b/src/cmd/go/internal/modconv/convert_test.go @@ -9,7 +9,6 @@ import ( "context" "fmt" "internal/testenv" - "io/ioutil" "log" "os" "os/exec" @@ -37,7 +36,7 @@ func testMain(m *testing.M) int { return 0 } - dir, err := ioutil.TempDir("", "modconv-test-") + dir, err := os.MkdirTemp("", "modconv-test-") if err != nil { log.Fatal(err) } @@ -167,7 +166,7 @@ func TestConvertLegacyConfig(t *testing.T) { for name := range Converters { file := filepath.Join(dir, name) - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) if err == nil { f := new(modfile.File) f.AddModuleStmt(tt.path) diff --git a/src/cmd/go/internal/modconv/modconv_test.go b/src/cmd/go/internal/modconv/modconv_test.go index ccc4f3d576..750525d404 100644 --- a/src/cmd/go/internal/modconv/modconv_test.go +++ b/src/cmd/go/internal/modconv/modconv_test.go @@ -7,7 +7,7 @@ package modconv import ( "bytes" "fmt" - "io/ioutil" + "os" "path/filepath" "testing" ) @@ -42,7 +42,7 @@ func Test(t *testing.T) { if Converters[extMap[ext]] == nil { t.Fatalf("Converters[%q] == nil", extMap[ext]) } - data, err := ioutil.ReadFile(test) + data, err := os.ReadFile(test) if err != nil { t.Fatal(err) } @@ -50,7 +50,7 @@ func Test(t *testing.T) { if err != nil { t.Fatal(err) } - want, err := ioutil.ReadFile(test[:len(test)-len(ext)] + ".out") + want, err := os.ReadFile(test[:len(test)-len(ext)] + ".out") if err != nil { t.Error(err) } diff --git a/src/cmd/go/internal/modfetch/cache_test.go b/src/cmd/go/internal/modfetch/cache_test.go index 241c800e69..722c984e37 100644 --- a/src/cmd/go/internal/modfetch/cache_test.go +++ b/src/cmd/go/internal/modfetch/cache_test.go @@ -5,14 +5,13 @@ package modfetch import ( - "io/ioutil" "os" "path/filepath" "testing" ) func TestWriteDiskCache(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "go-writeCache-test-") + tmpdir, err := os.MkdirTemp("", "go-writeCache-test-") if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go index 286d3f7220..86c1c14d4a 100644 --- a/src/cmd/go/internal/modfetch/codehost/codehost.go +++ b/src/cmd/go/internal/modfetch/codehost/codehost.go @@ -12,7 +12,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -189,7 +188,7 @@ func WorkDir(typ, name string) (dir, lockfile string, err error) { } defer unlock() - data, err := ioutil.ReadFile(dir + ".info") + data, err := os.ReadFile(dir + ".info") info, err2 := os.Stat(dir) if err == nil && err2 == nil && info.IsDir() { // Info file and directory both already exist: reuse. @@ -211,7 +210,7 @@ func WorkDir(typ, name string) (dir, lockfile string, err error) { if err := os.MkdirAll(dir, 0777); err != nil { return "", "", err } - if err := ioutil.WriteFile(dir+".info", []byte(key), 0666); err != nil { + if err := os.WriteFile(dir+".info", []byte(key), 0666); err != nil { os.RemoveAll(dir) return "", "", err } diff --git a/src/cmd/go/internal/modfetch/codehost/git_test.go b/src/cmd/go/internal/modfetch/codehost/git_test.go index 981e3fe91f..89a73baad9 100644 --- a/src/cmd/go/internal/modfetch/codehost/git_test.go +++ b/src/cmd/go/internal/modfetch/codehost/git_test.go @@ -12,7 +12,6 @@ import ( "internal/testenv" "io" "io/fs" - "io/ioutil" "log" "os" "os/exec" @@ -54,7 +53,7 @@ func testMain(m *testing.M) int { return 0 } - dir, err := ioutil.TempDir("", "gitrepo-test-") + dir, err := os.MkdirTemp("", "gitrepo-test-") if err != nil { log.Fatal(err) } diff --git a/src/cmd/go/internal/modfetch/codehost/shell.go b/src/cmd/go/internal/modfetch/codehost/shell.go index b9525adf5e..ce8b501d53 100644 --- a/src/cmd/go/internal/modfetch/codehost/shell.go +++ b/src/cmd/go/internal/modfetch/codehost/shell.go @@ -15,7 +15,6 @@ import ( "flag" "fmt" "io" - "io/ioutil" "log" "os" "strings" @@ -124,7 +123,7 @@ func main() { } if f[3] != "-" { - if err := ioutil.WriteFile(f[3], data, 0666); err != nil { + if err := os.WriteFile(f[3], data, 0666); err != nil { fmt.Fprintf(os.Stderr, "?%s\n", err) continue } diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index e67ee94ad8..c2cca084e3 100644 --- a/src/cmd/go/internal/modfetch/codehost/vcs.go +++ b/src/cmd/go/internal/modfetch/codehost/vcs.go @@ -10,7 +10,6 @@ import ( "internal/lazyregexp" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "sort" @@ -433,7 +432,7 @@ func (r *vcsRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, if rev == "latest" { rev = r.cmd.latest } - f, err := ioutil.TempFile("", "go-readzip-*.zip") + f, err := os.CreateTemp("", "go-readzip-*.zip") if err != nil { return nil, err } diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go index b6bcf83f1a..2dcbb99b18 100644 --- a/src/cmd/go/internal/modfetch/coderepo.go +++ b/src/cmd/go/internal/modfetch/coderepo.go @@ -11,7 +11,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "os" "path" "sort" @@ -966,7 +965,7 @@ func (r *codeRepo) Zip(dst io.Writer, version string) error { subdir = strings.Trim(subdir, "/") // Spool to local file. - f, err := ioutil.TempFile("", "go-codehost-") + f, err := os.CreateTemp("", "go-codehost-") if err != nil { dl.Close() return err diff --git a/src/cmd/go/internal/modfetch/coderepo_test.go b/src/cmd/go/internal/modfetch/coderepo_test.go index 53b048dbdf..02e399f352 100644 --- a/src/cmd/go/internal/modfetch/coderepo_test.go +++ b/src/cmd/go/internal/modfetch/coderepo_test.go @@ -11,7 +11,6 @@ import ( "hash" "internal/testenv" "io" - "io/ioutil" "log" "os" "reflect" @@ -38,7 +37,7 @@ func testMain(m *testing.M) int { // code, bypass the sum database. cfg.GOSUMDB = "off" - dir, err := ioutil.TempDir("", "gitrepo-test-") + dir, err := os.MkdirTemp("", "gitrepo-test-") if err != nil { log.Fatal(err) } @@ -424,7 +423,7 @@ var codeRepoTests = []codeRepoTest{ func TestCodeRepo(t *testing.T) { testenv.MustHaveExternalNetwork(t) - tmpdir, err := ioutil.TempDir("", "modfetch-test-") + tmpdir, err := os.MkdirTemp("", "modfetch-test-") if err != nil { t.Fatal(err) } @@ -491,9 +490,9 @@ func TestCodeRepo(t *testing.T) { needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "") if tt.zip != nil || tt.zipErr != "" || needHash { - f, err := ioutil.TempFile(tmpdir, tt.version+".zip.") + f, err := os.CreateTemp(tmpdir, tt.version+".zip.") if err != nil { - t.Fatalf("ioutil.TempFile: %v", err) + t.Fatalf("os.CreateTemp: %v", err) } zipfile := f.Name() defer func() { @@ -655,7 +654,7 @@ var codeRepoVersionsTests = []struct { func TestCodeRepoVersions(t *testing.T) { testenv.MustHaveExternalNetwork(t) - tmpdir, err := ioutil.TempDir("", "vgo-modfetch-test-") + tmpdir, err := os.MkdirTemp("", "vgo-modfetch-test-") if err != nil { t.Fatal(err) } @@ -729,7 +728,7 @@ var latestTests = []struct { func TestLatest(t *testing.T) { testenv.MustHaveExternalNetwork(t) - tmpdir, err := ioutil.TempDir("", "vgo-modfetch-test-") + tmpdir, err := os.MkdirTemp("", "vgo-modfetch-test-") if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index 2ee78de5b2..debeb3f319 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -12,7 +12,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "sort" @@ -136,7 +135,7 @@ func download(ctx context.Context, mod module.Version) (dir string, err error) { if err := os.MkdirAll(parentDir, 0777); err != nil { return "", err } - if err := ioutil.WriteFile(partialPath, nil, 0666); err != nil { + if err := os.WriteFile(partialPath, nil, 0666); err != nil { return "", err } if err := modzip.Unzip(dir, mod, zipfile); err != nil { @@ -223,7 +222,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e // contents of the file (by hashing it) before we commit it. Because the file // is zip-compressed, we need an actual file — or at least an io.ReaderAt — to // validate it: we can't just tee the stream as we write it. - f, err := ioutil.TempFile(filepath.Dir(zipfile), filepath.Base(renameio.Pattern(zipfile))) + f, err := os.CreateTemp(filepath.Dir(zipfile), filepath.Base(renameio.Pattern(zipfile))) if err != nil { return err } diff --git a/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go b/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go index 82398ebfed..d9ba8ef2da 100644 --- a/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go +++ b/src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go @@ -24,7 +24,6 @@ import ( "fmt" "internal/testenv" "io" - "io/ioutil" "os" "path/filepath" "strings" @@ -81,7 +80,7 @@ func TestZipSums(t *testing.T) { if *modCacheDir != "" { cfg.BuildContext.GOPATH = *modCacheDir } else { - tmpDir, err := ioutil.TempDir("", "TestZipSums") + tmpDir, err := os.MkdirTemp("", "TestZipSums") if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 1c31a5f90a..6a2cea668d 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -632,7 +632,7 @@ func setDefaultBuildMod() { func convertLegacyConfig(modPath string) (from string, err error) { for _, name := range altConfigs { cfg := filepath.Join(modRoot, name) - data, err := ioutil.ReadFile(cfg) + data, err := os.ReadFile(cfg) if err == nil { convert := modconv.Converters[name] if convert == nil { @@ -753,7 +753,7 @@ func findModulePath(dir string) (string, error) { } // Look for Godeps.json declaring import path. - data, _ := ioutil.ReadFile(filepath.Join(dir, "Godeps/Godeps.json")) + data, _ := os.ReadFile(filepath.Join(dir, "Godeps/Godeps.json")) var cfg1 struct{ ImportPath string } json.Unmarshal(data, &cfg1) if cfg1.ImportPath != "" { @@ -761,7 +761,7 @@ func findModulePath(dir string) (string, error) { } // Look for vendor.json declaring import path. - data, _ = ioutil.ReadFile(filepath.Join(dir, "vendor/vendor.json")) + data, _ = os.ReadFile(filepath.Join(dir, "vendor/vendor.json")) var cfg2 struct{ RootPath string } json.Unmarshal(data, &cfg2) if cfg2.RootPath != "" { @@ -813,7 +813,7 @@ var ( ) func findImportComment(file string) string { - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) if err != nil { return "" } diff --git a/src/cmd/go/internal/modload/query_test.go b/src/cmd/go/internal/modload/query_test.go index 777a56b977..e225a0e71e 100644 --- a/src/cmd/go/internal/modload/query_test.go +++ b/src/cmd/go/internal/modload/query_test.go @@ -7,7 +7,6 @@ package modload import ( "context" "internal/testenv" - "io/ioutil" "log" "os" "path" @@ -27,7 +26,7 @@ func TestMain(m *testing.M) { func testMain(m *testing.M) int { cfg.GOPROXY = "direct" - dir, err := ioutil.TempDir("", "modload-test-") + dir, err := os.MkdirTemp("", "modload-test-") if err != nil { log.Fatal(err) } diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index ab29d4d014..80d49053c6 100644 --- a/src/cmd/go/internal/modload/vendor.go +++ b/src/cmd/go/internal/modload/vendor.go @@ -8,7 +8,7 @@ import ( "errors" "fmt" "io/fs" - "io/ioutil" + "os" "path/filepath" "strings" "sync" @@ -40,7 +40,7 @@ func readVendorList() { vendorPkgModule = make(map[string]module.Version) vendorVersion = make(map[string]string) vendorMeta = make(map[module.Version]vendorMetadata) - data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) + data, err := os.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) if err != nil { if !errors.Is(err, fs.ErrNotExist) { base.Fatalf("go: %s", err) diff --git a/src/cmd/go/internal/renameio/renameio.go b/src/cmd/go/internal/renameio/renameio.go index 60a7138a76..9788171d6e 100644 --- a/src/cmd/go/internal/renameio/renameio.go +++ b/src/cmd/go/internal/renameio/renameio.go @@ -25,7 +25,7 @@ func Pattern(filename string) string { return filepath.Join(filepath.Dir(filename), filepath.Base(filename)+patternSuffix) } -// WriteFile is like ioutil.WriteFile, but first writes data to an arbitrary +// WriteFile is like os.WriteFile, but first writes data to an arbitrary // file in the same directory as filename, then renames it atomically to the // final name. // @@ -67,7 +67,7 @@ func WriteToFile(filename string, data io.Reader, perm fs.FileMode) (err error) return robustio.Rename(f.Name(), filename) } -// ReadFile is like ioutil.ReadFile, but on Windows retries spurious errors that +// ReadFile is like os.ReadFile, but on Windows retries spurious errors that // may occur if the file is concurrently replaced. // // Errors are classified heuristically and retries are bounded, so even this diff --git a/src/cmd/go/internal/renameio/renameio_test.go b/src/cmd/go/internal/renameio/renameio_test.go index e6d2025a0e..5b2ed83624 100644 --- a/src/cmd/go/internal/renameio/renameio_test.go +++ b/src/cmd/go/internal/renameio/renameio_test.go @@ -10,7 +10,6 @@ import ( "encoding/binary" "errors" "internal/testenv" - "io/ioutil" "math/rand" "os" "path/filepath" @@ -30,7 +29,7 @@ func TestConcurrentReadsAndWrites(t *testing.T) { testenv.SkipFlaky(t, 33041) } - dir, err := ioutil.TempDir("", "renameio") + dir, err := os.MkdirTemp("", "renameio") if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/renameio/umask_test.go b/src/cmd/go/internal/renameio/umask_test.go index 19e217c548..65e4fa587b 100644 --- a/src/cmd/go/internal/renameio/umask_test.go +++ b/src/cmd/go/internal/renameio/umask_test.go @@ -8,7 +8,6 @@ package renameio import ( "io/fs" - "io/ioutil" "os" "path/filepath" "syscall" @@ -16,7 +15,7 @@ import ( ) func TestWriteFileModeAppliesUmask(t *testing.T) { - dir, err := ioutil.TempDir("", "renameio") + dir, err := os.MkdirTemp("", "renameio") if err != nil { t.Fatalf("Failed to create temporary directory: %v", err) } diff --git a/src/cmd/go/internal/robustio/robustio.go b/src/cmd/go/internal/robustio/robustio.go index 76e47ad1ff..ce3dbbde6d 100644 --- a/src/cmd/go/internal/robustio/robustio.go +++ b/src/cmd/go/internal/robustio/robustio.go @@ -22,7 +22,7 @@ func Rename(oldpath, newpath string) error { return rename(oldpath, newpath) } -// ReadFile is like ioutil.ReadFile, but on Windows retries errors that may +// ReadFile is like os.ReadFile, but on Windows retries errors that may // occur if the file is concurrently replaced. // // (See golang.org/issue/31247 and golang.org/issue/32188.) diff --git a/src/cmd/go/internal/robustio/robustio_flaky.go b/src/cmd/go/internal/robustio/robustio_flaky.go index d4cb7e6457..5bd44bd345 100644 --- a/src/cmd/go/internal/robustio/robustio_flaky.go +++ b/src/cmd/go/internal/robustio/robustio_flaky.go @@ -8,7 +8,6 @@ package robustio import ( "errors" - "io/ioutil" "math/rand" "os" "syscall" @@ -70,11 +69,11 @@ func rename(oldpath, newpath string) (err error) { }) } -// readFile is like ioutil.ReadFile, but retries ephemeral errors. +// readFile is like os.ReadFile, but retries ephemeral errors. func readFile(filename string) ([]byte, error) { var b []byte err := retry(func() (err error, mayRetry bool) { - b, err = ioutil.ReadFile(filename) + b, err = os.ReadFile(filename) // Unlike in rename, we do not retry errFileNotFound here: it can occur // as a spurious error, but the file may also genuinely not exist, so the diff --git a/src/cmd/go/internal/robustio/robustio_other.go b/src/cmd/go/internal/robustio/robustio_other.go index 907b556858..6fe7b7e4e4 100644 --- a/src/cmd/go/internal/robustio/robustio_other.go +++ b/src/cmd/go/internal/robustio/robustio_other.go @@ -7,7 +7,6 @@ package robustio import ( - "io/ioutil" "os" ) @@ -16,7 +15,7 @@ func rename(oldpath, newpath string) error { } func readFile(filename string) ([]byte, error) { - return ioutil.ReadFile(filename) + return os.ReadFile(filename) } func removeAll(path string) error { diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 24601dc061..401b67c260 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -884,7 +884,7 @@ func builderTest(b *work.Builder, ctx context.Context, p *load.Package) (buildAc if !cfg.BuildN { // writeTestmain writes _testmain.go, // using the test description gathered in t. - if err := ioutil.WriteFile(testDir+"_testmain.go", *pmain.Internal.TestmainGo, 0666); err != nil { + if err := os.WriteFile(testDir+"_testmain.go", *pmain.Internal.TestmainGo, 0666); err != nil { return nil, nil, nil, err } } @@ -1616,7 +1616,7 @@ func (c *runCache) saveOutput(a *work.Action) { } // See comment about two-level lookup in tryCacheWithID above. - testlog, err := ioutil.ReadFile(a.Objdir + "testlog.txt") + testlog, err := os.ReadFile(a.Objdir + "testlog.txt") if err != nil || !bytes.HasPrefix(testlog, testlogMagic) || testlog[len(testlog)-1] != '\n' { if cache.DebugTest { if err != nil { diff --git a/src/cmd/go/internal/txtar/archive.go b/src/cmd/go/internal/txtar/archive.go index c384f33bdf..1796684877 100644 --- a/src/cmd/go/internal/txtar/archive.go +++ b/src/cmd/go/internal/txtar/archive.go @@ -34,7 +34,7 @@ package txtar import ( "bytes" "fmt" - "io/ioutil" + "os" "strings" ) @@ -66,7 +66,7 @@ func Format(a *Archive) []byte { // ParseFile parses the named file as an archive. func ParseFile(file string) (*Archive, error) { - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) if err != nil { return nil, err } diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index 72d74a01e3..c5c7a3283b 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -7,7 +7,6 @@ package vcs import ( "errors" "internal/testenv" - "io/ioutil" "os" "path" "path/filepath" @@ -208,7 +207,7 @@ func TestRepoRootForImportPath(t *testing.T) { // Test that vcsFromDir correctly inspects a given directory and returns the right VCS and root. func TestFromDir(t *testing.T) { - tempDir, err := ioutil.TempDir("", "vcstest") + tempDir, err := os.MkdirTemp("", "vcstest") if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/web/file_test.go b/src/cmd/go/internal/web/file_test.go index a1bb080e07..3734df5c4e 100644 --- a/src/cmd/go/internal/web/file_test.go +++ b/src/cmd/go/internal/web/file_test.go @@ -7,7 +7,6 @@ package web import ( "errors" "io/fs" - "io/ioutil" "os" "path/filepath" "testing" @@ -16,7 +15,7 @@ import ( func TestGetFileURL(t *testing.T) { const content = "Hello, file!\n" - f, err := ioutil.TempFile("", "web-TestGetFileURL") + f, err := os.CreateTemp("", "web-TestGetFileURL") if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go index f461c5780f..9d141ae233 100644 --- a/src/cmd/go/internal/work/action.go +++ b/src/cmd/go/internal/work/action.go @@ -14,7 +14,6 @@ import ( "debug/elf" "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" "runtime" @@ -253,7 +252,7 @@ func (b *Builder) Init() { if cfg.BuildN { b.WorkDir = "$WORK" } else { - tmp, err := ioutil.TempDir(cfg.Getenv("GOTMPDIR"), "go-build") + tmp, err := os.MkdirTemp(cfg.Getenv("GOTMPDIR"), "go-build") if err != nil { base.Fatalf("go: creating work dir: %v", err) } diff --git a/src/cmd/go/internal/work/build_test.go b/src/cmd/go/internal/work/build_test.go index e941729734..eaf2639e9e 100644 --- a/src/cmd/go/internal/work/build_test.go +++ b/src/cmd/go/internal/work/build_test.go @@ -8,7 +8,6 @@ import ( "bytes" "fmt" "io/fs" - "io/ioutil" "os" "path/filepath" "reflect" @@ -170,7 +169,7 @@ func TestSharedLibName(t *testing.T) { for _, data := range testData { func() { if data.rootedAt != "" { - tmpGopath, err := ioutil.TempDir("", "gopath") + tmpGopath, err := os.MkdirTemp("", "gopath") if err != nil { t.Fatal(err) } @@ -238,7 +237,7 @@ func TestRespectSetgidDir(t *testing.T) { return cmdBuf.WriteString(fmt.Sprint(a...)) } - setgiddir, err := ioutil.TempDir("", "SetGroupID") + setgiddir, err := os.MkdirTemp("", "SetGroupID") if err != nil { t.Fatal(err) } @@ -258,9 +257,9 @@ func TestRespectSetgidDir(t *testing.T) { t.Fatal(err) } - pkgfile, err := ioutil.TempFile("", "pkgfile") + pkgfile, err := os.CreateTemp("", "pkgfile") if err != nil { - t.Fatalf("ioutil.TempFile(\"\", \"pkgfile\"): %v", err) + t.Fatalf("os.CreateTemp(\"\", \"pkgfile\"): %v", err) } defer os.Remove(pkgfile.Name()) defer pkgfile.Close() diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 3c7be5a3e3..d76988145b 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -7,7 +7,6 @@ package work import ( "bytes" "fmt" - "io/ioutil" "os" "os/exec" "strings" @@ -344,7 +343,7 @@ func (b *Builder) gccgoBuildIDFile(a *Action) (string, error) { } } - if err := ioutil.WriteFile(sfile, buf.Bytes(), 0666); err != nil { + if err := os.WriteFile(sfile, buf.Bytes(), 0666); err != nil { return "", err } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 6ce56dd6f4..336751df27 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -16,7 +16,6 @@ import ( "internal/lazyregexp" "io" "io/fs" - "io/ioutil" "log" "math/rand" "os" @@ -94,7 +93,7 @@ func (b *Builder) Do(ctx context.Context, root *Action) { base.Fatalf("go: refusing to write action graph to %v\n", file) } js := actionGraphJSON(root) - if err := ioutil.WriteFile(file, []byte(js), 0666); err != nil { + if err := os.WriteFile(file, []byte(js), 0666); err != nil { fmt.Fprintf(os.Stderr, "go: writing action graph: %v\n", err) base.SetExitStatus(1) } @@ -636,7 +635,7 @@ OverlayLoop: sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles) } else { for _, sfile := range sfiles { - data, err := ioutil.ReadFile(filepath.Join(a.Package.Dir, sfile)) + data, err := os.ReadFile(filepath.Join(a.Package.Dir, sfile)) if err == nil { if bytes.HasPrefix(data, []byte("TEXT")) || bytes.Contains(data, []byte("\nTEXT")) || bytes.HasPrefix(data, []byte("DATA")) || bytes.Contains(data, []byte("\nDATA")) || @@ -1471,7 +1470,7 @@ func (b *Builder) installShlibname(ctx context.Context, a *Action) error { // TODO: BuildN a1 := a.Deps[0] - err := ioutil.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666) + err := os.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666) if err != nil { return err } @@ -1788,7 +1787,7 @@ func (b *Builder) writeFile(file string, text []byte) error { if cfg.BuildN { return nil } - return ioutil.WriteFile(file, text, 0666) + return os.WriteFile(file, text, 0666) } // Install the cgo export header file, if there is one. @@ -2537,7 +2536,7 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool { tmp := os.DevNull if runtime.GOOS == "windows" { - f, err := ioutil.TempFile(b.WorkDir, "") + f, err := os.CreateTemp(b.WorkDir, "") if err != nil { return false } @@ -2840,7 +2839,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo continue } - src, err := ioutil.ReadFile(f) + src, err := os.ReadFile(f) if err != nil { return nil, nil, err } @@ -3070,7 +3069,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) { return "$INTBITS", nil } src := filepath.Join(b.WorkDir, "swig_intsize.go") - if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil { + if err = os.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil { return } srcs := []string{src} @@ -3230,7 +3229,7 @@ func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) { return } - tf, err := ioutil.TempFile("", "args") + tf, err := os.CreateTemp("", "args") if err != nil { log.Fatalf("error writing long arguments to response file: %v", err) } diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 3a53c714e3..cc4e2b2b2b 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -9,7 +9,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "log" "os" "path/filepath" @@ -426,11 +425,11 @@ func toolVerify(a *Action, b *Builder, p *load.Package, newTool string, ofile st if err := b.run(a, p.Dir, p.ImportPath, nil, newArgs...); err != nil { return err } - data1, err := ioutil.ReadFile(ofile) + data1, err := os.ReadFile(ofile) if err != nil { return err } - data2, err := ioutil.ReadFile(ofile + ".new") + data2, err := os.ReadFile(ofile + ".new") if err != nil { return err } @@ -580,7 +579,7 @@ func pluginPath(a *Action) string { } fmt.Fprintf(h, "build ID: %s\n", buildID) for _, file := range str.StringList(p.GoFiles, p.CgoFiles, p.SFiles) { - data, err := ioutil.ReadFile(filepath.Join(p.Dir, file)) + data, err := os.ReadFile(filepath.Join(p.Dir, file)) if err != nil { base.Fatalf("go: %s", err) } diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go index 01d2b89159..3ffd01c473 100644 --- a/src/cmd/go/internal/work/gccgo.go +++ b/src/cmd/go/internal/work/gccgo.go @@ -6,7 +6,6 @@ package work import ( "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -271,7 +270,7 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string } readCgoFlags := func(flagsFile string) error { - flags, err := ioutil.ReadFile(flagsFile) + flags, err := os.ReadFile(flagsFile) if err != nil { return err } diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index aee3742f13..dfaa40548e 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -15,7 +15,6 @@ import ( "go/build" "internal/testenv" "io/fs" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -220,7 +219,7 @@ func (ts *testScript) run() { for _, f := range a.Files { name := ts.mkabs(ts.expand(f.Name, false)) ts.check(os.MkdirAll(filepath.Dir(name), 0777)) - ts.check(ioutil.WriteFile(name, f.Data, 0666)) + ts.check(os.WriteFile(name, f.Data, 0666)) } // With -v or -testwork, start log with full environment. @@ -377,19 +376,19 @@ var ( func isCaseSensitive(t *testing.T) bool { onceCaseSensitive.Do(func() { - tmpdir, err := ioutil.TempDir("", "case-sensitive") + tmpdir, err := os.MkdirTemp("", "case-sensitive") if err != nil { t.Fatal("failed to create directory to determine case-sensitivity:", err) } defer os.RemoveAll(tmpdir) fcap := filepath.Join(tmpdir, "FILE") - if err := ioutil.WriteFile(fcap, []byte{}, 0644); err != nil { + if err := os.WriteFile(fcap, []byte{}, 0644); err != nil { t.Fatal("error writing file to determine case-sensitivity:", err) } flow := filepath.Join(tmpdir, "file") - _, err = ioutil.ReadFile(flow) + _, err = os.ReadFile(flow) switch { case err == nil: caseSensitive = false @@ -450,9 +449,9 @@ func (ts *testScript) cmdAddcrlf(want simpleStatus, args []string) { for _, file := range args { file = ts.mkabs(file) - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) ts.check(err) - ts.check(ioutil.WriteFile(file, bytes.ReplaceAll(data, []byte("\n"), []byte("\r\n")), 0666)) + ts.check(os.WriteFile(file, bytes.ReplaceAll(data, []byte("\n"), []byte("\r\n")), 0666)) } } @@ -557,12 +556,12 @@ func (ts *testScript) doCmdCmp(args []string, env, quiet bool) { } else if name1 == "stderr" { text1 = ts.stderr } else { - data, err := ioutil.ReadFile(ts.mkabs(name1)) + data, err := os.ReadFile(ts.mkabs(name1)) ts.check(err) text1 = string(data) } - data, err := ioutil.ReadFile(ts.mkabs(name2)) + data, err := os.ReadFile(ts.mkabs(name2)) ts.check(err) text2 = string(data) @@ -614,14 +613,14 @@ func (ts *testScript) cmdCp(want simpleStatus, args []string) { info, err := os.Stat(src) ts.check(err) mode = info.Mode() & 0777 - data, err = ioutil.ReadFile(src) + data, err = os.ReadFile(src) ts.check(err) } targ := dst if dstDir { targ = filepath.Join(dst, filepath.Base(src)) } - err := ioutil.WriteFile(targ, data, mode) + err := os.WriteFile(targ, data, mode) switch want { case failure: if err == nil { @@ -897,7 +896,7 @@ func scriptMatch(ts *testScript, want simpleStatus, args []string, text, name st isGrep := name == "grep" if isGrep { name = args[1] // for error messages - data, err := ioutil.ReadFile(ts.mkabs(args[1])) + data, err := os.ReadFile(ts.mkabs(args[1])) ts.check(err) text = string(data) } diff --git a/src/cmd/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go index 71ac47fdc1..58376b7ed4 100644 --- a/src/cmd/go/testdata/addmod.go +++ b/src/cmd/go/testdata/addmod.go @@ -23,7 +23,6 @@ import ( "flag" "fmt" "io/fs" - "io/ioutil" "log" "os" "os/exec" @@ -58,7 +57,7 @@ func main() { log.SetFlags(0) var err error - tmpdir, err = ioutil.TempDir("", "addmod-") + tmpdir, err = os.MkdirTemp("", "addmod-") if err != nil { log.Fatal(err) } @@ -82,7 +81,7 @@ func main() { exitCode := 0 for _, arg := range flag.Args() { - if err := ioutil.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module m\n"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module m\n"), 0666); err != nil { fatalf("%v", err) } run(goCmd, "get", "-d", arg) @@ -98,13 +97,13 @@ func main() { continue } path, vers, dir := f[0], f[1], f[2] - mod, err := ioutil.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".mod")) + mod, err := os.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".mod")) if err != nil { log.Printf("%s: %v", arg, err) exitCode = 1 continue } - info, err := ioutil.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".info")) + info, err := os.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".info")) if err != nil { log.Printf("%s: %v", arg, err) exitCode = 1 @@ -128,7 +127,7 @@ func main() { } name := info.Name() if name == "go.mod" || strings.HasSuffix(name, ".go") { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return err } @@ -144,7 +143,7 @@ func main() { data := txtar.Format(a) target := filepath.Join("mod", strings.ReplaceAll(path, "/", "_")+"_"+vers+".txt") - if err := ioutil.WriteFile(target, data, 0666); err != nil { + if err := os.WriteFile(target, data, 0666); err != nil { log.Printf("%s: %v", arg, err) exitCode = 1 continue diff --git a/src/cmd/go/testdata/savedir.go b/src/cmd/go/testdata/savedir.go index 75895ee279..d469c31a91 100644 --- a/src/cmd/go/testdata/savedir.go +++ b/src/cmd/go/testdata/savedir.go @@ -18,7 +18,6 @@ import ( "flag" "fmt" "io/fs" - "io/ioutil" "log" "os" "path/filepath" @@ -63,7 +62,7 @@ func main() { if !info.Type().IsRegular() { return nil } - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { log.Fatal(err) } diff --git a/src/cmd/go/testdata/script/build_issue6480.txt b/src/cmd/go/testdata/script/build_issue6480.txt index ae99c60d99..cf1e9ea6c2 100644 --- a/src/cmd/go/testdata/script/build_issue6480.txt +++ b/src/cmd/go/testdata/script/build_issue6480.txt @@ -81,7 +81,6 @@ package main import ( "encoding/json" "fmt" - "io/ioutil" "os" "time" ) @@ -100,7 +99,7 @@ func truncateLike(t, p time.Time) time.Time { func main() { var t1 time.Time - b1, err := ioutil.ReadFile(os.Args[1]) + b1, err := os.ReadFile(os.Args[1]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) @@ -111,7 +110,7 @@ func main() { } var t2 time.Time - b2, err := ioutil.ReadFile(os.Args[2]) + b2, err := os.ReadFile(os.Args[2]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/src/cmd/go/testdata/script/build_trimpath.txt b/src/cmd/go/testdata/script/build_trimpath.txt index 2c3bee8fdc..e1ea0a48b2 100644 --- a/src/cmd/go/testdata/script/build_trimpath.txt +++ b/src/cmd/go/testdata/script/build_trimpath.txt @@ -121,7 +121,6 @@ package main import ( "bytes" "fmt" - "io/ioutil" "log" "os" "os/exec" @@ -131,7 +130,7 @@ import ( func main() { exe := os.Args[1] - data, err := ioutil.ReadFile(exe) + data, err := os.ReadFile(exe) if err != nil { log.Fatal(err) } diff --git a/src/cmd/go/testdata/script/cover_error.txt b/src/cmd/go/testdata/script/cover_error.txt index 4abdf1137a..583a664237 100644 --- a/src/cmd/go/testdata/script/cover_error.txt +++ b/src/cmd/go/testdata/script/cover_error.txt @@ -54,7 +54,6 @@ func Test(t *testing.T) {} package main import ( - "io/ioutil" "log" "os" "strings" @@ -62,13 +61,13 @@ import ( func main() { log.SetFlags(0) - b, err := ioutil.ReadFile(os.Args[1]) + b, err := os.ReadFile(os.Args[1]) if err != nil { log.Fatal(err) } s := strings.ReplaceAll(string(b), "p.go:4:2:", "p.go:4:") s = strings.ReplaceAll(s, "p1.go:6:2:", "p1.go:6:") - ioutil.WriteFile(os.Args[1], []byte(s), 0644) + os.WriteFile(os.Args[1], []byte(s), 0644) if err != nil { log.Fatal(err) } diff --git a/src/cmd/go/testdata/script/gopath_moved_repo.txt b/src/cmd/go/testdata/script/gopath_moved_repo.txt index 869980da7c..99d80bff5d 100644 --- a/src/cmd/go/testdata/script/gopath_moved_repo.txt +++ b/src/cmd/go/testdata/script/gopath_moved_repo.txt @@ -45,7 +45,6 @@ package main import ( "bytes" - "io/ioutil" "log" "os" ) @@ -57,11 +56,11 @@ func main() { base := []byte(os.Args[1]) path := os.Args[2] - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { log.Fatal(err) } - err = ioutil.WriteFile(path, bytes.ReplaceAll(data, base, append(base, "XXX"...)), 0644) + err = os.WriteFile(path, bytes.ReplaceAll(data, base, append(base, "XXX"...)), 0644) if err != nil { log.Fatal(err) } diff --git a/src/cmd/go/testdata/script/mod_download_concurrent_read.txt b/src/cmd/go/testdata/script/mod_download_concurrent_read.txt index caf105c6e5..231babd0c0 100644 --- a/src/cmd/go/testdata/script/mod_download_concurrent_read.txt +++ b/src/cmd/go/testdata/script/mod_download_concurrent_read.txt @@ -25,7 +25,6 @@ package main import ( "fmt" - "io/ioutil" "log" "os" "os/exec" @@ -45,7 +44,7 @@ func main() { // don't need to clean the cache or synchronize closing files after each // iteration. func run() (err error) { - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") if err != nil { return err } diff --git a/src/cmd/go/testdata/script/mod_modinfo.txt b/src/cmd/go/testdata/script/mod_modinfo.txt index d9e9fdec21..8d77e224a5 100644 --- a/src/cmd/go/testdata/script/mod_modinfo.txt +++ b/src/cmd/go/testdata/script/mod_modinfo.txt @@ -69,7 +69,6 @@ package main import ( "bytes" "encoding/hex" - "io/ioutil" "log" "os" @@ -77,7 +76,7 @@ import ( ) func main() { - b, err := ioutil.ReadFile(os.Args[0]) + b, err := os.ReadFile(os.Args[0]) if err != nil { log.Fatal(err) } diff --git a/src/cmd/go/testdata/script/mod_test_cached.txt b/src/cmd/go/testdata/script/mod_test_cached.txt index ffd573c02a..3da4358fa1 100644 --- a/src/cmd/go/testdata/script/mod_test_cached.txt +++ b/src/cmd/go/testdata/script/mod_test_cached.txt @@ -51,26 +51,25 @@ bar package foo_test import ( - "io/ioutil" "os" "path/filepath" "testing" ) func TestWriteTmp(t *testing.T) { - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") if err != nil { t.Fatal(err) } defer os.RemoveAll(dir) - err = ioutil.WriteFile(filepath.Join(dir, "x"), nil, 0666) + err = os.WriteFile(filepath.Join(dir, "x"), nil, 0666) if err != nil { t.Fatal(err) } } func TestReadTestdata(t *testing.T) { - _, err := ioutil.ReadFile("testdata/foo.txt") + _, err := os.ReadFile("testdata/foo.txt") if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/testdata/script/test_compile_tempfile.txt b/src/cmd/go/testdata/script/test_compile_tempfile.txt index 912410814f..05f721a800 100644 --- a/src/cmd/go/testdata/script/test_compile_tempfile.txt +++ b/src/cmd/go/testdata/script/test_compile_tempfile.txt @@ -1,7 +1,7 @@ [short] skip # Ensure that the target of 'go build -o' can be an existing, empty file so that -# its name can be reserved using ioutil.TempFile or the 'mktemp` command. +# its name can be reserved using os.CreateTemp or the 'mktemp` command. go build -o empty-file$GOEXE main.go diff --git a/src/cmd/go/testdata/script/test_generated_main.txt b/src/cmd/go/testdata/script/test_generated_main.txt index 75ffa9cde2..2e991a5797 100644 --- a/src/cmd/go/testdata/script/test_generated_main.txt +++ b/src/cmd/go/testdata/script/test_generated_main.txt @@ -12,7 +12,6 @@ package x import ( "os" "path/filepath" - "io/ioutil" "regexp" "testing" ) @@ -23,7 +22,7 @@ func Test(t *testing.T) { t.Fatal(err) } testmainPath := filepath.Join(filepath.Dir(exePath), "_testmain.go") - source, err := ioutil.ReadFile(testmainPath) + source, err := os.ReadFile(testmainPath) if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/testdata/script/test_race_install_cgo.txt b/src/cmd/go/testdata/script/test_race_install_cgo.txt index 82f00f2086..3f4eb90e3f 100644 --- a/src/cmd/go/testdata/script/test_race_install_cgo.txt +++ b/src/cmd/go/testdata/script/test_race_install_cgo.txt @@ -29,7 +29,6 @@ go 1.16 package main import ( - "io/ioutil" "encoding/json" "fmt" "os" @@ -37,7 +36,7 @@ import ( ) func main() { - b, err := ioutil.ReadFile(os.Args[1]) + b, err := os.ReadFile(os.Args[1]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) @@ -59,7 +58,6 @@ package main import ( "encoding/json" "fmt" - "io/ioutil" "os" "time" ) @@ -67,7 +65,7 @@ import ( func main() { var t1 time.Time - b1, err := ioutil.ReadFile(os.Args[1]) + b1, err := os.ReadFile(os.Args[1]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) @@ -78,7 +76,7 @@ func main() { } var t2 time.Time - b2, err := ioutil.ReadFile(os.Args[2]) + b2, err := os.ReadFile(os.Args[2]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index 719c681a3e..2793c2c2a4 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -15,7 +15,6 @@ import ( "go/token" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "runtime" @@ -137,7 +136,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error if err != nil { return err } - err = ioutil.WriteFile(filename, res, perm) + err = os.WriteFile(filename, res, perm) if err != nil { os.Rename(bakname, filename) return err @@ -278,7 +277,7 @@ const chmodSupported = runtime.GOOS != "windows" // the chosen file name. func backupFile(filename string, data []byte, perm fs.FileMode) (string, error) { // create backup file - f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)) + f, err := os.CreateTemp(filepath.Dir(filename), filepath.Base(filename)) if err != nil { return "", err } diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go index 98d3eb7eb2..bf2adfe64c 100644 --- a/src/cmd/gofmt/gofmt_test.go +++ b/src/cmd/gofmt/gofmt_test.go @@ -7,7 +7,6 @@ package main import ( "bytes" "flag" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -93,7 +92,7 @@ func runTest(t *testing.T, in, out string) { return } - expected, err := ioutil.ReadFile(out) + expected, err := os.ReadFile(out) if err != nil { t.Error(err) return @@ -102,7 +101,7 @@ func runTest(t *testing.T, in, out string) { if got := buf.Bytes(); !bytes.Equal(got, expected) { if *update { if in != out { - if err := ioutil.WriteFile(out, got, 0666); err != nil { + if err := os.WriteFile(out, got, 0666); err != nil { t.Error(err) } return @@ -116,7 +115,7 @@ func runTest(t *testing.T, in, out string) { if err == nil { t.Errorf("%s", d) } - if err := ioutil.WriteFile(in+".gofmt", got, 0666); err != nil { + if err := os.WriteFile(in+".gofmt", got, 0666); err != nil { t.Error(err) } } @@ -157,7 +156,7 @@ func TestCRLF(t *testing.T) { const input = "testdata/crlf.input" // must contain CR/LF's const golden = "testdata/crlf.golden" // must not contain any CR's - data, err := ioutil.ReadFile(input) + data, err := os.ReadFile(input) if err != nil { t.Error(err) } @@ -165,7 +164,7 @@ func TestCRLF(t *testing.T) { t.Errorf("%s contains no CR/LF's", input) } - data, err = ioutil.ReadFile(golden) + data, err = os.ReadFile(golden) if err != nil { t.Error(err) } @@ -175,7 +174,7 @@ func TestCRLF(t *testing.T) { } func TestBackupFile(t *testing.T) { - dir, err := ioutil.TempDir("", "gofmt_test") + dir, err := os.MkdirTemp("", "gofmt_test") if err != nil { t.Fatal(err) } diff --git a/src/cmd/nm/nm_test.go b/src/cmd/nm/nm_test.go index 382446e9fe..0d51b07a44 100644 --- a/src/cmd/nm/nm_test.go +++ b/src/cmd/nm/nm_test.go @@ -8,7 +8,6 @@ import ( "fmt" "internal/obscuretestdata" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -31,7 +30,7 @@ func testMain(m *testing.M) int { return 0 } - tmpDir, err := ioutil.TempDir("", "TestNM") + tmpDir, err := os.MkdirTemp("", "TestNM") if err != nil { fmt.Println("TempDir failed:", err) return 2 @@ -88,7 +87,7 @@ func TestNonGoExecs(t *testing.T) { func testGoExec(t *testing.T, iscgo, isexternallinker bool) { t.Parallel() - tmpdir, err := ioutil.TempDir("", "TestGoExec") + tmpdir, err := os.MkdirTemp("", "TestGoExec") if err != nil { t.Fatal(err) } @@ -222,7 +221,7 @@ func TestGoExec(t *testing.T) { func testGoLib(t *testing.T, iscgo bool) { t.Parallel() - tmpdir, err := ioutil.TempDir("", "TestGoLib") + tmpdir, err := os.MkdirTemp("", "TestGoLib") if err != nil { t.Fatal(err) } @@ -245,7 +244,7 @@ func testGoLib(t *testing.T, iscgo bool) { err = e } if err == nil { - err = ioutil.WriteFile(filepath.Join(libpath, "go.mod"), []byte("module mylib\n"), 0666) + err = os.WriteFile(filepath.Join(libpath, "go.mod"), []byte("module mylib\n"), 0666) } if err != nil { t.Fatal(err) diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go index cb692e7a81..edaca774f7 100644 --- a/src/cmd/objdump/objdump_test.go +++ b/src/cmd/objdump/objdump_test.go @@ -10,7 +10,6 @@ import ( "fmt" "go/build" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -39,7 +38,7 @@ func TestMain(m *testing.M) { func buildObjdump() error { var err error - tmp, err = ioutil.TempDir("", "TestObjDump") + tmp, err = os.MkdirTemp("", "TestObjDump") if err != nil { return fmt.Errorf("TempDir failed: %v", err) } @@ -320,7 +319,7 @@ func TestGoobjFileNumber(t *testing.T) { t.Parallel() - tmpdir, err := ioutil.TempDir("", "TestGoobjFileNumber") + tmpdir, err := os.MkdirTemp("", "TestGoobjFileNumber") if err != nil { t.Fatal(err) } diff --git a/src/cmd/pack/pack_test.go b/src/cmd/pack/pack_test.go index 9f65705def..218c7acda6 100644 --- a/src/cmd/pack/pack_test.go +++ b/src/cmd/pack/pack_test.go @@ -12,7 +12,6 @@ import ( "internal/testenv" "io" "io/fs" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -22,7 +21,7 @@ import ( // tmpDir creates a temporary directory and returns its name. func tmpDir(t *testing.T) string { - name, err := ioutil.TempDir("", "pack") + name, err := os.MkdirTemp("", "pack") if err != nil { t.Fatal(err) } @@ -158,7 +157,7 @@ func TestExtract(t *testing.T) { ar = openArchive(name, os.O_RDONLY, []string{goodbyeFile.name}) ar.scan(ar.extractContents) ar.a.File().Close() - data, err := ioutil.ReadFile(goodbyeFile.name) + data, err := os.ReadFile(goodbyeFile.name) if err != nil { t.Fatal(err) } @@ -183,7 +182,7 @@ func TestHello(t *testing.T) { println("hello world") } ` - err := ioutil.WriteFile(hello, []byte(prog), 0666) + err := os.WriteFile(hello, []byte(prog), 0666) if err != nil { t.Fatal(err) } @@ -251,7 +250,7 @@ func TestLargeDefs(t *testing.T) { println("ok") } ` - err = ioutil.WriteFile(main, []byte(prog), 0666) + err = os.WriteFile(main, []byte(prog), 0666) if err != nil { t.Fatal(err) } @@ -281,13 +280,13 @@ func TestIssue21703(t *testing.T) { defer os.RemoveAll(dir) const aSrc = `package a; const X = "\n!\n"` - err := ioutil.WriteFile(filepath.Join(dir, "a.go"), []byte(aSrc), 0666) + err := os.WriteFile(filepath.Join(dir, "a.go"), []byte(aSrc), 0666) if err != nil { t.Fatal(err) } const bSrc = `package b; import _ "a"` - err = ioutil.WriteFile(filepath.Join(dir, "b.go"), []byte(bSrc), 0666) + err = os.WriteFile(filepath.Join(dir, "b.go"), []byte(bSrc), 0666) if err != nil { t.Fatal(err) } diff --git a/src/cmd/trace/annotations_test.go b/src/cmd/trace/annotations_test.go index a9068d53c1..9c2d027366 100644 --- a/src/cmd/trace/annotations_test.go +++ b/src/cmd/trace/annotations_test.go @@ -12,7 +12,7 @@ import ( "flag" "fmt" traceparser "internal/trace" - "io/ioutil" + "os" "reflect" "runtime/debug" "runtime/trace" @@ -386,7 +386,7 @@ func saveTrace(buf *bytes.Buffer, name string) { if !*saveTraces { return } - if err := ioutil.WriteFile(name+".trace", buf.Bytes(), 0600); err != nil { + if err := os.WriteFile(name+".trace", buf.Bytes(), 0600); err != nil { panic(fmt.Errorf("failed to write trace file: %v", err)) } } diff --git a/src/cmd/trace/pprof.go b/src/cmd/trace/pprof.go index a31d71b013..a73ff5336a 100644 --- a/src/cmd/trace/pprof.go +++ b/src/cmd/trace/pprof.go @@ -11,7 +11,6 @@ import ( "fmt" "internal/trace" "io" - "io/ioutil" "net/http" "os" "os/exec" @@ -294,7 +293,7 @@ func serveSVGProfile(prof func(w io.Writer, r *http.Request) error) http.Handler return } - blockf, err := ioutil.TempFile("", "block") + blockf, err := os.CreateTemp("", "block") if err != nil { http.Error(w, fmt.Sprintf("failed to create temp file: %v", err), http.StatusInternalServerError) return diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go index 5d8139d977..d15d1ce377 100644 --- a/src/cmd/vet/vet_test.go +++ b/src/cmd/vet/vet_test.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "internal/testenv" - "io/ioutil" "log" "os" "os/exec" @@ -32,7 +31,7 @@ func TestMain(m *testing.M) { } func testMain(m *testing.M) int { - dir, err := ioutil.TempDir("", "vet_test") + dir, err := os.MkdirTemp("", "vet_test") if err != nil { fmt.Fprintln(os.Stderr, err) return 1 @@ -345,7 +344,7 @@ var ( func wantedErrors(file, short string) (errs []wantedError) { cache := make(map[string]*regexp.Regexp) - src, err := ioutil.ReadFile(file) + src, err := os.ReadFile(file) if err != nil { log.Fatal(err) } diff --git a/src/compress/bzip2/bzip2_test.go b/src/compress/bzip2/bzip2_test.go index 98477791b3..e6065cb43f 100644 --- a/src/compress/bzip2/bzip2_test.go +++ b/src/compress/bzip2/bzip2_test.go @@ -9,7 +9,7 @@ import ( "encoding/hex" "fmt" "io" - "io/ioutil" + "os" "testing" ) @@ -22,7 +22,7 @@ func mustDecodeHex(s string) []byte { } func mustLoadFile(f string) []byte { - b, err := ioutil.ReadFile(f) + b, err := os.ReadFile(f) if err != nil { panic(err) } diff --git a/src/compress/flate/deflate_test.go b/src/compress/flate/deflate_test.go index 6fc5abf4d5..ff56712123 100644 --- a/src/compress/flate/deflate_test.go +++ b/src/compress/flate/deflate_test.go @@ -10,8 +10,8 @@ import ( "fmt" "internal/testenv" "io" - "io/ioutil" "math/rand" + "os" "reflect" "runtime/debug" "sync" @@ -387,7 +387,7 @@ func TestDeflateInflateString(t *testing.T) { t.Skip("skipping in short mode") } for _, test := range deflateInflateStringTests { - gold, err := ioutil.ReadFile(test.filename) + gold, err := os.ReadFile(test.filename) if err != nil { t.Error(err) } @@ -685,7 +685,7 @@ func (w *failWriter) Write(b []byte) (int, error) { func TestWriterPersistentError(t *testing.T) { t.Parallel() - d, err := ioutil.ReadFile("../../testdata/Isaac.Newton-Opticks.txt") + d, err := os.ReadFile("../../testdata/Isaac.Newton-Opticks.txt") if err != nil { t.Fatalf("ReadFile: %v", err) } diff --git a/src/compress/flate/huffman_bit_writer_test.go b/src/compress/flate/huffman_bit_writer_test.go index 882d3abec1..a57799cae0 100644 --- a/src/compress/flate/huffman_bit_writer_test.go +++ b/src/compress/flate/huffman_bit_writer_test.go @@ -8,7 +8,6 @@ import ( "bytes" "flag" "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -38,7 +37,7 @@ func TestBlockHuff(t *testing.T) { } func testBlockHuff(t *testing.T, in, out string) { - all, err := ioutil.ReadFile(in) + all, err := os.ReadFile(in) if err != nil { t.Error(err) return @@ -49,7 +48,7 @@ func testBlockHuff(t *testing.T, in, out string) { bw.flush() got := buf.Bytes() - want, err := ioutil.ReadFile(out) + want, err := os.ReadFile(out) if err != nil && !*update { t.Error(err) return @@ -60,7 +59,7 @@ func testBlockHuff(t *testing.T, in, out string) { if *update { if in != out { t.Logf("Updating %q", out) - if err := ioutil.WriteFile(out, got, 0666); err != nil { + if err := os.WriteFile(out, got, 0666); err != nil { t.Error(err) } return @@ -70,7 +69,7 @@ func testBlockHuff(t *testing.T, in, out string) { } t.Errorf("%q != %q (see %q)", in, out, in+".got") - if err := ioutil.WriteFile(in+".got", got, 0666); err != nil { + if err := os.WriteFile(in+".got", got, 0666); err != nil { t.Error(err) } return @@ -85,7 +84,7 @@ func testBlockHuff(t *testing.T, in, out string) { got = buf.Bytes() if !bytes.Equal(got, want) { t.Errorf("after reset %q != %q (see %q)", in, out, in+".reset.got") - if err := ioutil.WriteFile(in+".reset.got", got, 0666); err != nil { + if err := os.WriteFile(in+".reset.got", got, 0666); err != nil { t.Error(err) } return @@ -186,7 +185,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) { if *update { if test.input != "" { t.Logf("Updating %q", test.want) - input, err := ioutil.ReadFile(test.input) + input, err := os.ReadFile(test.input) if err != nil { t.Error(err) return @@ -216,12 +215,12 @@ func testBlock(t *testing.T, test huffTest, ttype string) { if test.input != "" { t.Logf("Testing %q", test.want) - input, err := ioutil.ReadFile(test.input) + input, err := os.ReadFile(test.input) if err != nil { t.Error(err) return } - want, err := ioutil.ReadFile(test.want) + want, err := os.ReadFile(test.want) if err != nil { t.Error(err) return @@ -233,7 +232,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) { got := buf.Bytes() if !bytes.Equal(got, want) { t.Errorf("writeBlock did not yield expected result for file %q with input. See %q", test.want, test.want+".got") - if err := ioutil.WriteFile(test.want+".got", got, 0666); err != nil { + if err := os.WriteFile(test.want+".got", got, 0666); err != nil { t.Error(err) } } @@ -247,7 +246,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) { got = buf.Bytes() if !bytes.Equal(got, want) { t.Errorf("reset: writeBlock did not yield expected result for file %q with input. See %q", test.want, test.want+".reset.got") - if err := ioutil.WriteFile(test.want+".reset.got", got, 0666); err != nil { + if err := os.WriteFile(test.want+".reset.got", got, 0666); err != nil { t.Error(err) } return @@ -256,7 +255,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) { testWriterEOF(t, "wb", test, true) } t.Logf("Testing %q", test.wantNoInput) - wantNI, err := ioutil.ReadFile(test.wantNoInput) + wantNI, err := os.ReadFile(test.wantNoInput) if err != nil { t.Error(err) return @@ -268,7 +267,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) { got := buf.Bytes() if !bytes.Equal(got, wantNI) { t.Errorf("writeBlock did not yield expected result for file %q with input. See %q", test.wantNoInput, test.wantNoInput+".got") - if err := ioutil.WriteFile(test.want+".got", got, 0666); err != nil { + if err := os.WriteFile(test.want+".got", got, 0666); err != nil { t.Error(err) } } else if got[0]&1 == 1 { @@ -286,7 +285,7 @@ func testBlock(t *testing.T, test huffTest, ttype string) { got = buf.Bytes() if !bytes.Equal(got, wantNI) { t.Errorf("reset: writeBlock did not yield expected result for file %q without input. See %q", test.want, test.want+".reset.got") - if err := ioutil.WriteFile(test.want+".reset.got", got, 0666); err != nil { + if err := os.WriteFile(test.want+".reset.got", got, 0666); err != nil { t.Error(err) } return @@ -325,7 +324,7 @@ func testWriterEOF(t *testing.T, ttype string, test huffTest, useInput bool) { var input []byte if useInput { var err error - input, err = ioutil.ReadFile(test.input) + input, err = os.ReadFile(test.input) if err != nil { t.Error(err) return diff --git a/src/compress/flate/reader_test.go b/src/compress/flate/reader_test.go index eb32c89184..94610fbb78 100644 --- a/src/compress/flate/reader_test.go +++ b/src/compress/flate/reader_test.go @@ -7,7 +7,7 @@ package flate import ( "bytes" "io" - "io/ioutil" + "os" "runtime" "strings" "testing" @@ -80,7 +80,7 @@ var sizes = []struct { func doBench(b *testing.B, f func(b *testing.B, buf []byte, level, n int)) { for _, suite := range suites { - buf, err := ioutil.ReadFile(suite.file) + buf, err := os.ReadFile(suite.file) if err != nil { b.Fatal(err) } diff --git a/src/compress/lzw/reader_test.go b/src/compress/lzw/reader_test.go index 6d91dd806f..d1eb76d042 100644 --- a/src/compress/lzw/reader_test.go +++ b/src/compress/lzw/reader_test.go @@ -8,8 +8,8 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "math" + "os" "runtime" "strconv" "strings" @@ -218,7 +218,7 @@ func TestNoLongerSavingPriorExpansions(t *testing.T) { } func BenchmarkDecoder(b *testing.B) { - buf, err := ioutil.ReadFile("../testdata/e.txt") + buf, err := os.ReadFile("../testdata/e.txt") if err != nil { b.Fatal(err) } diff --git a/src/compress/lzw/writer_test.go b/src/compress/lzw/writer_test.go index 33a28bdd3a..1a5dbcae93 100644 --- a/src/compress/lzw/writer_test.go +++ b/src/compress/lzw/writer_test.go @@ -8,7 +8,6 @@ import ( "fmt" "internal/testenv" "io" - "io/ioutil" "math" "os" "runtime" @@ -125,7 +124,7 @@ func TestSmallLitWidth(t *testing.T) { } func BenchmarkEncoder(b *testing.B) { - buf, err := ioutil.ReadFile("../testdata/e.txt") + buf, err := os.ReadFile("../testdata/e.txt") if err != nil { b.Fatal(err) } diff --git a/src/compress/zlib/writer_test.go b/src/compress/zlib/writer_test.go index c518729146..f0b38880a6 100644 --- a/src/compress/zlib/writer_test.go +++ b/src/compress/zlib/writer_test.go @@ -9,7 +9,6 @@ import ( "fmt" "internal/testenv" "io" - "io/ioutil" "os" "testing" ) @@ -95,7 +94,7 @@ func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) { var b0 []byte var err error if fn != "" { - b0, err = ioutil.ReadFile(fn) + b0, err = os.ReadFile(fn) if err != nil { t.Errorf("%s (level=%d): %v", fn, level, err) return diff --git a/src/crypto/md5/gen.go b/src/crypto/md5/gen.go index a11f22059f..1468924cbc 100644 --- a/src/crypto/md5/gen.go +++ b/src/crypto/md5/gen.go @@ -15,8 +15,8 @@ import ( "bytes" "flag" "go/format" - "io/ioutil" "log" + "os" "strings" "text/template" ) @@ -37,7 +37,7 @@ func main() { if err != nil { log.Fatal(err) } - err = ioutil.WriteFile(*filename, data, 0644) + err = os.WriteFile(*filename, data, 0644) if err != nil { log.Fatal(err) } diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go index 605be587b5..d9ff9fe948 100644 --- a/src/crypto/tls/handshake_test.go +++ b/src/crypto/tls/handshake_test.go @@ -13,7 +13,6 @@ import ( "flag" "fmt" "io" - "io/ioutil" "net" "os" "os/exec" @@ -224,7 +223,7 @@ func parseTestData(r io.Reader) (flows [][]byte, err error) { // tempFile creates a temp file containing contents and returns its path. func tempFile(contents string) string { - file, err := ioutil.TempFile("", "go-tls-test") + file, err := os.CreateTemp("", "go-tls-test") if err != nil { panic("failed to create temp file: " + err.Error()) } diff --git a/src/crypto/tls/link_test.go b/src/crypto/tls/link_test.go index 8224216b5c..8c392ff7c4 100644 --- a/src/crypto/tls/link_test.go +++ b/src/crypto/tls/link_test.go @@ -7,7 +7,6 @@ package tls import ( "bytes" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -77,7 +76,7 @@ func main() { tls.Dial("", "", nil) } exeFile := filepath.Join(tmpDir, "x.exe") for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := ioutil.WriteFile(goFile, []byte(tt.program), 0644); err != nil { + if err := os.WriteFile(goFile, []byte(tt.program), 0644); err != nil { t.Fatal(err) } os.Remove(exeFile) diff --git a/src/crypto/tls/tls.go b/src/crypto/tls/tls.go index bf577cadea..19884f96e7 100644 --- a/src/crypto/tls/tls.go +++ b/src/crypto/tls/tls.go @@ -22,8 +22,8 @@ import ( "encoding/pem" "errors" "fmt" - "io/ioutil" "net" + "os" "strings" ) @@ -222,11 +222,11 @@ func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Con // form a certificate chain. On successful return, Certificate.Leaf will // be nil because the parsed form of the certificate is not retained. func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) { - certPEMBlock, err := ioutil.ReadFile(certFile) + certPEMBlock, err := os.ReadFile(certFile) if err != nil { return Certificate{}, err } - keyPEMBlock, err := ioutil.ReadFile(keyFile) + keyPEMBlock, err := os.ReadFile(keyFile) if err != nil { return Certificate{}, err } diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go index 34055d07b5..3826c82c38 100644 --- a/src/crypto/x509/name_constraints_test.go +++ b/src/crypto/x509/name_constraints_test.go @@ -14,7 +14,6 @@ import ( "encoding/hex" "encoding/pem" "fmt" - "io/ioutil" "math/big" "net" "net/url" @@ -2005,7 +2004,7 @@ func TestConstraintCases(t *testing.T) { } func writePEMsToTempFile(certs []*Certificate) *os.File { - file, err := ioutil.TempFile("", "name_constraints_test") + file, err := os.CreateTemp("", "name_constraints_test") if err != nil { panic("cannot create tempfile") } diff --git a/src/crypto/x509/root_ios_gen.go b/src/crypto/x509/root_ios_gen.go index 2bcdab1a77..8bc6e7d9c4 100644 --- a/src/crypto/x509/root_ios_gen.go +++ b/src/crypto/x509/root_ios_gen.go @@ -27,9 +27,9 @@ import ( "fmt" "go/format" "io" - "io/ioutil" "log" "net/http" + "os" "path" "sort" "strings" @@ -155,7 +155,7 @@ func main() { if err != nil { log.Fatal(err) } - if err := ioutil.WriteFile(*output, source, 0644); err != nil { + if err := os.WriteFile(*output, source, 0644); err != nil { log.Fatal(err) } } diff --git a/src/crypto/x509/root_plan9.go b/src/crypto/x509/root_plan9.go index 09f0e23033..2dc4aaf5d7 100644 --- a/src/crypto/x509/root_plan9.go +++ b/src/crypto/x509/root_plan9.go @@ -7,7 +7,6 @@ package x509 import ( - "io/ioutil" "os" ) @@ -24,7 +23,7 @@ func loadSystemRoots() (*CertPool, error) { roots := NewCertPool() var bestErr error for _, file := range certFiles { - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) if err == nil { roots.AppendCertsFromPEM(data) return roots, nil diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go index 1090b69f83..3c643466ed 100644 --- a/src/crypto/x509/root_unix.go +++ b/src/crypto/x509/root_unix.go @@ -40,7 +40,7 @@ func loadSystemRoots() (*CertPool, error) { var firstErr error for _, file := range files { - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) if err == nil { roots.AppendCertsFromPEM(data) break @@ -68,7 +68,7 @@ func loadSystemRoots() (*CertPool, error) { continue } for _, fi := range fis { - data, err := ioutil.ReadFile(directory + "/" + fi.Name()) + data, err := os.ReadFile(directory + "/" + fi.Name()) if err == nil { roots.AppendCertsFromPEM(data) } diff --git a/src/crypto/x509/root_unix_test.go b/src/crypto/x509/root_unix_test.go index b2e832ff36..878ed7c2fa 100644 --- a/src/crypto/x509/root_unix_test.go +++ b/src/crypto/x509/root_unix_test.go @@ -9,7 +9,6 @@ package x509 import ( "bytes" "fmt" - "io/ioutil" "os" "path/filepath" "reflect" @@ -147,7 +146,7 @@ func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) { os.Setenv(certFileEnv, origFile) }() - tmpDir, err := ioutil.TempDir(os.TempDir(), "x509-issue35325") + tmpDir, err := os.MkdirTemp(os.TempDir(), "x509-issue35325") if err != nil { t.Fatalf("Failed to create temporary directory: %v", err) } @@ -166,7 +165,7 @@ func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) { t.Fatalf("Failed to create certificate dir: %v", err) } certOutFile := filepath.Join(certDir, "cert.crt") - if err := ioutil.WriteFile(certOutFile, []byte(certPEM), 0655); err != nil { + if err := os.WriteFile(certOutFile, []byte(certPEM), 0655); err != nil { t.Fatalf("Failed to write certificate to file: %v", err) } certDirs = append(certDirs, certDir) diff --git a/src/debug/dwarf/dwarf5ranges_test.go b/src/debug/dwarf/dwarf5ranges_test.go index 2229d439a5..0ff1a55bc9 100644 --- a/src/debug/dwarf/dwarf5ranges_test.go +++ b/src/debug/dwarf/dwarf5ranges_test.go @@ -6,13 +6,13 @@ package dwarf import ( "encoding/binary" - "io/ioutil" + "os" "reflect" "testing" ) func TestDwarf5Ranges(t *testing.T) { - rngLists, err := ioutil.ReadFile("testdata/debug_rnglists") + rngLists, err := os.ReadFile("testdata/debug_rnglists") if err != nil { t.Fatalf("could not read test data: %v", err) } diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go index f93a5bf5e5..7347139b5d 100644 --- a/src/debug/gosym/pclntab_test.go +++ b/src/debug/gosym/pclntab_test.go @@ -10,7 +10,6 @@ import ( "debug/elf" "internal/testenv" "io" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -31,7 +30,7 @@ func dotest(t *testing.T) { t.Skipf("skipping on non-AMD64 system %s", runtime.GOARCH) } var err error - pclineTempDir, err = ioutil.TempDir("", "pclinetest") + pclineTempDir, err = os.MkdirTemp("", "pclinetest") if err != nil { t.Fatal(err) } @@ -278,7 +277,7 @@ func TestPCLine(t *testing.T) { // } // [END] func Test115PclnParsing(t *testing.T) { - zippedDat, err := ioutil.ReadFile("testdata/pcln115.gz") + zippedDat, err := os.ReadFile("testdata/pcln115.gz") if err != nil { t.Fatal(err) } diff --git a/src/debug/pe/file_test.go b/src/debug/pe/file_test.go index d96cd30904..58deff1450 100644 --- a/src/debug/pe/file_test.go +++ b/src/debug/pe/file_test.go @@ -8,7 +8,6 @@ import ( "bytes" "debug/dwarf" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -354,7 +353,7 @@ func testDWARF(t *testing.T, linktype int) { } testenv.MustHaveGoRun(t) - tmpdir, err := ioutil.TempDir("", "TestDWARF") + tmpdir, err := os.MkdirTemp("", "TestDWARF") if err != nil { t.Fatal(err) } @@ -473,7 +472,7 @@ func TestBSSHasZeros(t *testing.T) { t.Skip("skipping test: gcc is missing") } - tmpdir, err := ioutil.TempDir("", "TestBSSHasZeros") + tmpdir, err := os.MkdirTemp("", "TestBSSHasZeros") if err != nil { t.Fatal(err) } @@ -492,7 +491,7 @@ main(void) return 0; } ` - err = ioutil.WriteFile(srcpath, []byte(src), 0644) + err = os.WriteFile(srcpath, []byte(src), 0644) if err != nil { t.Fatal(err) } @@ -597,14 +596,14 @@ func TestBuildingWindowsGUI(t *testing.T) { if runtime.GOOS != "windows" { t.Skip("skipping windows only test") } - tmpdir, err := ioutil.TempDir("", "TestBuildingWindowsGUI") + tmpdir, err := os.MkdirTemp("", "TestBuildingWindowsGUI") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) src := filepath.Join(tmpdir, "a.go") - err = ioutil.WriteFile(src, []byte(`package main; func main() {}`), 0644) + err = os.WriteFile(src, []byte(`package main; func main() {}`), 0644) if err != nil { t.Fatal(err) } @@ -684,7 +683,7 @@ func TestInvalidOptionalHeaderMagic(t *testing.T) { func TestImportedSymbolsNoPanicMissingOptionalHeader(t *testing.T) { // https://golang.org/issue/30250 // ImportedSymbols shouldn't panic if optional headers is missing - data, err := ioutil.ReadFile("testdata/gcc-amd64-mingw-obj") + data, err := os.ReadFile("testdata/gcc-amd64-mingw-obj") if err != nil { t.Fatal(err) } diff --git a/src/embed/internal/embedtest/embedx_test.go b/src/embed/internal/embedtest/embedx_test.go index 53d45488f1..20d5a28c11 100644 --- a/src/embed/internal/embedtest/embedx_test.go +++ b/src/embed/internal/embedtest/embedx_test.go @@ -6,7 +6,7 @@ package embedtest_test import ( "embed" - "io/ioutil" + "os" "testing" ) @@ -59,7 +59,7 @@ func TestXGlobal(t *testing.T) { testString(t, concurrency2, "concurrency2", "Concurrency is not parallelism.\n") testString(t, string(glass2), "glass2", "I can eat glass and it doesn't hurt me.\n") - big, err := ioutil.ReadFile("testdata/ascii.txt") + big, err := os.ReadFile("testdata/ascii.txt") if err != nil { t.Fatal(err) } diff --git a/src/go/build/build_test.go b/src/go/build/build_test.go index 5a4a2d62f5..5a3e9ee714 100644 --- a/src/go/build/build_test.go +++ b/src/go/build/build_test.go @@ -8,7 +8,6 @@ import ( "flag" "internal/testenv" "io" - "io/ioutil" "os" "path/filepath" "reflect" @@ -454,7 +453,7 @@ func TestImportDirNotExist(t *testing.T) { testenv.MustHaveGoBuild(t) // really must just have source ctxt := Default - emptyDir, err := ioutil.TempDir("", t.Name()) + emptyDir, err := os.MkdirTemp("", t.Name()) if err != nil { t.Fatal(err) } @@ -592,7 +591,7 @@ func TestImportPackageOutsideModule(t *testing.T) { // Create a GOPATH in a temporary directory. We don't use testdata // because it's in GOROOT, which interferes with the module heuristic. - gopath, err := ioutil.TempDir("", "gobuild-notmodule") + gopath, err := os.MkdirTemp("", "gobuild-notmodule") if err != nil { t.Fatal(err) } @@ -600,7 +599,7 @@ func TestImportPackageOutsideModule(t *testing.T) { if err := os.MkdirAll(filepath.Join(gopath, "src/example.com/p"), 0777); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(gopath, "src/example.com/p/p.go"), []byte("package p"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(gopath, "src/example.com/p/p.go"), []byte("package p"), 0666); err != nil { t.Fatal(err) } @@ -656,12 +655,12 @@ func TestIssue23594(t *testing.T) { // Verifies golang.org/issue/34752. func TestMissingImportErrorRepetition(t *testing.T) { testenv.MustHaveGoBuild(t) // need 'go list' internally - tmp, err := ioutil.TempDir("", "") + tmp, err := os.MkdirTemp("", "") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmp) - if err := ioutil.WriteFile(filepath.Join(tmp, "go.mod"), []byte("module m"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(tmp, "go.mod"), []byte("module m"), 0666); err != nil { t.Fatal(err) } defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE")) diff --git a/src/go/doc/doc_test.go b/src/go/doc/doc_test.go index ab98bed62b..cbdca62aa1 100644 --- a/src/go/doc/doc_test.go +++ b/src/go/doc/doc_test.go @@ -13,7 +13,7 @@ import ( "go/printer" "go/token" "io/fs" - "io/ioutil" + "os" "path/filepath" "regexp" "strings" @@ -127,7 +127,7 @@ func test(t *testing.T, mode Mode) { // update golden file if necessary golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode)) if *update { - err := ioutil.WriteFile(golden, got, 0644) + err := os.WriteFile(golden, got, 0644) if err != nil { t.Error(err) } @@ -135,7 +135,7 @@ func test(t *testing.T, mode Mode) { } // get golden file - want, err := ioutil.ReadFile(golden) + want, err := os.ReadFile(golden) if err != nil { t.Error(err) continue diff --git a/src/go/format/benchmark_test.go b/src/go/format/benchmark_test.go index 7bd45c0e95..ac19aa3bf5 100644 --- a/src/go/format/benchmark_test.go +++ b/src/go/format/benchmark_test.go @@ -12,7 +12,7 @@ import ( "flag" "fmt" "go/format" - "io/ioutil" + "os" "testing" ) @@ -67,7 +67,7 @@ func BenchmarkFormat(b *testing.B) { if *debug { filename := t.name + ".src" - err := ioutil.WriteFile(filename, data, 0660) + err := os.WriteFile(filename, data, 0660) if err != nil { b.Fatalf("couldn't write %s: %v", filename, err) } diff --git a/src/go/format/format_test.go b/src/go/format/format_test.go index 58e088ede3..27f4c74cdf 100644 --- a/src/go/format/format_test.go +++ b/src/go/format/format_test.go @@ -9,7 +9,7 @@ import ( "go/ast" "go/parser" "go/token" - "io/ioutil" + "os" "strings" "testing" ) @@ -38,7 +38,7 @@ func diff(t *testing.T, dst, src []byte) { } func TestNode(t *testing.T) { - src, err := ioutil.ReadFile(testfile) + src, err := os.ReadFile(testfile) if err != nil { t.Fatal(err) } @@ -96,7 +96,7 @@ func TestNodeNoModify(t *testing.T) { } func TestSource(t *testing.T) { - src, err := ioutil.ReadFile(testfile) + src, err := os.ReadFile(testfile) if err != nil { t.Fatal(err) } diff --git a/src/go/importer/importer_test.go b/src/go/importer/importer_test.go index ff6e12c0da..0f5121d802 100644 --- a/src/go/importer/importer_test.go +++ b/src/go/importer/importer_test.go @@ -8,7 +8,6 @@ import ( "go/token" "internal/testenv" "io" - "io/ioutil" "os" "os/exec" "runtime" @@ -52,7 +51,7 @@ func TestForCompiler(t *testing.T) { mathBigInt := pkg.Scope().Lookup("Int") posn := fset.Position(mathBigInt.Pos()) // "$GOROOT/src/math/big/int.go:25:1" filename := strings.Replace(posn.Filename, "$GOROOT", runtime.GOROOT(), 1) - data, err := ioutil.ReadFile(filename) + data, err := os.ReadFile(filename) if err != nil { t.Fatalf("can't read file containing declaration of math/big.Int: %v", err) } diff --git a/src/go/internal/gccgoimporter/importer_test.go b/src/go/internal/gccgoimporter/importer_test.go index e4236a5867..35240c8fe6 100644 --- a/src/go/internal/gccgoimporter/importer_test.go +++ b/src/go/internal/gccgoimporter/importer_test.go @@ -7,7 +7,6 @@ package gccgoimporter import ( "go/types" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -150,7 +149,7 @@ func TestObjImporter(t *testing.T) { } t.Logf("gccgo version %d.%d", major, minor) - tmpdir, err := ioutil.TempDir("", "TestObjImporter") + tmpdir, err := os.MkdirTemp("", "TestObjImporter") if err != nil { t.Fatal(err) } @@ -159,7 +158,7 @@ func TestObjImporter(t *testing.T) { initmap := make(map[*types.Package]InitData) imp := GetImporter([]string{tmpdir}, initmap) - artmpdir, err := ioutil.TempDir("", "TestObjImporter") + artmpdir, err := os.MkdirTemp("", "TestObjImporter") if err != nil { t.Fatal(err) } diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 663753a18a..8991e3bdee 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -94,7 +94,7 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { } func mktmpdir(t *testing.T) string { - tmpdir, err := ioutil.TempDir("", "gcimporter_test") + tmpdir, err := os.MkdirTemp("", "gcimporter_test") if err != nil { t.Fatal("mktmpdir:", err) } @@ -199,7 +199,7 @@ func TestVersionHandling(t *testing.T) { // create file with corrupted export data // 1) read file - data, err := ioutil.ReadFile(filepath.Join(dir, name)) + data, err := os.ReadFile(filepath.Join(dir, name)) if err != nil { t.Fatal(err) } @@ -216,7 +216,7 @@ func TestVersionHandling(t *testing.T) { // 4) write the file pkgpath += "_corrupted" filename := filepath.Join(corruptdir, pkgpath) + ".a" - ioutil.WriteFile(filename, data, 0666) + os.WriteFile(filename, data, 0666) // test that importing the corrupted file results in an error _, err = Import(fset, make(map[string]*types.Package), pkgpath, corruptdir, nil) diff --git a/src/go/internal/srcimporter/srcimporter.go b/src/go/internal/srcimporter/srcimporter.go index 90bb3a9bc1..c4d501dcd9 100644 --- a/src/go/internal/srcimporter/srcimporter.go +++ b/src/go/internal/srcimporter/srcimporter.go @@ -14,7 +14,6 @@ import ( "go/token" "go/types" "io" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -200,7 +199,7 @@ func (p *Importer) parseFiles(dir string, filenames []string) ([]*ast.File, erro } func (p *Importer) cgo(bp *build.Package) (*ast.File, error) { - tmpdir, err := ioutil.TempDir("", "srcimporter") + tmpdir, err := os.MkdirTemp("", "srcimporter") if err != nil { return nil, err } diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go index d5c18a9e2d..41d9a52847 100644 --- a/src/go/parser/interface.go +++ b/src/go/parser/interface.go @@ -14,6 +14,7 @@ import ( "io" "io/fs" "io/ioutil" + "os" "path/filepath" "strings" ) @@ -39,7 +40,7 @@ func readSource(filename string, src interface{}) ([]byte, error) { } return nil, errors.New("invalid source") } - return ioutil.ReadFile(filename) + return os.ReadFile(filename) } // A Mode value is a set of flags (or 0). diff --git a/src/go/parser/performance_test.go b/src/go/parser/performance_test.go index f2732c0e2b..f81bcee969 100644 --- a/src/go/parser/performance_test.go +++ b/src/go/parser/performance_test.go @@ -6,14 +6,14 @@ package parser import ( "go/token" - "io/ioutil" + "os" "testing" ) var src = readFile("parser.go") func readFile(filename string) []byte { - data, err := ioutil.ReadFile(filename) + data, err := os.ReadFile(filename) if err != nil { panic(err) } diff --git a/src/go/printer/performance_test.go b/src/go/printer/performance_test.go index e23de3fbae..e655fa13ee 100644 --- a/src/go/printer/performance_test.go +++ b/src/go/printer/performance_test.go @@ -12,8 +12,8 @@ import ( "go/ast" "go/parser" "io" - "io/ioutil" "log" + "os" "testing" ) @@ -29,7 +29,7 @@ func testprint(out io.Writer, file *ast.File) { func initialize() { const filename = "testdata/parser.go" - src, err := ioutil.ReadFile(filename) + src, err := os.ReadFile(filename) if err != nil { log.Fatalf("%s", err) } diff --git a/src/go/printer/printer_test.go b/src/go/printer/printer_test.go index b64bc6bfb7..45e501115a 100644 --- a/src/go/printer/printer_test.go +++ b/src/go/printer/printer_test.go @@ -13,7 +13,7 @@ import ( "go/parser" "go/token" "io" - "io/ioutil" + "os" "path/filepath" "testing" "time" @@ -119,7 +119,7 @@ func diff(aname, bname string, a, b []byte) error { } func runcheck(t *testing.T, source, golden string, mode checkMode) { - src, err := ioutil.ReadFile(source) + src, err := os.ReadFile(source) if err != nil { t.Error(err) return @@ -133,14 +133,14 @@ func runcheck(t *testing.T, source, golden string, mode checkMode) { // update golden files if necessary if *update { - if err := ioutil.WriteFile(golden, res, 0644); err != nil { + if err := os.WriteFile(golden, res, 0644); err != nil { t.Error(err) } return } // get golden - gld, err := ioutil.ReadFile(golden) + gld, err := os.ReadFile(golden) if err != nil { t.Error(err) return @@ -552,7 +552,7 @@ func TestBaseIndent(t *testing.T) { // are not indented (because their values must not change) and make // this test fail. const filename = "printer.go" - src, err := ioutil.ReadFile(filename) + src, err := os.ReadFile(filename) if err != nil { panic(err) // error in test } @@ -639,7 +639,7 @@ func (l *limitWriter) Write(buf []byte) (n int, err error) { func TestWriteErrors(t *testing.T) { t.Parallel() const filename = "printer.go" - src, err := ioutil.ReadFile(filename) + src, err := os.ReadFile(filename) if err != nil { panic(err) // error in test } diff --git a/src/go/scanner/scanner_test.go b/src/go/scanner/scanner_test.go index 9d3bbbbb24..ab4c2dd962 100644 --- a/src/go/scanner/scanner_test.go +++ b/src/go/scanner/scanner_test.go @@ -6,7 +6,6 @@ package scanner import ( "go/token" - "io/ioutil" "os" "path/filepath" "runtime" @@ -893,7 +892,7 @@ func BenchmarkScan(b *testing.B) { func BenchmarkScanFile(b *testing.B) { b.StopTimer() const filename = "scanner.go" - src, err := ioutil.ReadFile(filename) + src, err := os.ReadFile(filename) if err != nil { panic(err) } diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index 37b287a20d..841ca24511 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -34,6 +34,7 @@ import ( "go/token" "internal/testenv" "io/ioutil" + "os" "path/filepath" "regexp" "strings" @@ -153,7 +154,7 @@ func errMap(t *testing.T, testname string, files []*ast.File) map[string][]strin for _, file := range files { filename := fset.Position(file.Package).Filename - src, err := ioutil.ReadFile(filename) + src, err := os.ReadFile(filename) if err != nil { t.Fatalf("%s: could not read %s", testname, filename) } diff --git a/src/go/types/hilbert_test.go b/src/go/types/hilbert_test.go index 9783ce6dc9..77954d2f8b 100644 --- a/src/go/types/hilbert_test.go +++ b/src/go/types/hilbert_test.go @@ -12,7 +12,7 @@ import ( "go/importer" "go/parser" "go/token" - "io/ioutil" + "os" "testing" . "go/types" @@ -27,7 +27,7 @@ func TestHilbert(t *testing.T) { // generate source src := program(*H, *out) if *out != "" { - ioutil.WriteFile(*out, src, 0666) + os.WriteFile(*out, src, 0666) return } diff --git a/src/hash/crc32/gen_const_ppc64le.go b/src/hash/crc32/gen_const_ppc64le.go index bfb3b3a227..d7af018af4 100644 --- a/src/hash/crc32/gen_const_ppc64le.go +++ b/src/hash/crc32/gen_const_ppc64le.go @@ -27,7 +27,7 @@ package main import ( "bytes" "fmt" - "io/ioutil" + "os" ) var blocking = 32 * 1024 @@ -103,7 +103,7 @@ func main() { genCrc32ConstTable(w, 0xeb31d82e, "Koop") b := w.Bytes() - err := ioutil.WriteFile("crc32_table_ppc64le.s", b, 0666) + err := os.WriteFile("crc32_table_ppc64le.s", b, 0666) if err != nil { fmt.Printf("can't write output: %s\n", err) } diff --git a/src/html/template/examplefiles_test.go b/src/html/template/examplefiles_test.go index 60518aee9e..5eb2597464 100644 --- a/src/html/template/examplefiles_test.go +++ b/src/html/template/examplefiles_test.go @@ -6,7 +6,6 @@ package template_test import ( "io" - "io/ioutil" "log" "os" "path/filepath" @@ -20,7 +19,7 @@ type templateFile struct { } func createTestDir(files []templateFile) string { - dir, err := ioutil.TempDir("", "template") + dir, err := os.MkdirTemp("", "template") if err != nil { log.Fatal(err) } diff --git a/src/html/template/template.go b/src/html/template/template.go index bc960afe5f..69312d36fd 100644 --- a/src/html/template/template.go +++ b/src/html/template/template.go @@ -8,7 +8,7 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" + "os" "path" "path/filepath" "sync" @@ -523,7 +523,7 @@ func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) { func readFileOS(file string) (name string, b []byte, err error) { name = filepath.Base(file) - b, err = ioutil.ReadFile(file) + b, err = os.ReadFile(file) return } diff --git a/src/image/color/palette/gen.go b/src/image/color/palette/gen.go index f8587db8f3..3243e53981 100644 --- a/src/image/color/palette/gen.go +++ b/src/image/color/palette/gen.go @@ -15,8 +15,8 @@ import ( "fmt" "go/format" "io" - "io/ioutil" "log" + "os" ) var filename = flag.String("output", "palette.go", "output file name") @@ -43,7 +43,7 @@ func main() { if err != nil { log.Fatal(err) } - err = ioutil.WriteFile(*filename, data, 0644) + err = os.WriteFile(*filename, data, 0644) if err != nil { log.Fatal(err) } diff --git a/src/image/gif/reader_test.go b/src/image/gif/reader_test.go index 29f47b6c08..5eec5ecb4a 100644 --- a/src/image/gif/reader_test.go +++ b/src/image/gif/reader_test.go @@ -11,7 +11,7 @@ import ( "image/color" "image/color/palette" "io" - "io/ioutil" + "os" "reflect" "runtime" "runtime/debug" @@ -424,7 +424,7 @@ func TestDecodeMemoryConsumption(t *testing.T) { } func BenchmarkDecode(b *testing.B) { - data, err := ioutil.ReadFile("../testdata/video-001.gif") + data, err := os.ReadFile("../testdata/video-001.gif") if err != nil { b.Fatal(err) } diff --git a/src/image/internal/imageutil/gen.go b/src/image/internal/imageutil/gen.go index bc85c512f9..36de5dc9cc 100644 --- a/src/image/internal/imageutil/gen.go +++ b/src/image/internal/imageutil/gen.go @@ -11,7 +11,6 @@ import ( "flag" "fmt" "go/format" - "io/ioutil" "log" "os" ) @@ -36,7 +35,7 @@ func main() { if err != nil { log.Fatal(err) } - if err := ioutil.WriteFile("impl.go", out, 0660); err != nil { + if err := os.WriteFile("impl.go", out, 0660); err != nil { log.Fatal(err) } } diff --git a/src/image/jpeg/reader_test.go b/src/image/jpeg/reader_test.go index 1e2798c945..bf07fadede 100644 --- a/src/image/jpeg/reader_test.go +++ b/src/image/jpeg/reader_test.go @@ -11,7 +11,6 @@ import ( "image" "image/color" "io" - "io/ioutil" "math/rand" "os" "strings" @@ -118,7 +117,7 @@ func (r *eofReader) Read(b []byte) (n int, err error) { func TestDecodeEOF(t *testing.T) { // Check that if reader returns final data and EOF at same time, jpeg handles it. - data, err := ioutil.ReadFile("../testdata/video-001.jpeg") + data, err := os.ReadFile("../testdata/video-001.jpeg") if err != nil { t.Fatal(err) } @@ -189,7 +188,7 @@ func pixString(pix []byte, stride, x, y int) string { } func TestTruncatedSOSDataDoesntPanic(t *testing.T) { - b, err := ioutil.ReadFile("../testdata/video-005.gray.q50.jpeg") + b, err := os.ReadFile("../testdata/video-005.gray.q50.jpeg") if err != nil { t.Fatal(err) } @@ -493,7 +492,7 @@ func TestExtraneousData(t *testing.T) { } func benchmarkDecode(b *testing.B, filename string) { - data, err := ioutil.ReadFile(filename) + data, err := os.ReadFile(filename) if err != nil { b.Fatal(err) } diff --git a/src/image/png/reader_test.go b/src/image/png/reader_test.go index 22c704e5cb..3937685294 100644 --- a/src/image/png/reader_test.go +++ b/src/image/png/reader_test.go @@ -11,7 +11,6 @@ import ( "image" "image/color" "io" - "io/ioutil" "os" "reflect" "strings" @@ -785,7 +784,7 @@ func TestDimensionOverflow(t *testing.T) { } func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) { - data, err := ioutil.ReadFile(filename) + data, err := os.ReadFile(filename) if err != nil { b.Fatal(err) } diff --git a/src/index/suffixarray/gen.go b/src/index/suffixarray/gen.go index 8c3de553c9..94184d71b6 100644 --- a/src/index/suffixarray/gen.go +++ b/src/index/suffixarray/gen.go @@ -11,8 +11,8 @@ package main import ( "bytes" - "io/ioutil" "log" + "os" "strings" ) @@ -20,7 +20,7 @@ func main() { log.SetPrefix("gen: ") log.SetFlags(0) - data, err := ioutil.ReadFile("sais.go") + data, err := os.ReadFile("sais.go") if err != nil { log.Fatal(err) } @@ -64,7 +64,7 @@ func main() { } } - if err := ioutil.WriteFile("sais2.go", buf.Bytes(), 0666); err != nil { + if err := os.WriteFile("sais2.go", buf.Bytes(), 0666); err != nil { log.Fatal(err) } } diff --git a/src/index/suffixarray/suffixarray_test.go b/src/index/suffixarray/suffixarray_test.go index a11a98dae0..44c5041535 100644 --- a/src/index/suffixarray/suffixarray_test.go +++ b/src/index/suffixarray/suffixarray_test.go @@ -8,8 +8,8 @@ import ( "bytes" "fmt" "io/fs" - "io/ioutil" "math/rand" + "os" "path/filepath" "regexp" "sort" @@ -498,14 +498,14 @@ func makeText(name string) ([]byte, error) { switch name { case "opticks": var err error - data, err = ioutil.ReadFile("../../testdata/Isaac.Newton-Opticks.txt") + data, err = os.ReadFile("../../testdata/Isaac.Newton-Opticks.txt") if err != nil { return nil, err } case "go": err := filepath.WalkDir("../..", func(path string, info fs.DirEntry, err error) error { if err == nil && strings.HasSuffix(path, ".go") && !info.IsDir() { - file, err := ioutil.ReadFile(path) + file, err := os.ReadFile(path) if err != nil { return err } diff --git a/src/internal/cpu/cpu_s390x_test.go b/src/internal/cpu/cpu_s390x_test.go index d910bbe695..ad86858db0 100644 --- a/src/internal/cpu/cpu_s390x_test.go +++ b/src/internal/cpu/cpu_s390x_test.go @@ -7,13 +7,13 @@ package cpu_test import ( "errors" . "internal/cpu" - "io/ioutil" + "os" "regexp" "testing" ) func getFeatureList() ([]string, error) { - cpuinfo, err := ioutil.ReadFile("/proc/cpuinfo") + cpuinfo, err := os.ReadFile("/proc/cpuinfo") if err != nil { return nil, err } diff --git a/src/internal/obscuretestdata/obscuretestdata.go b/src/internal/obscuretestdata/obscuretestdata.go index 06cd1df22c..5ea2cdf5d1 100644 --- a/src/internal/obscuretestdata/obscuretestdata.go +++ b/src/internal/obscuretestdata/obscuretestdata.go @@ -10,7 +10,6 @@ package obscuretestdata import ( "encoding/base64" "io" - "io/ioutil" "os" ) @@ -24,7 +23,7 @@ func DecodeToTempFile(name string) (path string, err error) { } defer f.Close() - tmp, err := ioutil.TempFile("", "obscuretestdata-decoded-") + tmp, err := os.CreateTemp("", "obscuretestdata-decoded-") if err != nil { return "", err } diff --git a/src/internal/poll/read_test.go b/src/internal/poll/read_test.go index 2d4ef97da0..598a52ee44 100644 --- a/src/internal/poll/read_test.go +++ b/src/internal/poll/read_test.go @@ -5,7 +5,6 @@ package poll_test import ( - "io/ioutil" "os" "runtime" "sync" @@ -22,7 +21,7 @@ func TestRead(t *testing.T) { go func(p string) { defer wg.Done() for i := 0; i < 100; i++ { - if _, err := ioutil.ReadFile(p); err != nil { + if _, err := os.ReadFile(p); err != nil { t.Error(err) return } diff --git a/src/internal/testenv/testenv_windows.go b/src/internal/testenv/testenv_windows.go index eb8d6ac165..4802b13951 100644 --- a/src/internal/testenv/testenv_windows.go +++ b/src/internal/testenv/testenv_windows.go @@ -5,7 +5,6 @@ package testenv import ( - "io/ioutil" "os" "path/filepath" "sync" @@ -16,7 +15,7 @@ var symlinkOnce sync.Once var winSymlinkErr error func initWinHasSymlink() { - tmpdir, err := ioutil.TempDir("", "symtest") + tmpdir, err := os.MkdirTemp("", "symtest") if err != nil { panic("failed to create temp directory: " + err.Error()) } diff --git a/src/internal/trace/gc_test.go b/src/internal/trace/gc_test.go index 4f9c77041a..9b9771e7b0 100644 --- a/src/internal/trace/gc_test.go +++ b/src/internal/trace/gc_test.go @@ -6,8 +6,8 @@ package trace import ( "bytes" - "io/ioutil" "math" + "os" "testing" "time" ) @@ -84,7 +84,7 @@ func TestMMUTrace(t *testing.T) { t.Skip("skipping in -short mode") } - data, err := ioutil.ReadFile("testdata/stress_1_10_good") + data, err := os.ReadFile("testdata/stress_1_10_good") if err != nil { t.Fatalf("failed to read input file: %v", err) } @@ -126,7 +126,7 @@ func TestMMUTrace(t *testing.T) { } func BenchmarkMMU(b *testing.B) { - data, err := ioutil.ReadFile("testdata/stress_1_10_good") + data, err := os.ReadFile("testdata/stress_1_10_good") if err != nil { b.Fatalf("failed to read input file: %v", err) } diff --git a/src/internal/trace/parser_test.go b/src/internal/trace/parser_test.go index 6d87970157..316220cfa8 100644 --- a/src/internal/trace/parser_test.go +++ b/src/internal/trace/parser_test.go @@ -47,7 +47,7 @@ func TestParseCanned(t *testing.T) { if testing.Short() && info.Size() > 10000 { continue } - data, err := ioutil.ReadFile(name) + data, err := os.ReadFile(name) if err != nil { t.Fatal(err) } diff --git a/src/log/syslog/syslog_test.go b/src/log/syslog/syslog_test.go index 8f472a56b7..207bcf57c1 100644 --- a/src/log/syslog/syslog_test.go +++ b/src/log/syslog/syslog_test.go @@ -10,7 +10,6 @@ import ( "bufio" "fmt" "io" - "io/ioutil" "log" "net" "os" @@ -88,8 +87,8 @@ func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, } else { // unix and unixgram: choose an address if none given if la == "" { - // use ioutil.TempFile to get a name that is unique - f, err := ioutil.TempFile("", "syslogtest") + // use os.CreateTemp to get a name that is unique + f, err := os.CreateTemp("", "syslogtest") if err != nil { log.Fatal("TempFile: ", err) } diff --git a/src/math/big/link_test.go b/src/math/big/link_test.go index 2212bd444f..42f9cefca0 100644 --- a/src/math/big/link_test.go +++ b/src/math/big/link_test.go @@ -7,7 +7,7 @@ package big import ( "bytes" "internal/testenv" - "io/ioutil" + "os" "os/exec" "path/filepath" "testing" @@ -27,7 +27,7 @@ func TestLinkerGC(t *testing.T) { import _ "math/big" func main() {} `) - if err := ioutil.WriteFile(goFile, file, 0644); err != nil { + if err := os.WriteFile(goFile, file, 0644); err != nil { t.Fatal(err) } cmd := exec.Command(goBin, "build", "-o", "x.exe", "x.go") diff --git a/src/math/bits/make_examples.go b/src/math/bits/make_examples.go index cd81cd6c4d..1d3ad53fe6 100644 --- a/src/math/bits/make_examples.go +++ b/src/math/bits/make_examples.go @@ -11,9 +11,9 @@ package main import ( "bytes" "fmt" - "io/ioutil" "log" "math/bits" + "os" ) const header = `// Copyright 2017 The Go Authors. All rights reserved. @@ -106,7 +106,7 @@ func main() { } } - if err := ioutil.WriteFile("example_test.go", w.Bytes(), 0666); err != nil { + if err := os.WriteFile("example_test.go", w.Bytes(), 0666); err != nil { log.Fatal(err) } } diff --git a/src/math/bits/make_tables.go b/src/math/bits/make_tables.go index ff2fe2e385..b068d5e0e3 100644 --- a/src/math/bits/make_tables.go +++ b/src/math/bits/make_tables.go @@ -13,8 +13,8 @@ import ( "fmt" "go/format" "io" - "io/ioutil" "log" + "os" ) var header = []byte(`// Copyright 2017 The Go Authors. All rights reserved. @@ -40,7 +40,7 @@ func main() { log.Fatal(err) } - err = ioutil.WriteFile("bits_tables.go", out, 0666) + err = os.WriteFile("bits_tables.go", out, 0666) if err != nil { log.Fatal(err) } diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go index 9c42ea8c02..fca5f9e15f 100644 --- a/src/mime/multipart/formdata.go +++ b/src/mime/multipart/formdata.go @@ -8,7 +8,6 @@ import ( "bytes" "errors" "io" - "io/ioutil" "math" "net/textproto" "os" @@ -91,7 +90,7 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) { } if n > maxMemory { // too big, write to disk and flush buffer - file, err := ioutil.TempFile("", "multipart-") + file, err := os.CreateTemp("", "multipart-") if err != nil { return nil, err } diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 06553636ee..0530c92c2e 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -10,7 +10,6 @@ import ( "context" "errors" "fmt" - "io/ioutil" "os" "path" "reflect" @@ -235,7 +234,7 @@ type resolvConfTest struct { } func newResolvConfTest() (*resolvConfTest, error) { - dir, err := ioutil.TempDir("", "go-resolvconftest") + dir, err := os.MkdirTemp("", "go-resolvconftest") if err != nil { return nil, err } diff --git a/src/net/error_test.go b/src/net/error_test.go index 7823fdf9d8..556eb8c8d4 100644 --- a/src/net/error_test.go +++ b/src/net/error_test.go @@ -13,7 +13,6 @@ import ( "internal/poll" "io" "io/fs" - "io/ioutil" "net/internal/socktest" "os" "runtime" @@ -730,7 +729,7 @@ func TestFileError(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - f, err := ioutil.TempFile("", "go-nettest") + f, err := os.CreateTemp("", "go-nettest") if err != nil { t.Fatal(err) } diff --git a/src/net/http/filetransport_test.go b/src/net/http/filetransport_test.go index fdfd44d967..b58888dcb1 100644 --- a/src/net/http/filetransport_test.go +++ b/src/net/http/filetransport_test.go @@ -6,7 +6,6 @@ package http import ( "io" - "io/ioutil" "os" "path/filepath" "testing" @@ -24,10 +23,10 @@ func checker(t *testing.T) func(string, error) { func TestFileTransport(t *testing.T) { check := checker(t) - dname, err := ioutil.TempDir("", "") + dname, err := os.MkdirTemp("", "") check("TempDir", err) fname := filepath.Join(dname, "foo.txt") - err = ioutil.WriteFile(fname, []byte("Bar"), 0644) + err = os.WriteFile(fname, []byte("Bar"), 0644) check("WriteFile", err) defer os.Remove(dname) defer os.Remove(fname) diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go index 2e4751114d..2499051625 100644 --- a/src/net/http/fs_test.go +++ b/src/net/http/fs_test.go @@ -79,7 +79,7 @@ func TestServeFile(t *testing.T) { var err error - file, err := ioutil.ReadFile(testFile) + file, err := os.ReadFile(testFile) if err != nil { t.Fatal("reading file:", err) } @@ -379,12 +379,12 @@ func mustRemoveAll(dir string) { func TestFileServerImplicitLeadingSlash(t *testing.T) { defer afterTest(t) - tempDir, err := ioutil.TempDir("", "") + tempDir, err := os.MkdirTemp("", "") if err != nil { t.Fatalf("TempDir: %v", err) } defer mustRemoveAll(tempDir) - if err := ioutil.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil { + if err := os.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil { t.Fatalf("WriteFile: %v", err) } ts := httptest.NewServer(StripPrefix("/bar/", FileServer(Dir(tempDir)))) @@ -1177,7 +1177,7 @@ func TestLinuxSendfile(t *testing.T) { filename := fmt.Sprintf("1kb-%d", os.Getpid()) filepath := path.Join(os.TempDir(), filename) - if err := ioutil.WriteFile(filepath, bytes.Repeat([]byte{'a'}, 1<<10), 0755); err != nil { + if err := os.WriteFile(filepath, bytes.Repeat([]byte{'a'}, 1<<10), 0755); err != nil { t.Fatal(err) } defer os.Remove(filepath) diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go index 689498e19d..29297b0e7b 100644 --- a/src/net/http/request_test.go +++ b/src/net/http/request_test.go @@ -12,7 +12,6 @@ import ( "encoding/base64" "fmt" "io" - "io/ioutil" "math" "mime/multipart" . "net/http" @@ -1164,7 +1163,7 @@ func BenchmarkFileAndServer_64MB(b *testing.B) { } func benchmarkFileAndServer(b *testing.B, n int64) { - f, err := ioutil.TempFile(os.TempDir(), "go-bench-http-file-and-server") + f, err := os.CreateTemp(os.TempDir(), "go-bench-http-file-and-server") if err != nil { b.Fatalf("Failed to create temp file: %v", err) } diff --git a/src/net/http/transfer_test.go b/src/net/http/transfer_test.go index 1f3d32526d..f0c28b2629 100644 --- a/src/net/http/transfer_test.go +++ b/src/net/http/transfer_test.go @@ -10,7 +10,6 @@ import ( "crypto/rand" "fmt" "io" - "io/ioutil" "os" "reflect" "strings" @@ -118,7 +117,7 @@ func TestTransferWriterWriteBodyReaderTypes(t *testing.T) { nBytes := int64(1 << 10) newFileFunc := func() (r io.Reader, done func(), err error) { - f, err := ioutil.TempFile("", "net-http-newfilefunc") + f, err := os.CreateTemp("", "net-http-newfilefunc") if err != nil { return nil, nil, err } diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index f22b798035..7f6e0938c2 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -23,7 +23,6 @@ import ( "go/token" "internal/nettrace" "io" - "io/ioutil" "log" mrand "math/rand" "net" @@ -5746,7 +5745,7 @@ func (c *testMockTCPConn) ReadFrom(r io.Reader) (int64, error) { func TestTransportRequestWriteRoundTrip(t *testing.T) { nBytes := int64(1 << 10) newFileFunc := func() (r io.Reader, done func(), err error) { - f, err := ioutil.TempFile("", "net-http-newfilefunc") + f, err := os.CreateTemp("", "net-http-newfilefunc") if err != nil { return nil, nil, err } diff --git a/src/net/mockserver_test.go b/src/net/mockserver_test.go index e085f4440b..9faf173679 100644 --- a/src/net/mockserver_test.go +++ b/src/net/mockserver_test.go @@ -9,16 +9,15 @@ package net import ( "errors" "fmt" - "io/ioutil" "os" "sync" "testing" "time" ) -// testUnixAddr uses ioutil.TempFile to get a name that is unique. +// testUnixAddr uses os.CreateTemp to get a name that is unique. func testUnixAddr() string { - f, err := ioutil.TempFile("", "go-nettest") + f, err := os.CreateTemp("", "go-nettest") if err != nil { panic(err) } diff --git a/src/net/net_windows_test.go b/src/net/net_windows_test.go index 8aa719f433..a0000950c6 100644 --- a/src/net/net_windows_test.go +++ b/src/net/net_windows_test.go @@ -9,7 +9,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "os" "os/exec" "regexp" @@ -176,7 +175,7 @@ func runCmd(args ...string) ([]byte, error) { } return b } - f, err := ioutil.TempFile("", "netcmd") + f, err := os.CreateTemp("", "netcmd") if err != nil { return nil, err } @@ -189,7 +188,7 @@ func runCmd(args ...string) ([]byte, error) { return nil, fmt.Errorf("%s failed: %v: %q", args[0], err, string(removeUTF8BOM(out))) } var err2 error - out, err2 = ioutil.ReadFile(f.Name()) + out, err2 = os.ReadFile(f.Name()) if err2 != nil { return nil, err2 } @@ -198,7 +197,7 @@ func runCmd(args ...string) ([]byte, error) { } return nil, fmt.Errorf("%s failed: %v", args[0], err) } - out, err = ioutil.ReadFile(f.Name()) + out, err = os.ReadFile(f.Name()) if err != nil { return nil, err } diff --git a/src/net/unixsock_test.go b/src/net/unixsock_test.go index 4b2cfc4d62..0b13bf655f 100644 --- a/src/net/unixsock_test.go +++ b/src/net/unixsock_test.go @@ -9,7 +9,6 @@ package net import ( "bytes" "internal/testenv" - "io/ioutil" "os" "reflect" "runtime" @@ -417,7 +416,7 @@ func TestUnixUnlink(t *testing.T) { checkExists(t, "after Listen") l.Close() checkNotExists(t, "after Listener close") - if err := ioutil.WriteFile(name, []byte("hello world"), 0666); err != nil { + if err := os.WriteFile(name, []byte("hello world"), 0666); err != nil { t.Fatalf("cannot recreate socket file: %v", err) } checkExists(t, "after writing temp file") diff --git a/src/os/error_test.go b/src/os/error_test.go index 060cf59875..6264ccc966 100644 --- a/src/os/error_test.go +++ b/src/os/error_test.go @@ -8,14 +8,13 @@ import ( "errors" "fmt" "io/fs" - "io/ioutil" "os" "path/filepath" "testing" ) func TestErrIsExist(t *testing.T) { - f, err := ioutil.TempFile("", "_Go_ErrIsExist") + f, err := os.CreateTemp("", "_Go_ErrIsExist") if err != nil { t.Fatalf("open ErrIsExist tempfile: %s", err) return @@ -55,7 +54,7 @@ func testErrNotExist(name string) string { } func TestErrIsNotExist(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "_Go_ErrIsNotExist") + tmpDir, err := os.MkdirTemp("", "_Go_ErrIsNotExist") if err != nil { t.Fatalf("create ErrIsNotExist tempdir: %s", err) return @@ -147,12 +146,12 @@ func TestIsPermission(t *testing.T) { } func TestErrPathNUL(t *testing.T) { - f, err := ioutil.TempFile("", "_Go_ErrPathNUL\x00") + f, err := os.CreateTemp("", "_Go_ErrPathNUL\x00") if err == nil { f.Close() t.Fatal("TempFile should have failed") } - f, err = ioutil.TempFile("", "_Go_ErrPathNUL") + f, err = os.CreateTemp("", "_Go_ErrPathNUL") if err != nil { t.Fatalf("open ErrPathNUL tempfile: %s", err) } diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index fc49b8a332..92429f63a5 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -645,7 +645,7 @@ func TestExtraFiles(t *testing.T) { t.Errorf("success trying to fetch %s; want an error", ts.URL) } - tf, err := ioutil.TempFile("", "") + tf, err := os.CreateTemp("", "") if err != nil { t.Fatalf("TempFile: %v", err) } diff --git a/src/os/exec/lp_unix_test.go b/src/os/exec/lp_unix_test.go index e4656cafb8..296480fd04 100644 --- a/src/os/exec/lp_unix_test.go +++ b/src/os/exec/lp_unix_test.go @@ -7,13 +7,12 @@ package exec import ( - "io/ioutil" "os" "testing" ) func TestLookPathUnixEmptyPath(t *testing.T) { - tmp, err := ioutil.TempDir("", "TestLookPathUnixEmptyPath") + tmp, err := os.MkdirTemp("", "TestLookPathUnixEmptyPath") if err != nil { t.Fatal("TempDir failed: ", err) } diff --git a/src/os/exec/lp_windows_test.go b/src/os/exec/lp_windows_test.go index 59b5f1c2c7..c6f3d5d406 100644 --- a/src/os/exec/lp_windows_test.go +++ b/src/os/exec/lp_windows_test.go @@ -11,7 +11,6 @@ import ( "fmt" "internal/testenv" "io" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -307,7 +306,7 @@ var lookPathTests = []lookPathTest{ } func TestLookPath(t *testing.T) { - tmp, err := ioutil.TempDir("", "TestLookPath") + tmp, err := os.MkdirTemp("", "TestLookPath") if err != nil { t.Fatal("TempDir failed: ", err) } @@ -504,7 +503,7 @@ var commandTests = []commandTest{ } func TestCommand(t *testing.T) { - tmp, err := ioutil.TempDir("", "TestCommand") + tmp, err := os.MkdirTemp("", "TestCommand") if err != nil { t.Fatal("TempDir failed: ", err) } @@ -529,7 +528,7 @@ func TestCommand(t *testing.T) { func buildPrintPathExe(t *testing.T, dir string) string { const name = "printpath" srcname := name + ".go" - err := ioutil.WriteFile(filepath.Join(dir, srcname), []byte(printpathSrc), 0644) + err := os.WriteFile(filepath.Join(dir, srcname), []byte(printpathSrc), 0644) if err != nil { t.Fatalf("failed to create source: %v", err) } diff --git a/src/os/fifo_test.go b/src/os/fifo_test.go index 3041dcfa02..2439192a9d 100644 --- a/src/os/fifo_test.go +++ b/src/os/fifo_test.go @@ -11,7 +11,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "os" "path/filepath" "runtime" @@ -31,7 +30,7 @@ func TestFifoEOF(t *testing.T) { t.Skip("skipping on OpenBSD; issue 25877") } - dir, err := ioutil.TempDir("", "TestFifoEOF") + dir, err := os.MkdirTemp("", "TestFifoEOF") if err != nil { t.Fatal(err) } diff --git a/src/os/os_test.go b/src/os/os_test.go index c5e5cbbb1b..765797f5fb 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -11,7 +11,7 @@ import ( "fmt" "internal/testenv" "io" - "io/ioutil" + "os" . "os" osexec "os/exec" "path/filepath" @@ -155,7 +155,7 @@ func localTmp() string { } func newFile(testName string, t *testing.T) (f *File) { - f, err := ioutil.TempFile(localTmp(), "_Go_"+testName) + f, err := os.CreateTemp(localTmp(), "_Go_"+testName) if err != nil { t.Fatalf("TempFile %s: %s", testName, err) } @@ -163,7 +163,7 @@ func newFile(testName string, t *testing.T) (f *File) { } func newDir(testName string, t *testing.T) (name string) { - name, err := ioutil.TempDir(localTmp(), "_Go_"+testName) + name, err := os.MkdirTemp(localTmp(), "_Go_"+testName) if err != nil { t.Fatalf("TempDir %s: %s", testName, err) } @@ -616,7 +616,7 @@ func TestReaddirNValues(t *testing.T) { if testing.Short() { t.Skip("test.short; skipping") } - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") if err != nil { t.Fatalf("TempDir: %v", err) } @@ -715,7 +715,7 @@ func TestReaddirStatFailures(t *testing.T) { // testing it wouldn't work. t.Skipf("skipping test on %v", runtime.GOOS) } - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") if err != nil { t.Fatalf("TempDir: %v", err) } @@ -776,7 +776,7 @@ func TestReaddirStatFailures(t *testing.T) { // Readdir on a regular file should fail. func TestReaddirOfFile(t *testing.T) { - f, err := ioutil.TempFile("", "_Go_ReaddirOfFile") + f, err := os.CreateTemp("", "_Go_ReaddirOfFile") if err != nil { t.Fatal(err) } @@ -867,7 +867,7 @@ func chtmpdir(t *testing.T) func() { if err != nil { t.Fatalf("chtmpdir: %v", err) } - d, err := ioutil.TempDir("", "test") + d, err := os.MkdirTemp("", "test") if err != nil { t.Fatalf("chtmpdir: %v", err) } @@ -992,12 +992,12 @@ func TestRenameOverwriteDest(t *testing.T) { toData := []byte("to") fromData := []byte("from") - err := ioutil.WriteFile(to, toData, 0777) + err := os.WriteFile(to, toData, 0777) if err != nil { t.Fatalf("write file %q failed: %v", to, err) } - err = ioutil.WriteFile(from, fromData, 0777) + err = os.WriteFile(from, fromData, 0777) if err != nil { t.Fatalf("write file %q failed: %v", from, err) } @@ -1341,7 +1341,7 @@ func testChtimes(t *testing.T, name string) { // the contents are accessed; also, it is set // whenever mtime is set. case "netbsd": - mounts, _ := ioutil.ReadFile("/proc/mounts") + mounts, _ := os.ReadFile("/proc/mounts") if strings.Contains(string(mounts), "noatime") { t.Logf("AccessTime didn't go backwards, but see a filesystem mounted noatime; ignoring. Issue 19293.") } else { @@ -1415,7 +1415,7 @@ func TestChdirAndGetwd(t *testing.T) { case "arm64": dirs = nil for _, d := range []string{"d1", "d2"} { - dir, err := ioutil.TempDir("", d) + dir, err := os.MkdirTemp("", d) if err != nil { t.Fatalf("TempDir: %v", err) } @@ -1509,7 +1509,7 @@ func TestProgWideChdir(t *testing.T) { c <- true t.Fatalf("Getwd: %v", err) } - d, err := ioutil.TempDir("", "test") + d, err := os.MkdirTemp("", "test") if err != nil { c <- true t.Fatalf("TempDir: %v", err) @@ -1576,7 +1576,7 @@ func TestSeek(t *testing.T) { off, err := f.Seek(tt.in, tt.whence) if off != tt.out || err != nil { if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == "linux" { - mounts, _ := ioutil.ReadFile("/proc/mounts") + mounts, _ := os.ReadFile("/proc/mounts") if strings.Contains(string(mounts), "reiserfs") { // Reiserfs rejects the big seeks. t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91") @@ -1858,7 +1858,7 @@ func TestWriteAt(t *testing.T) { t.Fatalf("WriteAt 7: %d, %v", n, err) } - b, err := ioutil.ReadFile(f.Name()) + b, err := os.ReadFile(f.Name()) if err != nil { t.Fatalf("ReadFile %s: %v", f.Name(), err) } @@ -1906,7 +1906,7 @@ func writeFile(t *testing.T, fname string, flag int, text string) string { t.Fatalf("WriteString: %d, %v", n, err) } f.Close() - data, err := ioutil.ReadFile(fname) + data, err := os.ReadFile(fname) if err != nil { t.Fatalf("ReadFile: %v", err) } @@ -1948,7 +1948,7 @@ func TestAppend(t *testing.T) { func TestStatDirWithTrailingSlash(t *testing.T) { // Create new temporary directory and arrange to clean it up. - path, err := ioutil.TempDir("", "_TestStatDirWithSlash_") + path, err := os.MkdirTemp("", "_TestStatDirWithSlash_") if err != nil { t.Fatalf("TempDir: %s", err) } @@ -2090,7 +2090,7 @@ func TestLargeWriteToConsole(t *testing.T) { func TestStatDirModeExec(t *testing.T) { const mode = 0111 - path, err := ioutil.TempDir("", "go-build") + path, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("Failed to create temp directory: %v", err) } @@ -2159,7 +2159,7 @@ func TestStatStdin(t *testing.T) { func TestStatRelativeSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := ioutil.TempDir("", "TestStatRelativeSymlink") + tmpdir, err := os.MkdirTemp("", "TestStatRelativeSymlink") if err != nil { t.Fatal(err) } @@ -2249,8 +2249,8 @@ func TestLongPath(t *testing.T) { t.Fatalf("MkdirAll failed: %v", err) } data := []byte("hello world\n") - if err := ioutil.WriteFile(sizedTempDir+"/foo.txt", data, 0644); err != nil { - t.Fatalf("ioutil.WriteFile() failed: %v", err) + if err := os.WriteFile(sizedTempDir+"/foo.txt", data, 0644); err != nil { + t.Fatalf("os.WriteFile() failed: %v", err) } if err := Rename(sizedTempDir+"/foo.txt", sizedTempDir+"/bar.txt"); err != nil { t.Fatalf("Rename failed: %v", err) @@ -2434,7 +2434,7 @@ func TestRemoveAllRace(t *testing.T) { n := runtime.GOMAXPROCS(16) defer runtime.GOMAXPROCS(n) - root, err := ioutil.TempDir("", "issue") + root, err := os.MkdirTemp("", "issue") if err != nil { t.Fatal(err) } diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go index 0bce2989c4..51693fd82a 100644 --- a/src/os/os_unix_test.go +++ b/src/os/os_unix_test.go @@ -8,7 +8,7 @@ package os_test import ( "io" - "io/ioutil" + "os" . "os" "path/filepath" "runtime" @@ -190,7 +190,7 @@ func TestReaddirRemoveRace(t *testing.T) { } dir := newDir("TestReaddirRemoveRace", t) defer RemoveAll(dir) - if err := ioutil.WriteFile(filepath.Join(dir, "some-file"), []byte("hello"), 0644); err != nil { + if err := os.WriteFile(filepath.Join(dir, "some-file"), []byte("hello"), 0644); err != nil { t.Fatal(err) } d, err := Open(dir) diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go index e002774844..8d1d1f61b2 100644 --- a/src/os/os_windows_test.go +++ b/src/os/os_windows_test.go @@ -13,7 +13,6 @@ import ( "internal/testenv" "io" "io/fs" - "io/ioutil" "os" osexec "os/exec" "path/filepath" @@ -31,7 +30,7 @@ import ( type syscallDescriptor = syscall.Handle func TestSameWindowsFile(t *testing.T) { - temp, err := ioutil.TempDir("", "TestSameWindowsFile") + temp, err := os.MkdirTemp("", "TestSameWindowsFile") if err != nil { t.Fatal(err) } @@ -90,7 +89,7 @@ type dirLinkTest struct { } func testDirLinks(t *testing.T, tests []dirLinkTest) { - tmpdir, err := ioutil.TempDir("", "testDirLinks") + tmpdir, err := os.MkdirTemp("", "testDirLinks") if err != nil { t.Fatal(err) } @@ -115,7 +114,7 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) { if err != nil { t.Fatal(err) } - err = ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("abc"), 0644) + err = os.WriteFile(filepath.Join(dir, "abc"), []byte("abc"), 0644) if err != nil { t.Fatal(err) } @@ -127,7 +126,7 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) { continue } - data, err := ioutil.ReadFile(filepath.Join(link, "abc")) + data, err := os.ReadFile(filepath.Join(link, "abc")) if err != nil { t.Errorf("failed to read abc file: %v", err) continue @@ -439,7 +438,7 @@ func TestNetworkSymbolicLink(t *testing.T) { const _NERR_ServerNotStarted = syscall.Errno(2114) - dir, err := ioutil.TempDir("", "TestNetworkSymbolicLink") + dir, err := os.MkdirTemp("", "TestNetworkSymbolicLink") if err != nil { t.Fatal(err) } @@ -600,7 +599,7 @@ func TestStatDir(t *testing.T) { } func TestOpenVolumeName(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "TestOpenVolumeName") + tmpdir, err := os.MkdirTemp("", "TestOpenVolumeName") if err != nil { t.Fatal(err) } @@ -619,7 +618,7 @@ func TestOpenVolumeName(t *testing.T) { want := []string{"file1", "file2", "file3", "gopher.txt"} sort.Strings(want) for _, name := range want { - err := ioutil.WriteFile(filepath.Join(tmpdir, name), nil, 0777) + err := os.WriteFile(filepath.Join(tmpdir, name), nil, 0777) if err != nil { t.Fatal(err) } @@ -643,7 +642,7 @@ func TestOpenVolumeName(t *testing.T) { } func TestDeleteReadOnly(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "TestDeleteReadOnly") + tmpdir, err := os.MkdirTemp("", "TestDeleteReadOnly") if err != nil { t.Fatal(err) } @@ -804,7 +803,7 @@ func compareCommandLineToArgvWithSyscall(t *testing.T, cmd string) { } func TestCmdArgs(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "TestCmdArgs") + tmpdir, err := os.MkdirTemp("", "TestCmdArgs") if err != nil { t.Fatal(err) } @@ -823,7 +822,7 @@ func main() { } ` src := filepath.Join(tmpdir, "main.go") - err = ioutil.WriteFile(src, []byte(prog), 0666) + err = os.WriteFile(src, []byte(prog), 0666) if err != nil { t.Fatal(err) } @@ -971,14 +970,14 @@ func TestSymlinkCreation(t *testing.T) { } t.Parallel() - temp, err := ioutil.TempDir("", "TestSymlinkCreation") + temp, err := os.MkdirTemp("", "TestSymlinkCreation") if err != nil { t.Fatal(err) } defer os.RemoveAll(temp) dummyFile := filepath.Join(temp, "file") - err = ioutil.WriteFile(dummyFile, []byte(""), 0644) + err = os.WriteFile(dummyFile, []byte(""), 0644) if err != nil { t.Fatal(err) } @@ -1207,7 +1206,7 @@ func mklinkd(t *testing.T, link, target string) { } func TestWindowsReadlink(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "TestWindowsReadlink") + tmpdir, err := os.MkdirTemp("", "TestWindowsReadlink") if err != nil { t.Fatal(err) } @@ -1272,7 +1271,7 @@ func TestWindowsReadlink(t *testing.T) { testReadlink(t, "reldirlink", "dir") file := filepath.Join(tmpdir, "file") - err = ioutil.WriteFile(file, []byte(""), 0666) + err = os.WriteFile(file, []byte(""), 0666) if err != nil { t.Fatal(err) } diff --git a/src/os/path_test.go b/src/os/path_test.go index 3fe9c5ffa3..b79d958711 100644 --- a/src/os/path_test.go +++ b/src/os/path_test.go @@ -6,7 +6,7 @@ package os_test import ( "internal/testenv" - "io/ioutil" + "os" . "os" "path/filepath" "runtime" @@ -78,7 +78,7 @@ func TestMkdirAll(t *testing.T) { func TestMkdirAllWithSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-") + tmpDir, err := os.MkdirTemp("", "TestMkdirAllWithSymlink-") if err != nil { t.Fatal(err) } diff --git a/src/os/path_windows_test.go b/src/os/path_windows_test.go index 862b404362..869db8fd6c 100644 --- a/src/os/path_windows_test.go +++ b/src/os/path_windows_test.go @@ -5,7 +5,6 @@ package os_test import ( - "io/ioutil" "os" "strings" "syscall" @@ -48,7 +47,7 @@ func TestFixLongPath(t *testing.T) { } func TestMkdirAllExtendedLength(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "TestMkdirAllExtendedLength") + tmpDir, err := os.MkdirTemp("", "TestMkdirAllExtendedLength") if err != nil { t.Fatal(err) } diff --git a/src/os/pipe_test.go b/src/os/pipe_test.go index 0593efec75..b98e53845c 100644 --- a/src/os/pipe_test.go +++ b/src/os/pipe_test.go @@ -14,7 +14,6 @@ import ( "internal/testenv" "io" "io/fs" - "io/ioutil" "os" osexec "os/exec" "os/signal" @@ -161,7 +160,7 @@ func testClosedPipeRace(t *testing.T, read bool) { // Get the amount we have to write to overload a pipe // with no reader. limit = 131073 - if b, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size"); err == nil { + if b, err := os.ReadFile("/proc/sys/fs/pipe-max-size"); err == nil { if i, err := strconv.Atoi(strings.TrimSpace(string(b))); err == nil { limit = i + 1 } diff --git a/src/os/readfrom_linux_test.go b/src/os/readfrom_linux_test.go index 00faf39fe5..37047175e6 100644 --- a/src/os/readfrom_linux_test.go +++ b/src/os/readfrom_linux_test.go @@ -8,8 +8,8 @@ import ( "bytes" "internal/poll" "io" - "io/ioutil" "math/rand" + "os" . "os" "path/filepath" "strconv" @@ -173,7 +173,7 @@ func TestCopyFileRange(t *testing.T) { }) t.Run("Nil", func(t *testing.T) { var nilFile *File - anyFile, err := ioutil.TempFile("", "") + anyFile, err := os.CreateTemp("", "") if err != nil { t.Fatal(err) } diff --git a/src/os/removeall_test.go b/src/os/removeall_test.go index 90efa313ea..3a2f6e3759 100644 --- a/src/os/removeall_test.go +++ b/src/os/removeall_test.go @@ -6,7 +6,7 @@ package os_test import ( "fmt" - "io/ioutil" + "os" . "os" "path/filepath" "runtime" @@ -15,7 +15,7 @@ import ( ) func TestRemoveAll(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "TestRemoveAll-") + tmpDir, err := os.MkdirTemp("", "TestRemoveAll-") if err != nil { t.Fatal(err) } @@ -128,7 +128,7 @@ func TestRemoveAllLarge(t *testing.T) { t.Skip("skipping in short mode") } - tmpDir, err := ioutil.TempDir("", "TestRemoveAll-") + tmpDir, err := os.MkdirTemp("", "TestRemoveAll-") if err != nil { t.Fatal(err) } @@ -169,7 +169,7 @@ func TestRemoveAllLongPath(t *testing.T) { t.Fatalf("Could not get wd: %s", err) } - startPath, err := ioutil.TempDir("", "TestRemoveAllLongPath-") + startPath, err := os.MkdirTemp("", "TestRemoveAllLongPath-") if err != nil { t.Fatalf("Could not create TempDir: %s", err) } @@ -211,7 +211,7 @@ func TestRemoveAllDot(t *testing.T) { if err != nil { t.Fatalf("Could not get wd: %s", err) } - tempDir, err := ioutil.TempDir("", "TestRemoveAllDot-") + tempDir, err := os.MkdirTemp("", "TestRemoveAllDot-") if err != nil { t.Fatalf("Could not create TempDir: %s", err) } @@ -236,7 +236,7 @@ func TestRemoveAllDot(t *testing.T) { func TestRemoveAllDotDot(t *testing.T) { t.Parallel() - tempDir, err := ioutil.TempDir("", "TestRemoveAllDotDot-") + tempDir, err := os.MkdirTemp("", "TestRemoveAllDotDot-") if err != nil { t.Fatal(err) } @@ -261,7 +261,7 @@ func TestRemoveAllDotDot(t *testing.T) { func TestRemoveReadOnlyDir(t *testing.T) { t.Parallel() - tempDir, err := ioutil.TempDir("", "TestRemoveReadOnlyDir-") + tempDir, err := os.MkdirTemp("", "TestRemoveReadOnlyDir-") if err != nil { t.Fatal(err) } @@ -298,7 +298,7 @@ func TestRemoveAllButReadOnlyAndPathError(t *testing.T) { t.Parallel() - tempDir, err := ioutil.TempDir("", "TestRemoveAllButReadOnly-") + tempDir, err := os.MkdirTemp("", "TestRemoveAllButReadOnly-") if err != nil { t.Fatal(err) } @@ -389,7 +389,7 @@ func TestRemoveUnreadableDir(t *testing.T) { t.Parallel() - tempDir, err := ioutil.TempDir("", "TestRemoveAllButReadOnly-") + tempDir, err := os.MkdirTemp("", "TestRemoveAllButReadOnly-") if err != nil { t.Fatal(err) } @@ -413,7 +413,7 @@ func TestRemoveAllWithMoreErrorThanReqSize(t *testing.T) { t.Skip("skipping in short mode") } - tmpDir, err := ioutil.TempDir("", "TestRemoveAll-") + tmpDir, err := os.MkdirTemp("", "TestRemoveAll-") if err != nil { t.Fatal(err) } diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go index 23e33fe82b..8945cbfccb 100644 --- a/src/os/signal/signal_test.go +++ b/src/os/signal/signal_test.go @@ -12,7 +12,6 @@ import ( "flag" "fmt" "internal/testenv" - "io/ioutil" "os" "os/exec" "runtime" @@ -304,7 +303,7 @@ func TestDetectNohup(t *testing.T) { os.Remove("nohup.out") out, err := exec.Command("/usr/bin/nohup", os.Args[0], "-test.run=TestDetectNohup", "-check_sighup_ignored").CombinedOutput() - data, _ := ioutil.ReadFile("nohup.out") + data, _ := os.ReadFile("nohup.out") os.Remove("nohup.out") if err != nil { t.Errorf("ran test with -check_sighup_ignored under nohup and it failed: expected success.\nError: %v\nOutput:\n%s%s", err, out, data) diff --git a/src/os/signal/signal_windows_test.go b/src/os/signal/signal_windows_test.go index c2b59010fc..4640428587 100644 --- a/src/os/signal/signal_windows_test.go +++ b/src/os/signal/signal_windows_test.go @@ -7,7 +7,6 @@ package signal import ( "bytes" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -57,7 +56,7 @@ func main() { } } ` - tmp, err := ioutil.TempDir("", "TestCtrlBreak") + tmp, err := os.MkdirTemp("", "TestCtrlBreak") if err != nil { t.Fatal("TempDir failed: ", err) } diff --git a/src/os/stat_test.go b/src/os/stat_test.go index 88b789080e..c409f0ff18 100644 --- a/src/os/stat_test.go +++ b/src/os/stat_test.go @@ -7,7 +7,6 @@ package os_test import ( "internal/testenv" "io/fs" - "io/ioutil" "os" "path/filepath" "runtime" @@ -186,7 +185,7 @@ func testSymlinkSameFile(t *testing.T, path, link string) { func TestDirAndSymlinkStats(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := ioutil.TempDir("", "TestDirAndSymlinkStats") + tmpdir, err := os.MkdirTemp("", "TestDirAndSymlinkStats") if err != nil { t.Fatal(err) } @@ -219,14 +218,14 @@ func TestDirAndSymlinkStats(t *testing.T) { func TestFileAndSymlinkStats(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := ioutil.TempDir("", "TestFileAndSymlinkStats") + tmpdir, err := os.MkdirTemp("", "TestFileAndSymlinkStats") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) file := filepath.Join(tmpdir, "file") - err = ioutil.WriteFile(file, []byte(""), 0644) + err = os.WriteFile(file, []byte(""), 0644) if err != nil { t.Fatal(err) } @@ -253,7 +252,7 @@ func TestFileAndSymlinkStats(t *testing.T) { func TestSymlinkWithTrailingSlash(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := ioutil.TempDir("", "TestSymlinkWithTrailingSlash") + tmpdir, err := os.MkdirTemp("", "TestSymlinkWithTrailingSlash") if err != nil { t.Fatal(err) } diff --git a/src/os/timeout_test.go b/src/os/timeout_test.go index d848e41642..0a39f46333 100644 --- a/src/os/timeout_test.go +++ b/src/os/timeout_test.go @@ -11,7 +11,6 @@ package os_test import ( "fmt" "io" - "io/ioutil" "math/rand" "os" "os/signal" @@ -29,7 +28,7 @@ func TestNonpollableDeadline(t *testing.T) { t.Skipf("skipping on %s", runtime.GOOS) } - f, err := ioutil.TempFile("", "ostest") + f, err := os.CreateTemp("", "ostest") if err != nil { t.Fatal(err) } diff --git a/src/os/user/lookup_plan9.go b/src/os/user/lookup_plan9.go index ea3ce0bc7c..33ae3a6adf 100644 --- a/src/os/user/lookup_plan9.go +++ b/src/os/user/lookup_plan9.go @@ -6,7 +6,6 @@ package user import ( "fmt" - "io/ioutil" "os" "syscall" ) @@ -23,7 +22,7 @@ func init() { } func current() (*User, error) { - ubytes, err := ioutil.ReadFile(userFile) + ubytes, err := os.ReadFile(userFile) if err != nil { return nil, fmt.Errorf("user: %s", err) } diff --git a/src/path/filepath/example_unix_walk_test.go b/src/path/filepath/example_unix_walk_test.go index 66dc7f6b53..c8a818fd6e 100644 --- a/src/path/filepath/example_unix_walk_test.go +++ b/src/path/filepath/example_unix_walk_test.go @@ -9,13 +9,12 @@ package filepath_test import ( "fmt" "io/fs" - "io/ioutil" "os" "path/filepath" ) func prepareTestDirTree(tree string) (string, error) { - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") if err != nil { return "", fmt.Errorf("error creating temp directory: %v\n", err) } diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go index 1c3b567fa3..48880ea439 100644 --- a/src/path/filepath/match_test.go +++ b/src/path/filepath/match_test.go @@ -7,7 +7,6 @@ package filepath_test import ( "fmt" "internal/testenv" - "io/ioutil" "os" . "path/filepath" "reflect" @@ -182,7 +181,7 @@ var globSymlinkTests = []struct { func TestGlobSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := ioutil.TempDir("", "globsymlink") + tmpDir, err := os.MkdirTemp("", "globsymlink") if err != nil { t.Fatal("creating temp dir:", err) } @@ -268,7 +267,7 @@ func TestWindowsGlob(t *testing.T) { t.Skipf("skipping windows specific test") } - tmpDir, err := ioutil.TempDir("", "TestWindowsGlob") + tmpDir, err := os.MkdirTemp("", "TestWindowsGlob") if err != nil { t.Fatal(err) } @@ -302,7 +301,7 @@ func TestWindowsGlob(t *testing.T) { } } for _, file := range files { - err := ioutil.WriteFile(Join(tmpDir, file), nil, 0666) + err := os.WriteFile(Join(tmpDir, file), nil, 0666) if err != nil { t.Fatal(err) } diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go index d760530e26..8616256ac0 100644 --- a/src/path/filepath/path_test.go +++ b/src/path/filepath/path_test.go @@ -9,7 +9,6 @@ import ( "fmt" "internal/testenv" "io/fs" - "io/ioutil" "os" "path/filepath" "reflect" @@ -416,7 +415,7 @@ func chtmpdir(t *testing.T) (restore func()) { if err != nil { t.Fatalf("chtmpdir: %v", err) } - d, err := ioutil.TempDir("", "test") + d, err := os.MkdirTemp("", "test") if err != nil { t.Fatalf("chtmpdir: %v", err) } @@ -459,7 +458,7 @@ func testWalk(t *testing.T, walk func(string, fs.WalkDirFunc) error, errVisit in defer restore() } - tmpDir, err := ioutil.TempDir("", "TestWalk") + tmpDir, err := os.MkdirTemp("", "TestWalk") if err != nil { t.Fatal("creating temp dir:", err) } @@ -563,7 +562,7 @@ func touch(t *testing.T, name string) { } func TestWalkSkipDirOnFile(t *testing.T) { - td, err := ioutil.TempDir("", "walktest") + td, err := os.MkdirTemp("", "walktest") if err != nil { t.Fatal(err) } @@ -613,7 +612,7 @@ func TestWalkSkipDirOnFile(t *testing.T) { } func TestWalkFileError(t *testing.T) { - td, err := ioutil.TempDir("", "walktest") + td, err := os.MkdirTemp("", "walktest") if err != nil { t.Fatal(err) } @@ -892,7 +891,7 @@ func testEvalSymlinksAfterChdir(t *testing.T, wd, path, want string) { func TestEvalSymlinks(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := ioutil.TempDir("", "evalsymlink") + tmpDir, err := os.MkdirTemp("", "evalsymlink") if err != nil { t.Fatal("creating temp dir:", err) } @@ -978,7 +977,7 @@ func TestEvalSymlinksIsNotExist(t *testing.T) { func TestIssue13582(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := ioutil.TempDir("", "issue13582") + tmpDir, err := os.MkdirTemp("", "issue13582") if err != nil { t.Fatal(err) } @@ -995,7 +994,7 @@ func TestIssue13582(t *testing.T) { t.Fatal(err) } file := filepath.Join(linkToDir, "file") - err = ioutil.WriteFile(file, nil, 0644) + err = os.WriteFile(file, nil, 0644) if err != nil { t.Fatal(err) } @@ -1065,7 +1064,7 @@ var absTests = []string{ } func TestAbs(t *testing.T) { - root, err := ioutil.TempDir("", "TestAbs") + root, err := os.MkdirTemp("", "TestAbs") if err != nil { t.Fatal("TempDir failed: ", err) } @@ -1136,7 +1135,7 @@ func TestAbs(t *testing.T) { // We test it separately from all other absTests because the empty string is not // a valid path, so it can't be used with os.Stat. func TestAbsEmptyString(t *testing.T) { - root, err := ioutil.TempDir("", "TestAbsEmptyString") + root, err := os.MkdirTemp("", "TestAbsEmptyString") if err != nil { t.Fatal("TempDir failed: ", err) } @@ -1357,7 +1356,7 @@ func TestBug3486(t *testing.T) { // https://golang.org/issue/3486 } func testWalkSymlink(t *testing.T, mklink func(target, link string) error) { - tmpdir, err := ioutil.TempDir("", "testWalkSymlink") + tmpdir, err := os.MkdirTemp("", "testWalkSymlink") if err != nil { t.Fatal(err) } @@ -1407,14 +1406,14 @@ func TestWalkSymlink(t *testing.T) { } func TestIssue29372(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "TestIssue29372") + tmpDir, err := os.MkdirTemp("", "TestIssue29372") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpDir) path := filepath.Join(tmpDir, "file.txt") - err = ioutil.WriteFile(path, nil, 0644) + err = os.WriteFile(path, nil, 0644) if err != nil { t.Fatal(err) } @@ -1443,7 +1442,7 @@ func TestEvalSymlinksAboveRoot(t *testing.T) { t.Parallel() - tmpDir, err := ioutil.TempDir("", "TestEvalSymlinksAboveRoot") + tmpDir, err := os.MkdirTemp("", "TestEvalSymlinksAboveRoot") if err != nil { t.Fatal(err) } @@ -1460,7 +1459,7 @@ func TestEvalSymlinksAboveRoot(t *testing.T) { if err := os.Symlink(filepath.Join(evalTmpDir, "a"), filepath.Join(evalTmpDir, "b")); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(evalTmpDir, "a", "file"), nil, 0666); err != nil { + if err := os.WriteFile(filepath.Join(evalTmpDir, "a", "file"), nil, 0666); err != nil { t.Fatal(err) } @@ -1491,7 +1490,7 @@ func TestEvalSymlinksAboveRoot(t *testing.T) { func TestEvalSymlinksAboveRootChdir(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := ioutil.TempDir("", "TestEvalSymlinksAboveRootChdir") + tmpDir, err := os.MkdirTemp("", "TestEvalSymlinksAboveRootChdir") if err != nil { t.Fatal(err) } @@ -1514,7 +1513,7 @@ func TestEvalSymlinksAboveRootChdir(t *testing.T) { if err := os.Symlink(subdir, "c"); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(subdir, "file"), nil, 0666); err != nil { + if err := os.WriteFile(filepath.Join(subdir, "file"), nil, 0666); err != nil { t.Fatal(err) } diff --git a/src/path/filepath/path_windows_test.go b/src/path/filepath/path_windows_test.go index 9309a7dc4d..1c3d84c62d 100644 --- a/src/path/filepath/path_windows_test.go +++ b/src/path/filepath/path_windows_test.go @@ -9,7 +9,6 @@ import ( "fmt" "internal/testenv" "io/fs" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -38,7 +37,7 @@ func testWinSplitListTestIsValid(t *testing.T, ti int, tt SplitListTest, perm fs.FileMode = 0700 ) - tmp, err := ioutil.TempDir("", "testWinSplitListTestIsValid") + tmp, err := os.MkdirTemp("", "testWinSplitListTestIsValid") if err != nil { t.Fatalf("TempDir failed: %v", err) } @@ -63,7 +62,7 @@ func testWinSplitListTestIsValid(t *testing.T, ti int, tt SplitListTest, return } fn, data := filepath.Join(dd, cmdfile), []byte("@echo "+d+"\r\n") - if err = ioutil.WriteFile(fn, data, perm); err != nil { + if err = os.WriteFile(fn, data, perm); err != nil { t.Errorf("%d,%d: WriteFile(%#q) failed: %v", ti, i, fn, err) return } @@ -104,7 +103,7 @@ func testWinSplitListTestIsValid(t *testing.T, ti int, tt SplitListTest, func TestWindowsEvalSymlinks(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := ioutil.TempDir("", "TestWindowsEvalSymlinks") + tmpDir, err := os.MkdirTemp("", "TestWindowsEvalSymlinks") if err != nil { t.Fatal(err) } @@ -162,13 +161,13 @@ func TestWindowsEvalSymlinks(t *testing.T) { // TestEvalSymlinksCanonicalNames verify that EvalSymlinks // returns "canonical" path names on windows. func TestEvalSymlinksCanonicalNames(t *testing.T) { - tmp, err := ioutil.TempDir("", "evalsymlinkcanonical") + tmp, err := os.MkdirTemp("", "evalsymlinkcanonical") if err != nil { t.Fatal("creating temp dir:", err) } defer os.RemoveAll(tmp) - // ioutil.TempDir might return "non-canonical" name. + // os.MkdirTemp might return "non-canonical" name. cTmpName, err := filepath.EvalSymlinks(tmp) if err != nil { t.Errorf("EvalSymlinks(%q) error: %v", tmp, err) @@ -418,7 +417,7 @@ func TestToNorm(t *testing.T) { {".", `\\localhost\c$`, `\\localhost\c$`}, } - tmp, err := ioutil.TempDir("", "testToNorm") + tmp, err := os.MkdirTemp("", "testToNorm") if err != nil { t.Fatal(err) } @@ -429,7 +428,7 @@ func TestToNorm(t *testing.T) { } }() - // ioutil.TempDir might return "non-canonical" name. + // os.MkdirTemp might return "non-canonical" name. ctmp, err := filepath.EvalSymlinks(tmp) if err != nil { t.Fatal(err) @@ -527,7 +526,7 @@ func TestNTNamespaceSymlink(t *testing.T) { t.Skip("skipping test because mklink command does not support junctions") } - tmpdir, err := ioutil.TempDir("", "TestNTNamespaceSymlink") + tmpdir, err := os.MkdirTemp("", "TestNTNamespaceSymlink") if err != nil { t.Fatal(err) } @@ -564,7 +563,7 @@ func TestNTNamespaceSymlink(t *testing.T) { testenv.MustHaveSymlink(t) file := filepath.Join(tmpdir, "file") - err = ioutil.WriteFile(file, []byte(""), 0666) + err = os.WriteFile(file, []byte(""), 0666) if err != nil { t.Fatal(err) } diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 5e22b7593e..58ad4f3eba 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -9,7 +9,6 @@ import ( "flag" "fmt" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -117,7 +116,7 @@ func buildTestProg(t *testing.T, binary string, flags ...string) (string, error) testprog.Lock() defer testprog.Unlock() if testprog.dir == "" { - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index ebbdbfe5b9..803b031873 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -10,7 +10,6 @@ import ( "bytes" "internal/testenv" "io" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -85,13 +84,13 @@ func TestCrashDumpsAllThreads(t *testing.T) { t.Parallel() - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } defer os.RemoveAll(dir) - if err := ioutil.WriteFile(filepath.Join(dir, "main.go"), []byte(crashDumpsAllThreadsSource), 0666); err != nil { + if err := os.WriteFile(filepath.Join(dir, "main.go"), []byte(crashDumpsAllThreadsSource), 0666); err != nil { t.Fatalf("failed to create Go file: %v", err) } diff --git a/src/runtime/debug/heapdump_test.go b/src/runtime/debug/heapdump_test.go index de1ec27d21..768934d05d 100644 --- a/src/runtime/debug/heapdump_test.go +++ b/src/runtime/debug/heapdump_test.go @@ -5,7 +5,6 @@ package debug_test import ( - "io/ioutil" "os" "runtime" . "runtime/debug" @@ -16,7 +15,7 @@ func TestWriteHeapDumpNonempty(t *testing.T) { if runtime.GOOS == "js" { t.Skipf("WriteHeapDump is not available on %s.", runtime.GOOS) } - f, err := ioutil.TempFile("", "heapdumptest") + f, err := os.CreateTemp("", "heapdumptest") if err != nil { t.Fatalf("TempFile failed: %v", err) } @@ -45,7 +44,7 @@ func TestWriteHeapDumpFinalizers(t *testing.T) { if runtime.GOOS == "js" { t.Skipf("WriteHeapDump is not available on %s.", runtime.GOOS) } - f, err := ioutil.TempFile("", "heapdumptest") + f, err := os.CreateTemp("", "heapdumptest") if err != nil { t.Fatalf("TempFile failed: %v", err) } diff --git a/src/runtime/debug_test.go b/src/runtime/debug_test.go index 722e81121f..a0b3f84382 100644 --- a/src/runtime/debug_test.go +++ b/src/runtime/debug_test.go @@ -17,7 +17,7 @@ package runtime_test import ( "fmt" - "io/ioutil" + "os" "regexp" "runtime" "runtime/debug" @@ -95,7 +95,7 @@ func debugCallTKill(tid int) error { // Linux-specific. func skipUnderDebugger(t *testing.T) { pid := syscall.Getpid() - status, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) + status, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) if err != nil { t.Logf("couldn't get proc tracer: %s", err) return diff --git a/src/runtime/env_plan9.go b/src/runtime/env_plan9.go index b7ea863735..f1ac4760a7 100644 --- a/src/runtime/env_plan9.go +++ b/src/runtime/env_plan9.go @@ -23,8 +23,8 @@ const ( // to the (possibly shared) Plan 9 environment, so that Setenv and Getenv // conform to the same Posix semantics as on other operating systems. // For Plan 9 shared environment semantics, instead of Getenv(key) and -// Setenv(key, value), one can use ioutil.ReadFile("/env/" + key) and -// ioutil.WriteFile("/env/" + key, value, 0666) respectively. +// Setenv(key, value), one can use os.ReadFile("/env/" + key) and +// os.WriteFile("/env/" + key, value, 0666) respectively. //go:nosplit func goenvs() { buf := make([]byte, envBufSize) diff --git a/src/runtime/internal/sys/gengoos.go b/src/runtime/internal/sys/gengoos.go index 2a4bf0c3b4..9bbc48d94f 100644 --- a/src/runtime/internal/sys/gengoos.go +++ b/src/runtime/internal/sys/gengoos.go @@ -9,8 +9,8 @@ package main import ( "bytes" "fmt" - "io/ioutil" "log" + "os" "strconv" "strings" ) @@ -18,7 +18,7 @@ import ( var gooses, goarches []string func main() { - data, err := ioutil.ReadFile("../../../go/build/syslist.go") + data, err := os.ReadFile("../../../go/build/syslist.go") if err != nil { log.Fatal(err) } @@ -68,7 +68,7 @@ func main() { } fmt.Fprintf(&buf, "const Goos%s = %d\n", strings.Title(goos), value) } - err := ioutil.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666) + err := os.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666) if err != nil { log.Fatal(err) } @@ -90,7 +90,7 @@ func main() { } fmt.Fprintf(&buf, "const Goarch%s = %d\n", strings.Title(goarch), value) } - err := ioutil.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666) + err := os.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666) if err != nil { log.Fatal(err) } diff --git a/src/runtime/memmove_linux_amd64_test.go b/src/runtime/memmove_linux_amd64_test.go index d0e8b42a5a..b3ccd907b9 100644 --- a/src/runtime/memmove_linux_amd64_test.go +++ b/src/runtime/memmove_linux_amd64_test.go @@ -5,7 +5,6 @@ package runtime_test import ( - "io/ioutil" "os" "reflect" "syscall" @@ -18,7 +17,7 @@ import ( func TestMemmoveOverflow(t *testing.T) { t.Parallel() // Create a temporary file. - tmp, err := ioutil.TempFile("", "go-memmovetest") + tmp, err := os.CreateTemp("", "go-memmovetest") if err != nil { t.Fatal(err) } diff --git a/src/runtime/mkduff.go b/src/runtime/mkduff.go index 6ddf0256e9..94ae75fbfe 100644 --- a/src/runtime/mkduff.go +++ b/src/runtime/mkduff.go @@ -27,8 +27,8 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "log" + "os" ) func main() { @@ -54,7 +54,7 @@ func gen(arch string, tags, zero, copy func(io.Writer)) { fmt.Fprintln(&buf) copy(&buf) - if err := ioutil.WriteFile("duff_"+arch+".s", buf.Bytes(), 0644); err != nil { + if err := os.WriteFile("duff_"+arch+".s", buf.Bytes(), 0644); err != nil { log.Fatalln(err) } } diff --git a/src/runtime/mkfastlog2table.go b/src/runtime/mkfastlog2table.go index 305c84a7c1..d650292394 100644 --- a/src/runtime/mkfastlog2table.go +++ b/src/runtime/mkfastlog2table.go @@ -12,9 +12,9 @@ package main import ( "bytes" "fmt" - "io/ioutil" "log" "math" + "os" ) func main() { @@ -36,7 +36,7 @@ func main() { } fmt.Fprintln(&buf, "}") - if err := ioutil.WriteFile("fastlog2table.go", buf.Bytes(), 0644); err != nil { + if err := os.WriteFile("fastlog2table.go", buf.Bytes(), 0644); err != nil { log.Fatalln(err) } } diff --git a/src/runtime/mksizeclasses.go b/src/runtime/mksizeclasses.go index 1a210953a4..b92d1fed5f 100644 --- a/src/runtime/mksizeclasses.go +++ b/src/runtime/mksizeclasses.go @@ -35,7 +35,6 @@ import ( "fmt" "go/format" "io" - "io/ioutil" "log" "os" ) @@ -65,7 +64,7 @@ func main() { if *stdout { _, err = os.Stdout.Write(out) } else { - err = ioutil.WriteFile("sizeclasses.go", out, 0666) + err = os.WriteFile("sizeclasses.go", out, 0666) } if err != nil { log.Fatal(err) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index b807072485..b6ee160e84 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -13,7 +13,6 @@ import ( "internal/profile" "internal/testenv" "io" - "io/ioutil" "math/big" "os" "os/exec" @@ -1179,7 +1178,7 @@ func TestLabelRace(t *testing.T) { // Check that there is no deadlock when the program receives SIGPROF while in // 64bit atomics' critical section. Used to happen on mips{,le}. See #20146. func TestAtomicLoadStore64(t *testing.T) { - f, err := ioutil.TempFile("", "profatomic") + f, err := os.CreateTemp("", "profatomic") if err != nil { t.Fatalf("TempFile: %v", err) } @@ -1208,7 +1207,7 @@ func TestAtomicLoadStore64(t *testing.T) { func TestTracebackAll(t *testing.T) { // With gccgo, if a profiling signal arrives at the wrong time // during traceback, it may crash or hang. See issue #29448. - f, err := ioutil.TempFile("", "proftraceback") + f, err := os.CreateTemp("", "proftraceback") if err != nil { t.Fatalf("TempFile: %v", err) } diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go index 8519af6985..bdb4454b6e 100644 --- a/src/runtime/pprof/proto.go +++ b/src/runtime/pprof/proto.go @@ -9,7 +9,7 @@ import ( "compress/gzip" "fmt" "io" - "io/ioutil" + "os" "runtime" "strconv" "time" @@ -575,7 +575,7 @@ func (b *profileBuilder) emitLocation() uint64 { // It saves the address ranges of the mappings in b.mem for use // when emitting locations. func (b *profileBuilder) readMapping() { - data, _ := ioutil.ReadFile("/proc/self/maps") + data, _ := os.ReadFile("/proc/self/maps") parseProcSelfMaps(data, b.addMapping) if len(b.mem) == 0 { // pprof expects a map entry, so fake one. b.addMappingEntry(0, 0, 0, "", "", true) diff --git a/src/runtime/pprof/proto_test.go b/src/runtime/pprof/proto_test.go index 3043d5353f..5eb1aab140 100644 --- a/src/runtime/pprof/proto_test.go +++ b/src/runtime/pprof/proto_test.go @@ -10,7 +10,6 @@ import ( "fmt" "internal/profile" "internal/testenv" - "io/ioutil" "os" "os/exec" "reflect" @@ -78,7 +77,7 @@ func testPCs(t *testing.T) (addr1, addr2 uint64, map1, map2 *profile.Mapping) { switch runtime.GOOS { case "linux", "android", "netbsd": // Figure out two addresses from /proc/self/maps. - mmap, err := ioutil.ReadFile("/proc/self/maps") + mmap, err := os.ReadFile("/proc/self/maps") if err != nil { t.Fatal(err) } diff --git a/src/runtime/race/output_test.go b/src/runtime/race/output_test.go index 5d0192f67f..986667332f 100644 --- a/src/runtime/race/output_test.go +++ b/src/runtime/race/output_test.go @@ -8,7 +8,6 @@ package race_test import ( "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -19,7 +18,7 @@ import ( ) func TestOutput(t *testing.T) { - pkgdir, err := ioutil.TempDir("", "go-build-race-output") + pkgdir, err := os.MkdirTemp("", "go-build-race-output") if err != nil { t.Fatal(err) } @@ -34,7 +33,7 @@ func TestOutput(t *testing.T) { t.Logf("test %v runs only on %v, skipping: ", test.name, test.goos) continue } - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } diff --git a/src/runtime/race/testdata/io_test.go b/src/runtime/race/testdata/io_test.go index 30a121bee4..c5055f7837 100644 --- a/src/runtime/race/testdata/io_test.go +++ b/src/runtime/race/testdata/io_test.go @@ -6,7 +6,6 @@ package race_test import ( "fmt" - "io/ioutil" "net" "net/http" "os" @@ -18,7 +17,7 @@ import ( func TestNoRaceIOFile(t *testing.T) { x := 0 - path, _ := ioutil.TempDir("", "race_test") + path, _ := os.MkdirTemp("", "race_test") fname := filepath.Join(path, "data") go func() { x = 42 diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go index e52bd1c4c4..5df8c3c745 100644 --- a/src/runtime/runtime-gdb_test.go +++ b/src/runtime/runtime-gdb_test.go @@ -8,7 +8,6 @@ import ( "bytes" "fmt" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -170,7 +169,7 @@ func testGdbPython(t *testing.T, cgo bool) { checkGdbVersion(t) checkGdbPython(t) - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } @@ -195,7 +194,7 @@ func testGdbPython(t *testing.T, cgo bool) { } } - err = ioutil.WriteFile(filepath.Join(dir, "main.go"), src, 0644) + err = os.WriteFile(filepath.Join(dir, "main.go"), src, 0644) if err != nil { t.Fatalf("failed to create file: %v", err) } @@ -404,7 +403,7 @@ func TestGdbBacktrace(t *testing.T) { t.Parallel() checkGdbVersion(t) - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } @@ -412,7 +411,7 @@ func TestGdbBacktrace(t *testing.T) { // Build the source code. src := filepath.Join(dir, "main.go") - err = ioutil.WriteFile(src, []byte(backtraceSource), 0644) + err = os.WriteFile(src, []byte(backtraceSource), 0644) if err != nil { t.Fatalf("failed to create file: %v", err) } @@ -482,7 +481,7 @@ func TestGdbAutotmpTypes(t *testing.T) { t.Skip("TestGdbAutotmpTypes is too slow on aix/ppc64") } - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } @@ -490,7 +489,7 @@ func TestGdbAutotmpTypes(t *testing.T) { // Build the source code. src := filepath.Join(dir, "main.go") - err = ioutil.WriteFile(src, []byte(autotmpTypeSource), 0644) + err = os.WriteFile(src, []byte(autotmpTypeSource), 0644) if err != nil { t.Fatalf("failed to create file: %v", err) } @@ -551,7 +550,7 @@ func TestGdbConst(t *testing.T) { t.Parallel() checkGdbVersion(t) - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } @@ -559,7 +558,7 @@ func TestGdbConst(t *testing.T) { // Build the source code. src := filepath.Join(dir, "main.go") - err = ioutil.WriteFile(src, []byte(constsSource), 0644) + err = os.WriteFile(src, []byte(constsSource), 0644) if err != nil { t.Fatalf("failed to create file: %v", err) } @@ -618,7 +617,7 @@ func TestGdbPanic(t *testing.T) { t.Parallel() checkGdbVersion(t) - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } @@ -626,7 +625,7 @@ func TestGdbPanic(t *testing.T) { // Build the source code. src := filepath.Join(dir, "main.go") - err = ioutil.WriteFile(src, []byte(panicSource), 0644) + err = os.WriteFile(src, []byte(panicSource), 0644) if err != nil { t.Fatalf("failed to create file: %v", err) } @@ -696,7 +695,7 @@ func TestGdbInfCallstack(t *testing.T) { t.Parallel() checkGdbVersion(t) - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } @@ -704,7 +703,7 @@ func TestGdbInfCallstack(t *testing.T) { // Build the source code. src := filepath.Join(dir, "main.go") - err = ioutil.WriteFile(src, []byte(InfCallstackSource), 0644) + err = os.WriteFile(src, []byte(InfCallstackSource), 0644) if err != nil { t.Fatalf("failed to create file: %v", err) } diff --git a/src/runtime/runtime-lldb_test.go b/src/runtime/runtime-lldb_test.go index 1e2e5d5be9..c923b872aa 100644 --- a/src/runtime/runtime-lldb_test.go +++ b/src/runtime/runtime-lldb_test.go @@ -6,7 +6,6 @@ package runtime_test import ( "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -143,20 +142,20 @@ func TestLldbPython(t *testing.T) { checkLldbPython(t) - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } defer os.RemoveAll(dir) src := filepath.Join(dir, "main.go") - err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644) + err = os.WriteFile(src, []byte(lldbHelloSource), 0644) if err != nil { t.Fatalf("failed to create src file: %v", err) } mod := filepath.Join(dir, "go.mod") - err = ioutil.WriteFile(mod, []byte("module lldbtest"), 0644) + err = os.WriteFile(mod, []byte("module lldbtest"), 0644) if err != nil { t.Fatalf("failed to create mod file: %v", err) } @@ -172,7 +171,7 @@ func TestLldbPython(t *testing.T) { } src = filepath.Join(dir, "script.py") - err = ioutil.WriteFile(src, []byte(lldbScriptSource), 0755) + err = os.WriteFile(src, []byte(lldbScriptSource), 0755) if err != nil { t.Fatalf("failed to create script: %v", err) } diff --git a/src/runtime/signal_windows_test.go b/src/runtime/signal_windows_test.go index f99857193c..a5a885c2f7 100644 --- a/src/runtime/signal_windows_test.go +++ b/src/runtime/signal_windows_test.go @@ -7,7 +7,6 @@ import ( "bytes" "fmt" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -28,7 +27,7 @@ func TestVectoredHandlerDontCrashOnLibrary(t *testing.T) { testenv.MustHaveExecPath(t, "gcc") testprog.Lock() defer testprog.Unlock() - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } @@ -93,7 +92,7 @@ func TestLibraryCtrlHandler(t *testing.T) { testenv.MustHaveExecPath(t, "gcc") testprog.Lock() defer testprog.Unlock() - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go index a20573eb6a..fb215b3c31 100644 --- a/src/runtime/syscall_windows_test.go +++ b/src/runtime/syscall_windows_test.go @@ -10,7 +10,6 @@ import ( "internal/syscall/windows/sysdll" "internal/testenv" "io" - "io/ioutil" "math" "os" "os/exec" @@ -446,7 +445,7 @@ func TestStdcallAndCDeclCallbacks(t *testing.T) { if _, err := exec.LookPath("gcc"); err != nil { t.Skip("skipping test: gcc is missing") } - tmp, err := ioutil.TempDir("", "TestCDeclCallback") + tmp, err := os.MkdirTemp("", "TestCDeclCallback") if err != nil { t.Fatal("TempDir failed: ", err) } @@ -602,14 +601,14 @@ uintptr_t cfunc(callback f, uintptr_t n) { return r; } ` - tmpdir, err := ioutil.TempDir("", "TestReturnAfterStackGrowInCallback") + tmpdir, err := os.MkdirTemp("", "TestReturnAfterStackGrowInCallback") if err != nil { t.Fatal("TempDir failed: ", err) } defer os.RemoveAll(tmpdir) srcname := "mydll.c" - err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) + err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) if err != nil { t.Fatal(err) } @@ -671,14 +670,14 @@ uintptr_t cfunc(uintptr_t a, double b, float c, double d) { return 0; } ` - tmpdir, err := ioutil.TempDir("", "TestFloatArgs") + tmpdir, err := os.MkdirTemp("", "TestFloatArgs") if err != nil { t.Fatal("TempDir failed: ", err) } defer os.RemoveAll(tmpdir) srcname := "mydll.c" - err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) + err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) if err != nil { t.Fatal(err) } @@ -733,14 +732,14 @@ double cfuncDouble(uintptr_t a, double b, float c, double d) { return 0; } ` - tmpdir, err := ioutil.TempDir("", "TestFloatReturn") + tmpdir, err := os.MkdirTemp("", "TestFloatReturn") if err != nil { t.Fatal("TempDir failed: ", err) } defer os.RemoveAll(tmpdir) srcname := "mydll.c" - err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) + err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) if err != nil { t.Fatal(err) } @@ -948,7 +947,7 @@ func TestDLLPreloadMitigation(t *testing.T) { t.Skip("skipping test: gcc is missing") } - tmpdir, err := ioutil.TempDir("", "TestDLLPreloadMitigation") + tmpdir, err := os.MkdirTemp("", "TestDLLPreloadMitigation") if err != nil { t.Fatal("TempDir failed: ", err) } @@ -975,7 +974,7 @@ uintptr_t cfunc(void) { } ` srcname := "nojack.c" - err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) + err = os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) if err != nil { t.Fatal(err) } @@ -1035,7 +1034,7 @@ func TestBigStackCallbackSyscall(t *testing.T) { t.Fatal("Abs failed: ", err) } - tmpdir, err := ioutil.TempDir("", "TestBigStackCallback") + tmpdir, err := os.MkdirTemp("", "TestBigStackCallback") if err != nil { t.Fatal("TempDir failed: ", err) } @@ -1184,14 +1183,14 @@ func BenchmarkOsYield(b *testing.B) { } func BenchmarkRunningGoProgram(b *testing.B) { - tmpdir, err := ioutil.TempDir("", "BenchmarkRunningGoProgram") + tmpdir, err := os.MkdirTemp("", "BenchmarkRunningGoProgram") if err != nil { b.Fatal(err) } defer os.RemoveAll(tmpdir) src := filepath.Join(tmpdir, "main.go") - err = ioutil.WriteFile(src, []byte(benchmarkRunningGoProgram), 0666) + err = os.WriteFile(src, []byte(benchmarkRunningGoProgram), 0666) if err != nil { b.Fatal(err) } diff --git a/src/runtime/testdata/testprog/memprof.go b/src/runtime/testdata/testprog/memprof.go index 7b134bc078..0392e60f84 100644 --- a/src/runtime/testdata/testprog/memprof.go +++ b/src/runtime/testdata/testprog/memprof.go @@ -7,7 +7,6 @@ package main import ( "bytes" "fmt" - "io/ioutil" "os" "runtime" "runtime/pprof" @@ -31,7 +30,7 @@ func MemProf() { runtime.GC() - f, err := ioutil.TempFile("", "memprof") + f, err := os.CreateTemp("", "memprof") if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(2) diff --git a/src/runtime/testdata/testprog/syscalls_linux.go b/src/runtime/testdata/testprog/syscalls_linux.go index b8ac087626..48f8014237 100644 --- a/src/runtime/testdata/testprog/syscalls_linux.go +++ b/src/runtime/testdata/testprog/syscalls_linux.go @@ -7,7 +7,6 @@ package main import ( "bytes" "fmt" - "io/ioutil" "os" "syscall" ) @@ -17,7 +16,7 @@ func gettid() int { } func tidExists(tid int) (exists, supported bool) { - stat, err := ioutil.ReadFile(fmt.Sprintf("/proc/self/task/%d/stat", tid)) + stat, err := os.ReadFile(fmt.Sprintf("/proc/self/task/%d/stat", tid)) if os.IsNotExist(err) { return false, true } diff --git a/src/runtime/testdata/testprog/timeprof.go b/src/runtime/testdata/testprog/timeprof.go index 0702885369..1e90af4033 100644 --- a/src/runtime/testdata/testprog/timeprof.go +++ b/src/runtime/testdata/testprog/timeprof.go @@ -6,7 +6,6 @@ package main import ( "fmt" - "io/ioutil" "os" "runtime/pprof" "time" @@ -17,7 +16,7 @@ func init() { } func TimeProf() { - f, err := ioutil.TempFile("", "timeprof") + f, err := os.CreateTemp("", "timeprof") if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(2) diff --git a/src/runtime/testdata/testprog/vdso.go b/src/runtime/testdata/testprog/vdso.go index ef92f48758..d2a300d8f2 100644 --- a/src/runtime/testdata/testprog/vdso.go +++ b/src/runtime/testdata/testprog/vdso.go @@ -8,7 +8,6 @@ package main import ( "fmt" - "io/ioutil" "os" "runtime/pprof" "time" @@ -19,7 +18,7 @@ func init() { } func signalInVDSO() { - f, err := ioutil.TempFile("", "timeprofnow") + f, err := os.CreateTemp("", "timeprofnow") if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(2) diff --git a/src/runtime/testdata/testprogcgo/pprof.go b/src/runtime/testdata/testprogcgo/pprof.go index 00f2c42e93..3b73fa0bdd 100644 --- a/src/runtime/testdata/testprogcgo/pprof.go +++ b/src/runtime/testdata/testprogcgo/pprof.go @@ -60,7 +60,6 @@ import "C" import ( "fmt" - "io/ioutil" "os" "runtime" "runtime/pprof" @@ -75,7 +74,7 @@ func init() { func CgoPprof() { runtime.SetCgoTraceback(0, unsafe.Pointer(C.pprofCgoTraceback), nil, nil) - f, err := ioutil.TempFile("", "prof") + f, err := os.CreateTemp("", "prof") if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(2) diff --git a/src/runtime/testdata/testprogcgo/threadpprof.go b/src/runtime/testdata/testprogcgo/threadpprof.go index 37a2a1ab65..feb774ba59 100644 --- a/src/runtime/testdata/testprogcgo/threadpprof.go +++ b/src/runtime/testdata/testprogcgo/threadpprof.go @@ -74,7 +74,6 @@ import "C" import ( "fmt" - "io/ioutil" "os" "runtime" "runtime/pprof" @@ -97,7 +96,7 @@ func CgoPprofThreadNoTraceback() { } func pprofThread() { - f, err := ioutil.TempFile("", "prof") + f, err := os.CreateTemp("", "prof") if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(2) diff --git a/src/runtime/trace/trace_test.go b/src/runtime/trace/trace_test.go index 235845df4e..b316eafe4c 100644 --- a/src/runtime/trace/trace_test.go +++ b/src/runtime/trace/trace_test.go @@ -10,7 +10,6 @@ import ( "internal/race" "internal/trace" "io" - "io/ioutil" "net" "os" "runtime" @@ -586,7 +585,7 @@ func saveTrace(t *testing.T, buf *bytes.Buffer, name string) { if !*saveTraces { return } - if err := ioutil.WriteFile(name+".trace", buf.Bytes(), 0600); err != nil { + if err := os.WriteFile(name+".trace", buf.Bytes(), 0600); err != nil { t.Errorf("failed to write trace file: %s", err) } } diff --git a/src/runtime/wincallback.go b/src/runtime/wincallback.go index c022916422..fb452222da 100644 --- a/src/runtime/wincallback.go +++ b/src/runtime/wincallback.go @@ -11,7 +11,6 @@ package main import ( "bytes" "fmt" - "io/ioutil" "os" ) @@ -38,7 +37,7 @@ TEXT runtime·callbackasm(SB),7,$0 } filename := fmt.Sprintf("zcallback_windows.s") - err := ioutil.WriteFile(filename, buf.Bytes(), 0666) + err := os.WriteFile(filename, buf.Bytes(), 0666) if err != nil { fmt.Fprintf(os.Stderr, "wincallback: %s\n", err) os.Exit(2) @@ -66,7 +65,7 @@ TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0 buf.WriteString("\tB\truntime·callbackasm1(SB)\n") } - err := ioutil.WriteFile("zcallback_windows_arm.s", buf.Bytes(), 0666) + err := os.WriteFile("zcallback_windows_arm.s", buf.Bytes(), 0666) if err != nil { fmt.Fprintf(os.Stderr, "wincallback: %s\n", err) os.Exit(2) @@ -82,7 +81,7 @@ package runtime const cb_max = %d // maximum number of windows callbacks allowed `, maxCallback)) - err := ioutil.WriteFile("zcallback_windows.go", buf.Bytes(), 0666) + err := os.WriteFile("zcallback_windows.go", buf.Bytes(), 0666) if err != nil { fmt.Fprintf(os.Stderr, "wincallback: %s\n", err) os.Exit(2) diff --git a/src/sort/genzfunc.go b/src/sort/genzfunc.go index 66408d26c6..e7eb573737 100644 --- a/src/sort/genzfunc.go +++ b/src/sort/genzfunc.go @@ -20,8 +20,8 @@ import ( "go/format" "go/parser" "go/token" - "io/ioutil" "log" + "os" "regexp" ) @@ -92,7 +92,7 @@ func main() { out.Write(src) const target = "zfuncversion.go" - if err := ioutil.WriteFile(target, out.Bytes(), 0644); err != nil { + if err := os.WriteFile(target, out.Bytes(), 0644); err != nil { log.Fatal(err) } } diff --git a/src/strconv/makeisprint.go b/src/strconv/makeisprint.go index 1a3248f308..0e6e90a6c6 100644 --- a/src/strconv/makeisprint.go +++ b/src/strconv/makeisprint.go @@ -17,8 +17,8 @@ import ( "flag" "fmt" "go/format" - "io/ioutil" "log" + "os" "unicode" ) @@ -196,7 +196,7 @@ func main() { if err != nil { log.Fatal(err) } - err = ioutil.WriteFile(*filename, data, 0644) + err = os.WriteFile(*filename, data, 0644) if err != nil { log.Fatal(err) } diff --git a/src/syscall/dirent_test.go b/src/syscall/dirent_test.go index f63153340a..7dac98ff4b 100644 --- a/src/syscall/dirent_test.go +++ b/src/syscall/dirent_test.go @@ -9,7 +9,6 @@ package syscall_test import ( "bytes" "fmt" - "io/ioutil" "os" "path/filepath" "runtime" @@ -27,7 +26,7 @@ func TestDirent(t *testing.T) { filenameMinSize = 11 ) - d, err := ioutil.TempDir("", "dirent-test") + d, err := os.MkdirTemp("", "dirent-test") if err != nil { t.Fatalf("tempdir: %v", err) } @@ -36,7 +35,7 @@ func TestDirent(t *testing.T) { for i, c := range []byte("0123456789") { name := string(bytes.Repeat([]byte{c}, filenameMinSize+i)) - err = ioutil.WriteFile(filepath.Join(d, name), nil, 0644) + err = os.WriteFile(filepath.Join(d, name), nil, 0644) if err != nil { t.Fatalf("writefile: %v", err) } @@ -93,7 +92,7 @@ func TestDirentRepeat(t *testing.T) { } // Make a directory containing N files - d, err := ioutil.TempDir("", "direntRepeat-test") + d, err := os.MkdirTemp("", "direntRepeat-test") if err != nil { t.Fatalf("tempdir: %v", err) } @@ -104,7 +103,7 @@ func TestDirentRepeat(t *testing.T) { files = append(files, fmt.Sprintf("file%d", i)) } for _, file := range files { - err = ioutil.WriteFile(filepath.Join(d, file), []byte("contents"), 0644) + err = os.WriteFile(filepath.Join(d, file), []byte("contents"), 0644) if err != nil { t.Fatalf("writefile: %v", err) } diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index b79dee7525..ac3a5754ae 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -11,7 +11,6 @@ import ( "fmt" "internal/testenv" "io" - "io/ioutil" "os" "os/exec" "os/user" @@ -65,7 +64,7 @@ func skipNoUserNamespaces(t *testing.T) { func skipUnprivilegedUserClone(t *testing.T) { // Skip the test if the sysctl that prevents unprivileged user // from creating user namespaces is enabled. - data, errRead := ioutil.ReadFile("/proc/sys/kernel/unprivileged_userns_clone") + data, errRead := os.ReadFile("/proc/sys/kernel/unprivileged_userns_clone") if errRead != nil || len(data) < 1 || data[0] == '0' { t.Skip("kernel prohibits user namespace in unprivileged process") } @@ -98,7 +97,7 @@ func checkUserNS(t *testing.T) { // On Centos 7 make sure they set the kernel parameter user_namespace=1 // See issue 16283 and 20796. if _, err := os.Stat("/sys/module/user_namespace/parameters/enable"); err == nil { - buf, _ := ioutil.ReadFile("/sys/module/user_namespace/parameters/enabled") + buf, _ := os.ReadFile("/sys/module/user_namespace/parameters/enabled") if !strings.HasPrefix(string(buf), "Y") { t.Skip("kernel doesn't support user namespaces") } @@ -106,7 +105,7 @@ func checkUserNS(t *testing.T) { // On Centos 7.5+, user namespaces are disabled if user.max_user_namespaces = 0 if _, err := os.Stat("/proc/sys/user/max_user_namespaces"); err == nil { - buf, errRead := ioutil.ReadFile("/proc/sys/user/max_user_namespaces") + buf, errRead := os.ReadFile("/proc/sys/user/max_user_namespaces") if errRead == nil && buf[0] == '0' { t.Skip("kernel doesn't support user namespaces") } @@ -226,7 +225,7 @@ func TestUnshare(t *testing.T) { t.Fatal(err) } - orig, err := ioutil.ReadFile(path) + orig, err := os.ReadFile(path) if err != nil { t.Fatal(err) } @@ -349,7 +348,7 @@ func TestUnshareMountNameSpace(t *testing.T) { t.Skip("kernel prohibits unshare in unprivileged process, unless using user namespace") } - d, err := ioutil.TempDir("", "unshare") + d, err := os.MkdirTemp("", "unshare") if err != nil { t.Fatalf("tempdir: %v", err) } @@ -391,7 +390,7 @@ func TestUnshareMountNameSpaceChroot(t *testing.T) { t.Skip("kernel prohibits unshare in unprivileged process, unless using user namespace") } - d, err := ioutil.TempDir("", "unshare") + d, err := os.MkdirTemp("", "unshare") if err != nil { t.Fatalf("tempdir: %v", err) } @@ -599,7 +598,7 @@ func testAmbientCaps(t *testing.T, userns bool) { } // Copy the test binary to a temporary location which is readable by nobody. - f, err := ioutil.TempFile("", "gotest") + f, err := os.CreateTemp("", "gotest") if err != nil { t.Fatal(err) } diff --git a/src/syscall/getdirentries_test.go b/src/syscall/getdirentries_test.go index 2a3419c230..66bb8acba2 100644 --- a/src/syscall/getdirentries_test.go +++ b/src/syscall/getdirentries_test.go @@ -8,7 +8,6 @@ package syscall_test import ( "fmt" - "io/ioutil" "os" "path/filepath" "sort" @@ -29,7 +28,7 @@ func testGetdirentries(t *testing.T, count int) { if count > 100 && testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" { t.Skip("skipping in -short mode") } - d, err := ioutil.TempDir("", "getdirentries-test") + d, err := os.MkdirTemp("", "getdirentries-test") if err != nil { t.Fatalf("Tempdir: %v", err) } @@ -41,7 +40,7 @@ func testGetdirentries(t *testing.T, count int) { // Make files in the temp directory for _, name := range names { - err := ioutil.WriteFile(filepath.Join(d, name), []byte("data"), 0) + err := os.WriteFile(filepath.Join(d, name), []byte("data"), 0) if err != nil { t.Fatalf("WriteFile: %v", err) } diff --git a/src/syscall/mkasm_darwin.go b/src/syscall/mkasm_darwin.go index f6f75f99f6..1783387a53 100644 --- a/src/syscall/mkasm_darwin.go +++ b/src/syscall/mkasm_darwin.go @@ -11,23 +11,22 @@ package main import ( "bytes" "fmt" - "io/ioutil" "log" "os" "strings" ) func main() { - in1, err := ioutil.ReadFile("syscall_darwin.go") + in1, err := os.ReadFile("syscall_darwin.go") if err != nil { log.Fatalf("can't open syscall_darwin.go: %s", err) } arch := os.Args[1] - in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch)) + in2, err := os.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch)) if err != nil { log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err) } - in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch)) + in3, err := os.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch)) if err != nil { log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err) } @@ -51,7 +50,7 @@ func main() { fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn) } } - err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644) + err = os.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644) if err != nil { log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err) } diff --git a/src/syscall/syscall_linux_test.go b/src/syscall/syscall_linux_test.go index 92764323ee..153d0efef1 100644 --- a/src/syscall/syscall_linux_test.go +++ b/src/syscall/syscall_linux_test.go @@ -9,7 +9,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "os" "os/exec" "os/signal" @@ -30,7 +29,7 @@ func chtmpdir(t *testing.T) func() { if err != nil { t.Fatalf("chtmpdir: %v", err) } - d, err := ioutil.TempDir("", "test") + d, err := os.MkdirTemp("", "test") if err != nil { t.Fatalf("chtmpdir: %v", err) } @@ -160,7 +159,7 @@ func TestLinuxDeathSignal(t *testing.T) { // Copy the test binary to a location that a non-root user can read/execute // after we drop privileges - tempDir, err := ioutil.TempDir("", "TestDeathSignal") + tempDir, err := os.MkdirTemp("", "TestDeathSignal") if err != nil { t.Fatalf("cannot create temporary directory: %v", err) } @@ -321,7 +320,7 @@ func TestSyscallNoError(t *testing.T) { // Copy the test binary to a location that a non-root user can read/execute // after we drop privileges - tempDir, err := ioutil.TempDir("", "TestSyscallNoError") + tempDir, err := os.MkdirTemp("", "TestSyscallNoError") if err != nil { t.Fatalf("cannot create temporary directory: %v", err) } @@ -543,7 +542,7 @@ func TestAllThreadsSyscall(t *testing.T) { func compareStatus(filter, expect string) error { expected := filter + expect pid := syscall.Getpid() - fs, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/task", pid)) + fs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid)) if err != nil { return fmt.Errorf("unable to find %d tasks: %v", pid, err) } @@ -551,7 +550,7 @@ func compareStatus(filter, expect string) error { foundAThread := false for _, f := range fs { tf := fmt.Sprintf("/proc/%s/status", f.Name()) - d, err := ioutil.ReadFile(tf) + d, err := os.ReadFile(tf) if err != nil { // There are a surprising number of ways this // can error out on linux. We've seen all of diff --git a/src/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go index 1c34ed2c27..7e6a8c9043 100644 --- a/src/syscall/syscall_unix_test.go +++ b/src/syscall/syscall_unix_test.go @@ -11,7 +11,6 @@ import ( "fmt" "internal/testenv" "io" - "io/ioutil" "net" "os" "os/exec" @@ -79,7 +78,7 @@ func TestFcntlFlock(t *testing.T) { } if os.Getenv("GO_WANT_HELPER_PROCESS") == "" { // parent - tempDir, err := ioutil.TempDir("", "TestFcntlFlock") + tempDir, err := os.MkdirTemp("", "TestFcntlFlock") if err != nil { t.Fatalf("Failed to create temp dir: %v", err) } @@ -157,7 +156,7 @@ func TestPassFD(t *testing.T) { } - tempDir, err := ioutil.TempDir("", "TestPassFD") + tempDir, err := os.MkdirTemp("", "TestPassFD") if err != nil { t.Fatal(err) } @@ -257,7 +256,7 @@ func passFDChild() { // We make it in tempDir, which our parent will clean up. flag.Parse() tempDir := flag.Arg(0) - f, err := ioutil.TempFile(tempDir, "") + f, err := os.CreateTemp(tempDir, "") if err != nil { fmt.Printf("TempFile: %v", err) return diff --git a/src/syscall/syscall_windows_test.go b/src/syscall/syscall_windows_test.go index d146911073..a9ae54752b 100644 --- a/src/syscall/syscall_windows_test.go +++ b/src/syscall/syscall_windows_test.go @@ -5,7 +5,6 @@ package syscall_test import ( - "io/ioutil" "os" "path/filepath" "syscall" @@ -13,7 +12,7 @@ import ( ) func TestWin32finddata(t *testing.T) { - dir, err := ioutil.TempDir("", "go-build") + dir, err := os.MkdirTemp("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) } diff --git a/src/testing/testing.go b/src/testing/testing.go index d4b108a183..80354d5ce8 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -242,7 +242,6 @@ import ( "fmt" "internal/race" "io" - "io/ioutil" "os" "runtime" "runtime/debug" @@ -936,14 +935,14 @@ func (c *common) TempDir() string { if nonExistent { c.Helper() - // ioutil.TempDir doesn't like path separators in its pattern, + // os.MkdirTemp doesn't like path separators in its pattern, // so mangle the name to accommodate subtests. tempDirReplacer.Do(func() { tempDirReplacer.r = strings.NewReplacer("/", "_", "\\", "_", ":", "_") }) pattern := tempDirReplacer.r.Replace(c.Name()) - c.tempDir, c.tempDirErr = ioutil.TempDir("", pattern) + c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern) if c.tempDirErr == nil { c.Cleanup(func() { if err := os.RemoveAll(c.tempDir); err != nil { diff --git a/src/text/template/examplefiles_test.go b/src/text/template/examplefiles_test.go index a15c7a62a3..6534ee3315 100644 --- a/src/text/template/examplefiles_test.go +++ b/src/text/template/examplefiles_test.go @@ -6,7 +6,6 @@ package template_test import ( "io" - "io/ioutil" "log" "os" "path/filepath" @@ -20,7 +19,7 @@ type templateFile struct { } func createTestDir(files []templateFile) string { - dir, err := ioutil.TempDir("", "template") + dir, err := os.MkdirTemp("", "template") if err != nil { log.Fatal(err) } diff --git a/src/text/template/helper.go b/src/text/template/helper.go index 8269fa28c5..57905e613a 100644 --- a/src/text/template/helper.go +++ b/src/text/template/helper.go @@ -9,7 +9,7 @@ package template import ( "fmt" "io/fs" - "io/ioutil" + "os" "path" "path/filepath" ) @@ -164,7 +164,7 @@ func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) { func readFileOS(file string) (name string, b []byte, err error) { name = filepath.Base(file) - b, err = ioutil.ReadFile(file) + b, err = os.ReadFile(file) return } diff --git a/src/text/template/link_test.go b/src/text/template/link_test.go index 4eac7e6755..9dc70dfc0d 100644 --- a/src/text/template/link_test.go +++ b/src/text/template/link_test.go @@ -7,7 +7,6 @@ package template_test import ( "bytes" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -40,13 +39,13 @@ func main() { t.Used() } ` - td, err := ioutil.TempDir("", "text_template_TestDeadCodeElimination") + td, err := os.MkdirTemp("", "text_template_TestDeadCodeElimination") if err != nil { t.Fatal(err) } defer os.RemoveAll(td) - if err := ioutil.WriteFile(filepath.Join(td, "x.go"), []byte(prog), 0644); err != nil { + if err := os.WriteFile(filepath.Join(td, "x.go"), []byte(prog), 0644); err != nil { t.Fatal(err) } cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "x.exe", "x.go") @@ -54,7 +53,7 @@ func main() { if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("go build: %v, %s", err, out) } - slurp, err := ioutil.ReadFile(filepath.Join(td, "x.exe")) + slurp, err := os.ReadFile(filepath.Join(td, "x.exe")) if err != nil { t.Fatal(err) } diff --git a/src/time/genzabbrs.go b/src/time/genzabbrs.go index 1d59ba73ce..9825e705d2 100644 --- a/src/time/genzabbrs.go +++ b/src/time/genzabbrs.go @@ -18,9 +18,9 @@ import ( "flag" "go/format" "io" - "io/ioutil" "log" "net/http" + "os" "sort" "text/template" "time" @@ -128,7 +128,7 @@ func main() { if err != nil { log.Fatal(err) } - err = ioutil.WriteFile(*filename, data, 0644) + err = os.WriteFile(*filename, data, 0644) if err != nil { log.Fatal(err) } diff --git a/src/time/tzdata/generate_zipdata.go b/src/time/tzdata/generate_zipdata.go index d8b47e7878..21357fbf1c 100644 --- a/src/time/tzdata/generate_zipdata.go +++ b/src/time/tzdata/generate_zipdata.go @@ -10,7 +10,6 @@ package main import ( "bufio" "fmt" - "io/ioutil" "os" "strconv" ) @@ -40,7 +39,7 @@ const zipdata = ` func main() { // We should be run in the $GOROOT/src/time/tzdata directory. - data, err := ioutil.ReadFile("../../../lib/time/zoneinfo.zip") + data, err := os.ReadFile("../../../lib/time/zoneinfo.zip") if err != nil { die("cannot find zoneinfo.zip file: %v", err) } diff --git a/src/time/zoneinfo_read.go b/src/time/zoneinfo_read.go index 22a60f3211..c739864815 100644 --- a/src/time/zoneinfo_read.go +++ b/src/time/zoneinfo_read.go @@ -546,7 +546,7 @@ func loadLocation(name string, sources []string) (z *Location, firstErr error) { } // readFile reads and returns the content of the named file. -// It is a trivial implementation of ioutil.ReadFile, reimplemented +// It is a trivial implementation of os.ReadFile, reimplemented // here to avoid depending on io/ioutil or os. // It returns an error if name exceeds maxFileSize bytes. func readFile(name string) ([]byte, error) { From f1980efb92c011eab71aa61b68ccf58d845d1de7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 29 Oct 2020 14:46:29 -0400 Subject: [PATCH 205/212] all: update to use os.ReadDir where appropriate os.ReadDir is a replacement for ioutil.ReadDir that returns a slice of fs.DirEntry instead of fs.FileInfo, meaning it is the more efficient form. This CL updates call sites throughout the Go source tree wherever possible. As usual, code built using the Go 1.4 bootstrap toolchain is not included. There is also a use in go/build that appears in the public API and can't be changed, at least not without additional changes. Fixes #42026. Change-Id: Icfc9dd52c6045020f6830e22c72128499462d561 Reviewed-on: https://go-review.googlesource.com/c/go/+/266366 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/go/internal/clean/clean.go | 3 +- src/cmd/go/internal/imports/scan_test.go | 3 +- src/cmd/go/internal/load/pkg.go | 7 ++- src/cmd/go/internal/modcmd/vendor.go | 11 +++-- src/cmd/go/internal/modfetch/cache.go | 3 +- src/cmd/go/internal/modload/init.go | 17 ++++---- src/cmd/go/internal/test/test.go | 12 ++++-- src/cmd/go/proxy_test.go | 7 ++- src/crypto/x509/root_unix.go | 21 +++++---- src/go/build/deps_test.go | 3 +- src/go/internal/gcimporter/gcimporter_test.go | 5 +-- .../internal/srcimporter/srcimporter_test.go | 3 +- src/go/parser/error_test.go | 10 ++--- src/go/parser/interface.go | 43 +++++++++++-------- src/go/types/check_test.go | 11 +++-- src/go/types/stdlib_test.go | 11 +++-- src/internal/trace/parser_test.go | 7 ++- src/os/exec/exec_test.go | 3 +- src/testing/testing_test.go | 7 ++- 19 files changed, 92 insertions(+), 95 deletions(-) diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go index 87933f04f3..b1d40feb27 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -9,7 +9,6 @@ import ( "context" "fmt" "io" - "io/ioutil" "os" "path/filepath" "strconv" @@ -244,7 +243,7 @@ func clean(p *load.Package) { base.Errorf("%v", p.Error) return } - dirs, err := ioutil.ReadDir(p.Dir) + dirs, err := os.ReadDir(p.Dir) if err != nil { base.Errorf("go clean %s: %v", p.Dir, err) return diff --git a/src/cmd/go/internal/imports/scan_test.go b/src/cmd/go/internal/imports/scan_test.go index 5ba3201968..2d245ee787 100644 --- a/src/cmd/go/internal/imports/scan_test.go +++ b/src/cmd/go/internal/imports/scan_test.go @@ -7,7 +7,6 @@ package imports import ( "bytes" "internal/testenv" - "io/ioutil" "os" "path" "path/filepath" @@ -58,7 +57,7 @@ func TestScan(t *testing.T) { func TestScanDir(t *testing.T) { testenv.MustHaveGoBuild(t) - dirs, err := ioutil.ReadDir("testdata") + dirs, err := os.ReadDir("testdata") if err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index da3e0b895c..6f95af4f7e 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -15,7 +15,6 @@ import ( "go/scanner" "go/token" "io/fs" - "io/ioutil" "os" "path" pathpkg "path" @@ -1296,9 +1295,9 @@ HaveGoMod: // Otherwise it is not possible to vendor just a/b/c and still import the // non-vendored a/b. See golang.org/issue/13832. func hasGoFiles(dir string) bool { - fis, _ := ioutil.ReadDir(dir) - for _, fi := range fis { - if !fi.IsDir() && strings.HasSuffix(fi.Name(), ".go") { + files, _ := os.ReadDir(dir) + for _, f := range files { + if !f.IsDir() && strings.HasSuffix(f.Name(), ".go") { return true } } diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 390a195547..1bbb57d353 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -10,7 +10,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "sort" @@ -244,7 +243,7 @@ var metaPrefixes = []string{ } // matchMetadata reports whether info is a metadata file. -func matchMetadata(dir string, info fs.FileInfo) bool { +func matchMetadata(dir string, info fs.DirEntry) bool { name := info.Name() for _, p := range metaPrefixes { if strings.HasPrefix(name, p) { @@ -255,7 +254,7 @@ func matchMetadata(dir string, info fs.FileInfo) bool { } // matchPotentialSourceFile reports whether info may be relevant to a build operation. -func matchPotentialSourceFile(dir string, info fs.FileInfo) bool { +func matchPotentialSourceFile(dir string, info fs.DirEntry) bool { if strings.HasSuffix(info.Name(), "_test.go") { return false } @@ -281,8 +280,8 @@ func matchPotentialSourceFile(dir string, info fs.FileInfo) bool { } // copyDir copies all regular files satisfying match(info) from src to dst. -func copyDir(dst, src string, match func(dir string, info fs.FileInfo) bool) { - files, err := ioutil.ReadDir(src) +func copyDir(dst, src string, match func(dir string, info fs.DirEntry) bool) { + files, err := os.ReadDir(src) if err != nil { base.Fatalf("go mod vendor: %v", err) } @@ -290,7 +289,7 @@ func copyDir(dst, src string, match func(dir string, info fs.FileInfo) bool) { base.Fatalf("go mod vendor: %v", err) } for _, file := range files { - if file.IsDir() || !file.Mode().IsRegular() || !match(src, file) { + if file.IsDir() || !file.Type().IsRegular() || !match(src, file) { continue } r, err := os.Open(filepath.Join(src, file.Name())) diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go index 7572ff24f8..3a2ff63721 100644 --- a/src/cmd/go/internal/modfetch/cache.go +++ b/src/cmd/go/internal/modfetch/cache.go @@ -11,7 +11,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "strings" @@ -598,7 +597,7 @@ func rewriteVersionList(dir string) { } defer unlock() - infos, err := ioutil.ReadDir(dir) + infos, err := os.ReadDir(dir) if err != nil { return } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 6a2cea668d..3f70d04145 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -12,7 +12,6 @@ import ( "fmt" "go/build" "internal/lazyregexp" - "io/ioutil" "os" "path" "path/filepath" @@ -445,13 +444,13 @@ func CreateModFile(ctx context.Context, modPath string) { // this is an existing project. Walking the tree for packages would be more // accurate, but could take much longer. empty := true - fis, _ := ioutil.ReadDir(modRoot) - for _, fi := range fis { - name := fi.Name() + files, _ := os.ReadDir(modRoot) + for _, f := range files { + name := f.Name() if strings.HasPrefix(name, ".") || strings.HasPrefix(name, "_") { continue } - if strings.HasSuffix(name, ".go") || fi.IsDir() { + if strings.HasSuffix(name, ".go") || f.IsDir() { empty = false break } @@ -731,9 +730,9 @@ func findModulePath(dir string) (string, error) { // Cast about for import comments, // first in top-level directory, then in subdirectories. - list, _ := ioutil.ReadDir(dir) + list, _ := os.ReadDir(dir) for _, info := range list { - if info.Mode().IsRegular() && strings.HasSuffix(info.Name(), ".go") { + if info.Type().IsRegular() && strings.HasSuffix(info.Name(), ".go") { if com := findImportComment(filepath.Join(dir, info.Name())); com != "" { return com, nil } @@ -741,9 +740,9 @@ func findModulePath(dir string) (string, error) { } for _, info1 := range list { if info1.IsDir() { - files, _ := ioutil.ReadDir(filepath.Join(dir, info1.Name())) + files, _ := os.ReadDir(filepath.Join(dir, info1.Name())) for _, info2 := range files { - if info2.Mode().IsRegular() && strings.HasSuffix(info2.Name(), ".go") { + if info2.Type().IsRegular() && strings.HasSuffix(info2.Name(), ".go") { if com := findImportComment(filepath.Join(dir, info1.Name(), info2.Name())); com != "" { return path.Dir(com), nil } diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 401b67c260..e8a7aacb85 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -13,7 +13,6 @@ import ( "go/build" "io" "io/fs" - "io/ioutil" "os" "os/exec" "path" @@ -1561,13 +1560,18 @@ func hashOpen(name string) (cache.ActionID, error) { } hashWriteStat(h, info) if info.IsDir() { - names, err := ioutil.ReadDir(name) + files, err := os.ReadDir(name) if err != nil { fmt.Fprintf(h, "err %v\n", err) } - for _, f := range names { + for _, f := range files { fmt.Fprintf(h, "file %s ", f.Name()) - hashWriteStat(h, f) + finfo, err := f.Info() + if err != nil { + fmt.Fprintf(h, "err %v\n", err) + } else { + hashWriteStat(h, finfo) + } } } else if info.Mode().IsRegular() { // Because files might be very large, do not attempt diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go index 3ed42face2..e390c73a9c 100644 --- a/src/cmd/go/proxy_test.go +++ b/src/cmd/go/proxy_test.go @@ -13,7 +13,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "log" "net" "net/http" @@ -75,12 +74,12 @@ func StartProxy() { var modList []module.Version func readModList() { - infos, err := ioutil.ReadDir("testdata/mod") + files, err := os.ReadDir("testdata/mod") if err != nil { log.Fatal(err) } - for _, info := range infos { - name := info.Name() + for _, f := range files { + name := f.Name() if !strings.HasSuffix(name, ".txt") { continue } diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go index 3c643466ed..262fc079d5 100644 --- a/src/crypto/x509/root_unix.go +++ b/src/crypto/x509/root_unix.go @@ -8,7 +8,6 @@ package x509 import ( "io/fs" - "io/ioutil" "os" "path/filepath" "strings" @@ -82,17 +81,17 @@ func loadSystemRoots() (*CertPool, error) { return nil, firstErr } -// readUniqueDirectoryEntries is like ioutil.ReadDir but omits +// readUniqueDirectoryEntries is like os.ReadDir but omits // symlinks that point within the directory. -func readUniqueDirectoryEntries(dir string) ([]fs.FileInfo, error) { - fis, err := ioutil.ReadDir(dir) +func readUniqueDirectoryEntries(dir string) ([]fs.DirEntry, error) { + files, err := os.ReadDir(dir) if err != nil { return nil, err } - uniq := fis[:0] - for _, fi := range fis { - if !isSameDirSymlink(fi, dir) { - uniq = append(uniq, fi) + uniq := files[:0] + for _, f := range files { + if !isSameDirSymlink(f, dir) { + uniq = append(uniq, f) } } return uniq, nil @@ -100,10 +99,10 @@ func readUniqueDirectoryEntries(dir string) ([]fs.FileInfo, error) { // isSameDirSymlink reports whether fi in dir is a symlink with a // target not containing a slash. -func isSameDirSymlink(fi fs.FileInfo, dir string) bool { - if fi.Mode()&fs.ModeSymlink == 0 { +func isSameDirSymlink(f fs.DirEntry, dir string) bool { + if f.Type()&fs.ModeSymlink == 0 { return false } - target, err := os.Readlink(filepath.Join(dir, fi.Name())) + target, err := os.Readlink(filepath.Join(dir, f.Name())) return err == nil && !strings.Contains(target, "/") } diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index e9ed26aa5f..56942c0fd2 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -12,7 +12,6 @@ import ( "fmt" "internal/testenv" "io/fs" - "io/ioutil" "os" "path/filepath" "runtime" @@ -597,7 +596,7 @@ func findImports(pkg string) ([]string, error) { vpkg = "vendor/" + pkg } dir := filepath.Join(Default.GOROOT, "src", vpkg) - files, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) if err != nil { return nil, err } diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 8991e3bdee..3c76aafde3 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -8,7 +8,6 @@ import ( "bytes" "fmt" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -66,7 +65,7 @@ const maxTime = 30 * time.Second func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir) - list, err := ioutil.ReadDir(dirname) + list, err := os.ReadDir(dirname) if err != nil { t.Fatalf("testDir(%s): %s", dirname, err) } @@ -144,7 +143,7 @@ func TestVersionHandling(t *testing.T) { } const dir = "./testdata/versions" - list, err := ioutil.ReadDir(dir) + list, err := os.ReadDir(dir) if err != nil { t.Fatal(err) } diff --git a/src/go/internal/srcimporter/srcimporter_test.go b/src/go/internal/srcimporter/srcimporter_test.go index 102ac43f94..05b12f1636 100644 --- a/src/go/internal/srcimporter/srcimporter_test.go +++ b/src/go/internal/srcimporter/srcimporter_test.go @@ -10,7 +10,6 @@ import ( "go/token" "go/types" "internal/testenv" - "io/ioutil" "os" "path" "path/filepath" @@ -59,7 +58,7 @@ func walkDir(t *testing.T, path string, endTime time.Time) (int, bool) { return 0, false } - list, err := ioutil.ReadDir(filepath.Join(runtime.GOROOT(), "src", path)) + list, err := os.ReadDir(filepath.Join(runtime.GOROOT(), "src", path)) if err != nil { t.Fatalf("walkDir %s failed (%v)", path, err) } diff --git a/src/go/parser/error_test.go b/src/go/parser/error_test.go index 9b79097acf..358a844f65 100644 --- a/src/go/parser/error_test.go +++ b/src/go/parser/error_test.go @@ -25,7 +25,7 @@ package parser import ( "go/scanner" "go/token" - "io/ioutil" + "os" "path/filepath" "regexp" "strings" @@ -174,13 +174,13 @@ func checkErrors(t *testing.T, filename string, input interface{}) { } func TestErrors(t *testing.T) { - list, err := ioutil.ReadDir(testdata) + list, err := os.ReadDir(testdata) if err != nil { t.Fatal(err) } - for _, fi := range list { - name := fi.Name() - if !fi.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".src") { + for _, d := range list { + name := d.Name() + if !d.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".src") { checkErrors(t, filepath.Join(testdata, name), nil) } } diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go index 41d9a52847..56ff5fefb4 100644 --- a/src/go/parser/interface.go +++ b/src/go/parser/interface.go @@ -13,7 +13,6 @@ import ( "go/token" "io" "io/fs" - "io/ioutil" "os" "path/filepath" "strings" @@ -134,29 +133,39 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) // first error encountered are returned. // func ParseDir(fset *token.FileSet, path string, filter func(fs.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error) { - list, err := ioutil.ReadDir(path) + list, err := os.ReadDir(path) if err != nil { return nil, err } pkgs = make(map[string]*ast.Package) for _, d := range list { - if !d.IsDir() && strings.HasSuffix(d.Name(), ".go") && (filter == nil || filter(d)) { - filename := filepath.Join(path, d.Name()) - if src, err := ParseFile(fset, filename, nil, mode); err == nil { - name := src.Name.Name - pkg, found := pkgs[name] - if !found { - pkg = &ast.Package{ - Name: name, - Files: make(map[string]*ast.File), - } - pkgs[name] = pkg - } - pkg.Files[filename] = src - } else if first == nil { - first = err + if d.IsDir() || !strings.HasSuffix(d.Name(), ".go") { + continue + } + if filter != nil { + info, err := d.Info() + if err != nil { + return nil, err } + if !filter(info) { + continue + } + } + filename := filepath.Join(path, d.Name()) + if src, err := ParseFile(fset, filename, nil, mode); err == nil { + name := src.Name.Name + pkg, found := pkgs[name] + if !found { + pkg = &ast.Package{ + Name: name, + Files: make(map[string]*ast.File), + } + pkgs[name] = pkg + } + pkg.Files[filename] = src + } else if first == nil { + first = err } } diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index 841ca24511..ce31dab68b 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -33,7 +33,6 @@ import ( "go/scanner" "go/token" "internal/testenv" - "io/ioutil" "os" "path/filepath" "regexp" @@ -330,17 +329,17 @@ func TestFixedBugs(t *testing.T) { testDir(t, "fixedbugs") } func testDir(t *testing.T, dir string) { testenv.MustHaveGoBuild(t) - fis, err := ioutil.ReadDir(dir) + dirs, err := os.ReadDir(dir) if err != nil { t.Fatal(err) } - for _, fi := range fis { - testname := filepath.Base(fi.Name()) + for _, d := range dirs { + testname := filepath.Base(d.Name()) testname = strings.TrimSuffix(testname, filepath.Ext(testname)) t.Run(testname, func(t *testing.T) { - filename := filepath.Join(dir, fi.Name()) - if fi.IsDir() { + filename := filepath.Join(dir, d.Name()) + if d.IsDir() { t.Errorf("skipped directory %q", filename) return } diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index 669e7bec20..23f8f9a18d 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -16,7 +16,6 @@ import ( "go/scanner" "go/token" "internal/testenv" - "io/ioutil" "os" "path/filepath" "runtime" @@ -87,7 +86,7 @@ func firstComment(filename string) string { } func testTestDir(t *testing.T, path string, ignore ...string) { - files, err := ioutil.ReadDir(path) + files, err := os.ReadDir(path) if err != nil { t.Fatal(err) } @@ -297,7 +296,7 @@ func (w *walker) walk(dir string) { return } - fis, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) if err != nil { w.errh(err) return @@ -317,9 +316,9 @@ func (w *walker) walk(dir string) { } // traverse subdirectories, but don't walk into testdata - for _, fi := range fis { - if fi.IsDir() && fi.Name() != "testdata" { - w.walk(filepath.Join(dir, fi.Name())) + for _, f := range files { + if f.IsDir() && f.Name() != "testdata" { + w.walk(filepath.Join(dir, f.Name())) } } } diff --git a/src/internal/trace/parser_test.go b/src/internal/trace/parser_test.go index 316220cfa8..cdab95a59e 100644 --- a/src/internal/trace/parser_test.go +++ b/src/internal/trace/parser_test.go @@ -6,7 +6,6 @@ package trace import ( "bytes" - "io/ioutil" "os" "path/filepath" "strings" @@ -34,19 +33,19 @@ func TestCorruptedInputs(t *testing.T) { } func TestParseCanned(t *testing.T) { - files, err := ioutil.ReadDir("./testdata") + files, err := os.ReadDir("./testdata") if err != nil { t.Fatalf("failed to read ./testdata: %v", err) } for _, f := range files { - name := filepath.Join("./testdata", f.Name()) - info, err := os.Stat(name) + info, err := f.Info() if err != nil { t.Fatal(err) } if testing.Short() && info.Size() > 10000 { continue } + name := filepath.Join("./testdata", f.Name()) data, err := os.ReadFile(name) if err != nil { t.Fatal(err) diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 92429f63a5..8b0c93f382 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -15,7 +15,6 @@ import ( "internal/poll" "internal/testenv" "io" - "io/ioutil" "log" "net" "net/http" @@ -386,7 +385,7 @@ func TestPipeLookPathLeak(t *testing.T) { // Reading /proc/self/fd is more reliable than calling lsof, so try that // first. numOpenFDs := func() (int, []byte, error) { - fds, err := ioutil.ReadDir("/proc/self/fd") + fds, err := os.ReadDir("/proc/self/fd") if err != nil { return 0, nil, err } diff --git a/src/testing/testing_test.go b/src/testing/testing_test.go index d665a334e4..0f096980ca 100644 --- a/src/testing/testing_test.go +++ b/src/testing/testing_test.go @@ -5,7 +5,6 @@ package testing_test import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -102,11 +101,11 @@ func testTempDir(t *testing.T) { if !fi.IsDir() { t.Errorf("dir %q is not a dir", dir) } - fis, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) if err != nil { t.Fatal(err) } - if len(fis) > 0 { - t.Errorf("unexpected %d files in TempDir: %v", len(fis), fis) + if len(files) > 0 { + t.Errorf("unexpected %d files in TempDir: %v", len(files), files) } } From 89f465c2b59cea32c10ed69eaa07e17f85c910e2 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 9 Dec 2020 06:10:52 -0500 Subject: [PATCH 206/212] go/types: avoid endless recursion in the Comparable predicate This is a port of CL 276374 from the dev.typeparams branch. Avoid an endless recursion in Comparable by tracking types that have already been considered. Fixes #43088 Change-Id: I927b29ac544df9bfb5c8c04699d57fafe6cfff73 Reviewed-on: https://go-review.googlesource.com/c/go/+/276552 Run-TryBot: Robert Findley Trust: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/issues_test.go | 26 ++++++++++++++++++++++++++ src/go/types/predicates.go | 16 ++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go index f59f905397..34850eb034 100644 --- a/src/go/types/issues_test.go +++ b/src/go/types/issues_test.go @@ -12,6 +12,7 @@ import ( "go/ast" "go/importer" "go/parser" + "go/token" "internal/testenv" "sort" "strings" @@ -523,3 +524,28 @@ func TestIssue34921(t *testing.T) { pkg = res // res is imported by the next package in this test } } + +func TestIssue43088(t *testing.T) { + // type T1 struct { + // _ T2 + // } + // + // type T2 struct { + // _ struct { + // _ T2 + // } + // } + n1 := NewTypeName(token.NoPos, nil, "T1", nil) + T1 := NewNamed(n1, nil, nil) + n2 := NewTypeName(token.NoPos, nil, "T2", nil) + T2 := NewNamed(n2, nil, nil) + s1 := NewStruct([]*Var{NewField(token.NoPos, nil, "_", T2, false)}, nil) + T1.SetUnderlying(s1) + s2 := NewStruct([]*Var{NewField(token.NoPos, nil, "_", T2, false)}, nil) + s3 := NewStruct([]*Var{NewField(token.NoPos, nil, "_", s2, false)}, nil) + T2.SetUnderlying(s3) + + // These calls must terminate (no endless recursion). + Comparable(T1) + Comparable(T2) +} diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 057908eacd..148edbfb76 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -79,6 +79,18 @@ func IsInterface(typ Type) bool { // Comparable reports whether values of type T are comparable. func Comparable(T Type) bool { + return comparable(T, nil) +} + +func comparable(T Type, seen map[Type]bool) bool { + if seen[T] { + return true + } + if seen == nil { + seen = make(map[Type]bool) + } + seen[T] = true + switch t := T.Underlying().(type) { case *Basic: // assume invalid types to be comparable @@ -88,13 +100,13 @@ func Comparable(T Type) bool { return true case *Struct: for _, f := range t.fields { - if !Comparable(f.typ) { + if !comparable(f.typ, seen) { return false } } return true case *Array: - return Comparable(t.elem) + return comparable(t.elem, seen) } return false } From 6c64b6db6802818dd9a4789cdd564f19b70b6b4c Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 9 Dec 2020 08:27:54 -0800 Subject: [PATCH 207/212] cmd/compile: don't constant fold divide by zero It just makes the compiler crash. Oops. Fixes #43099 Change-Id: Id996c14799c1a5d0063ecae3b8770568161c2440 Reviewed-on: https://go-review.googlesource.com/c/go/+/276652 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/ssa/gen/ARM.rules | 4 +-- src/cmd/compile/internal/ssa/gen/ARM64.rules | 16 ++++----- src/cmd/compile/internal/ssa/gen/MIPS.rules | 8 ++--- src/cmd/compile/internal/ssa/gen/MIPS64.rules | 8 ++--- src/cmd/compile/internal/ssa/rewriteARM.go | 8 +++++ src/cmd/compile/internal/ssa/rewriteARM64.go | 32 +++++++++++++++++ src/cmd/compile/internal/ssa/rewriteMIPS.go | 16 +++++++++ src/cmd/compile/internal/ssa/rewriteMIPS64.go | 16 +++++++++ test/fixedbugs/issue43099.go | 34 +++++++++++++++++++ 9 files changed, 124 insertions(+), 18 deletions(-) create mode 100644 test/fixedbugs/issue43099.go diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index 6637c6cae4..11c36b5da3 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM.rules @@ -760,8 +760,8 @@ (MUL (MOVWconst [c]) (MOVWconst [d])) => (MOVWconst [c*d]) (MULA (MOVWconst [c]) (MOVWconst [d]) a) => (ADDconst [c*d] a) (MULS (MOVWconst [c]) (MOVWconst [d]) a) => (SUBconst [c*d] a) -(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)/uint32(d))]) -(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)%uint32(d))]) +(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)/uint32(d))]) +(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)%uint32(d))]) (ANDconst [c] (MOVWconst [d])) => (MOVWconst [c&d]) (ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x) (ORconst [c] (MOVWconst [d])) => (MOVWconst [c|d]) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 9edc0c94b0..3f4d0c1c52 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1372,14 +1372,14 @@ (MADDW a (MOVDconst [c]) (MOVDconst [d])) => (ADDconst [int64(int32(c)*int32(d))] a) (MSUB a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [c*d] a) (MSUBW a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [int64(int32(c)*int32(d))] a) -(DIV (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c/d]) -(UDIV (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint64(c)/uint64(d))]) -(DIVW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)/int32(d))]) -(UDIVW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint32(c)/uint32(d))]) -(MOD (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c%d]) -(UMOD (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint64(c)%uint64(d))]) -(MODW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)%int32(d))]) -(UMODW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint32(c)%uint32(d))]) +(DIV (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [c/d]) +(UDIV (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint64(c)/uint64(d))]) +(DIVW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(int32(c)/int32(d))]) +(UDIVW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint32(c)/uint32(d))]) +(MOD (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [c%d]) +(UMOD (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint64(c)%uint64(d))]) +(MODW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(int32(c)%int32(d))]) +(UMODW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint32(c)%uint32(d))]) (ANDconst [c] (MOVDconst [d])) => (MOVDconst [c&d]) (ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x) (ANDconst [c] (MOVWUreg x)) => (ANDconst [c&(1<<32-1)] x) diff --git a/src/cmd/compile/internal/ssa/gen/MIPS.rules b/src/cmd/compile/internal/ssa/gen/MIPS.rules index 470cc66869..8ad2c90ac3 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS.rules +++ b/src/cmd/compile/internal/ssa/gen/MIPS.rules @@ -626,10 +626,10 @@ (MUL (MOVWconst [c]) (MOVWconst [d])) => (MOVWconst [c*d]) (Select1 (MULTU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)*uint32(d))]) (Select0 (MULTU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32((int64(uint32(c))*int64(uint32(d)))>>32)]) -(Select1 (DIV (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [c/d]) -(Select1 (DIVU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)/uint32(d))]) -(Select0 (DIV (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [c%d]) -(Select0 (DIVU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)%uint32(d))]) +(Select1 (DIV (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [c/d]) +(Select1 (DIVU (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)/uint32(d))]) +(Select0 (DIV (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [c%d]) +(Select0 (DIVU (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)%uint32(d))]) (ANDconst [c] (MOVWconst [d])) => (MOVWconst [c&d]) (ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x) (ORconst [c] (MOVWconst [d])) => (MOVWconst [c|d]) diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64.rules b/src/cmd/compile/internal/ssa/gen/MIPS64.rules index 9af0f93333..088c9b1ac4 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64.rules +++ b/src/cmd/compile/internal/ssa/gen/MIPS64.rules @@ -617,10 +617,10 @@ (SRLVconst [c] (MOVVconst [d])) => (MOVVconst [int64(uint64(d)>>uint64(c))]) (SRAVconst [c] (MOVVconst [d])) => (MOVVconst [d>>uint64(c)]) (Select1 (MULVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c*d]) -(Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c/d]) -(Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [int64(uint64(c)/uint64(d))]) -(Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c%d]) // mod -(Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [int64(uint64(c)%uint64(d))]) // mod +(Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c/d]) +(Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)/uint64(d))]) +(Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c%d]) // mod +(Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)%uint64(d))]) // mod (ANDconst [c] (MOVVconst [d])) => (MOVVconst [c&d]) (ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x) (ORconst [c] (MOVVconst [d])) => (MOVVconst [c|d]) diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index 68495c558c..d9d439fa63 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM.go +++ b/src/cmd/compile/internal/ssa/rewriteARM.go @@ -15599,6 +15599,7 @@ func rewriteValueARM_OpSelect0(v *Value) bool { return true } // match: (Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) + // cond: d != 0 // result: (MOVWconst [int32(uint32(c)/uint32(d))]) for { if v_0.Op != OpARMCALLudiv { @@ -15615,6 +15616,9 @@ func rewriteValueARM_OpSelect0(v *Value) bool { break } d := auxIntToInt32(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARMMOVWconst) v.AuxInt = int32ToAuxInt(int32(uint32(c) / uint32(d))) return true @@ -15661,6 +15665,7 @@ func rewriteValueARM_OpSelect1(v *Value) bool { return true } // match: (Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) + // cond: d != 0 // result: (MOVWconst [int32(uint32(c)%uint32(d))]) for { if v_0.Op != OpARMCALLudiv { @@ -15677,6 +15682,9 @@ func rewriteValueARM_OpSelect1(v *Value) bool { break } d := auxIntToInt32(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARMMOVWconst) v.AuxInt = int32ToAuxInt(int32(uint32(c) % uint32(d))) return true diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 353696bf39..5d5e526add 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -3396,6 +3396,7 @@ func rewriteValueARM64_OpARM64DIV(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (DIV (MOVDconst [c]) (MOVDconst [d])) + // cond: d != 0 // result: (MOVDconst [c/d]) for { if v_0.Op != OpARM64MOVDconst { @@ -3406,6 +3407,9 @@ func rewriteValueARM64_OpARM64DIV(v *Value) bool { break } d := auxIntToInt64(v_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARM64MOVDconst) v.AuxInt = int64ToAuxInt(c / d) return true @@ -3416,6 +3420,7 @@ func rewriteValueARM64_OpARM64DIVW(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (DIVW (MOVDconst [c]) (MOVDconst [d])) + // cond: d != 0 // result: (MOVDconst [int64(int32(c)/int32(d))]) for { if v_0.Op != OpARM64MOVDconst { @@ -3426,6 +3431,9 @@ func rewriteValueARM64_OpARM64DIVW(v *Value) bool { break } d := auxIntToInt64(v_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARM64MOVDconst) v.AuxInt = int64ToAuxInt(int64(int32(c) / int32(d))) return true @@ -6165,6 +6173,7 @@ func rewriteValueARM64_OpARM64MOD(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (MOD (MOVDconst [c]) (MOVDconst [d])) + // cond: d != 0 // result: (MOVDconst [c%d]) for { if v_0.Op != OpARM64MOVDconst { @@ -6175,6 +6184,9 @@ func rewriteValueARM64_OpARM64MOD(v *Value) bool { break } d := auxIntToInt64(v_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARM64MOVDconst) v.AuxInt = int64ToAuxInt(c % d) return true @@ -6185,6 +6197,7 @@ func rewriteValueARM64_OpARM64MODW(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (MODW (MOVDconst [c]) (MOVDconst [d])) + // cond: d != 0 // result: (MOVDconst [int64(int32(c)%int32(d))]) for { if v_0.Op != OpARM64MOVDconst { @@ -6195,6 +6208,9 @@ func rewriteValueARM64_OpARM64MODW(v *Value) bool { break } d := auxIntToInt64(v_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARM64MOVDconst) v.AuxInt = int64ToAuxInt(int64(int32(c) % int32(d))) return true @@ -20423,6 +20439,7 @@ func rewriteValueARM64_OpARM64UDIV(v *Value) bool { return true } // match: (UDIV (MOVDconst [c]) (MOVDconst [d])) + // cond: d != 0 // result: (MOVDconst [int64(uint64(c)/uint64(d))]) for { if v_0.Op != OpARM64MOVDconst { @@ -20433,6 +20450,9 @@ func rewriteValueARM64_OpARM64UDIV(v *Value) bool { break } d := auxIntToInt64(v_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARM64MOVDconst) v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d))) return true @@ -20475,6 +20495,7 @@ func rewriteValueARM64_OpARM64UDIVW(v *Value) bool { return true } // match: (UDIVW (MOVDconst [c]) (MOVDconst [d])) + // cond: d != 0 // result: (MOVDconst [int64(uint32(c)/uint32(d))]) for { if v_0.Op != OpARM64MOVDconst { @@ -20485,6 +20506,9 @@ func rewriteValueARM64_OpARM64UDIVW(v *Value) bool { break } d := auxIntToInt64(v_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARM64MOVDconst) v.AuxInt = int64ToAuxInt(int64(uint32(c) / uint32(d))) return true @@ -20539,6 +20563,7 @@ func rewriteValueARM64_OpARM64UMOD(v *Value) bool { return true } // match: (UMOD (MOVDconst [c]) (MOVDconst [d])) + // cond: d != 0 // result: (MOVDconst [int64(uint64(c)%uint64(d))]) for { if v_0.Op != OpARM64MOVDconst { @@ -20549,6 +20574,9 @@ func rewriteValueARM64_OpARM64UMOD(v *Value) bool { break } d := auxIntToInt64(v_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARM64MOVDconst) v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d))) return true @@ -20608,6 +20636,7 @@ func rewriteValueARM64_OpARM64UMODW(v *Value) bool { return true } // match: (UMODW (MOVDconst [c]) (MOVDconst [d])) + // cond: d != 0 // result: (MOVDconst [int64(uint32(c)%uint32(d))]) for { if v_0.Op != OpARM64MOVDconst { @@ -20618,6 +20647,9 @@ func rewriteValueARM64_OpARM64UMODW(v *Value) bool { break } d := auxIntToInt64(v_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpARM64MOVDconst) v.AuxInt = int64ToAuxInt(int64(uint32(c) % uint32(d))) return true diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS.go b/src/cmd/compile/internal/ssa/rewriteMIPS.go index bbc331014f..3fc5527955 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS.go @@ -6421,6 +6421,7 @@ func rewriteValueMIPS_OpSelect0(v *Value) bool { break } // match: (Select0 (DIV (MOVWconst [c]) (MOVWconst [d]))) + // cond: d != 0 // result: (MOVWconst [c%d]) for { if v_0.Op != OpMIPSDIV { @@ -6437,11 +6438,15 @@ func rewriteValueMIPS_OpSelect0(v *Value) bool { break } d := auxIntToInt32(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpMIPSMOVWconst) v.AuxInt = int32ToAuxInt(c % d) return true } // match: (Select0 (DIVU (MOVWconst [c]) (MOVWconst [d]))) + // cond: d != 0 // result: (MOVWconst [int32(uint32(c)%uint32(d))]) for { if v_0.Op != OpMIPSDIVU { @@ -6458,6 +6463,9 @@ func rewriteValueMIPS_OpSelect0(v *Value) bool { break } d := auxIntToInt32(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpMIPSMOVWconst) v.AuxInt = int32ToAuxInt(int32(uint32(c) % uint32(d))) return true @@ -6609,6 +6617,7 @@ func rewriteValueMIPS_OpSelect1(v *Value) bool { break } // match: (Select1 (DIV (MOVWconst [c]) (MOVWconst [d]))) + // cond: d != 0 // result: (MOVWconst [c/d]) for { if v_0.Op != OpMIPSDIV { @@ -6625,11 +6634,15 @@ func rewriteValueMIPS_OpSelect1(v *Value) bool { break } d := auxIntToInt32(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpMIPSMOVWconst) v.AuxInt = int32ToAuxInt(c / d) return true } // match: (Select1 (DIVU (MOVWconst [c]) (MOVWconst [d]))) + // cond: d != 0 // result: (MOVWconst [int32(uint32(c)/uint32(d))]) for { if v_0.Op != OpMIPSDIVU { @@ -6646,6 +6659,9 @@ func rewriteValueMIPS_OpSelect1(v *Value) bool { break } d := auxIntToInt32(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpMIPSMOVWconst) v.AuxInt = int32ToAuxInt(int32(uint32(c) / uint32(d))) return true diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS64.go b/src/cmd/compile/internal/ssa/rewriteMIPS64.go index 29e3a8a363..d78f6089af 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS64.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS64.go @@ -6887,6 +6887,7 @@ func rewriteValueMIPS64_OpSelect0(v *Value) bool { return true } // match: (Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) + // cond: d != 0 // result: (MOVVconst [c%d]) for { if v_0.Op != OpMIPS64DIVV { @@ -6903,11 +6904,15 @@ func rewriteValueMIPS64_OpSelect0(v *Value) bool { break } d := auxIntToInt64(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpMIPS64MOVVconst) v.AuxInt = int64ToAuxInt(c % d) return true } // match: (Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) + // cond: d != 0 // result: (MOVVconst [int64(uint64(c)%uint64(d))]) for { if v_0.Op != OpMIPS64DIVVU { @@ -6924,6 +6929,9 @@ func rewriteValueMIPS64_OpSelect0(v *Value) bool { break } d := auxIntToInt64(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpMIPS64MOVVconst) v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d))) return true @@ -7099,6 +7107,7 @@ func rewriteValueMIPS64_OpSelect1(v *Value) bool { break } // match: (Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) + // cond: d != 0 // result: (MOVVconst [c/d]) for { if v_0.Op != OpMIPS64DIVV { @@ -7115,11 +7124,15 @@ func rewriteValueMIPS64_OpSelect1(v *Value) bool { break } d := auxIntToInt64(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpMIPS64MOVVconst) v.AuxInt = int64ToAuxInt(c / d) return true } // match: (Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) + // cond: d != 0 // result: (MOVVconst [int64(uint64(c)/uint64(d))]) for { if v_0.Op != OpMIPS64DIVVU { @@ -7136,6 +7149,9 @@ func rewriteValueMIPS64_OpSelect1(v *Value) bool { break } d := auxIntToInt64(v_0_1.AuxInt) + if !(d != 0) { + break + } v.reset(OpMIPS64MOVVconst) v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d))) return true diff --git a/test/fixedbugs/issue43099.go b/test/fixedbugs/issue43099.go new file mode 100644 index 0000000000..16f18e5f96 --- /dev/null +++ b/test/fixedbugs/issue43099.go @@ -0,0 +1,34 @@ +// compile + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check to make sure we don't try to constant fold a divide by zero. +// This is a tricky test, as we need a value that's not recognized as 0 +// until lowering (otherwise it gets handled in a different path). + +package p + +func f() { + var i int + var s string + for i > 0 { + _ = s[0] + i++ + } + + var c chan int + c <- 1 % i +} + +func f32() uint32 { + s := "\x00\x00\x00\x00" + c := uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 | uint32(s[3])<<24 + return 1 / c +} +func f64() uint64 { + s := "\x00\x00\x00\x00\x00\x00\x00\x00" + c := uint64(s[0]) | uint64(s[1])<<8 | uint64(s[2])<<16 | uint64(s[3])<<24 | uint64(s[4])<<32 | uint64(s[5])<<40 | uint64(s[6])<<48 | uint64(s[7])<<56 + return 1 / c +} From 9c5241e52020cf77683cd260a5fa3f3f029ed80c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 7 Dec 2020 20:05:17 -0800 Subject: [PATCH 208/212] [dev.regabi] cmd/compile: remove unnecessary String methods There were only a few places these were still used, none of which justify generating all this code. Instead rewrite them to use fmt.Sprint or simpler means. Passes buildall w/ toolstash -cmp. Change-Id: Ibd123a1696941a597f0cb4dcc96cda8ced672140 Reviewed-on: https://go-review.googlesource.com/c/go/+/276072 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/const.go | 2 +- src/cmd/compile/internal/gc/typecheck.go | 15 ++++--- src/cmd/compile/internal/gc/universe.go | 11 ----- src/cmd/compile/internal/ir/mini.go | 1 - src/cmd/compile/internal/ir/mknode.go | 1 - src/cmd/compile/internal/ir/node.go | 1 - src/cmd/compile/internal/ir/node_gen.go | 56 ------------------------ src/cmd/compile/internal/ssa/op.go | 1 - test/fixedbugs/issue22822.go | 4 +- 9 files changed, 12 insertions(+), 80 deletions(-) diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 80799580c6..677ed17dd9 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -887,7 +887,7 @@ func (s *constSet) add(pos src.XPos, n ir.Node, what, where string) { // // TODO(mdempsky): This could probably be a fmt.go flag. func nodeAndVal(n ir.Node) string { - show := n.String() + show := fmt.Sprint(n) val := ir.ConstValue(n) if s := fmt.Sprintf("%#v", val); show != s { show += " (value " + s + ")" diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index d88989f83c..f187880e28 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -956,7 +956,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { t := n.Left().Type() if t == nil { - base.UpdateErrorDot(ir.Line(n), n.Left().String(), n.String()) + base.UpdateErrorDot(ir.Line(n), fmt.Sprint(n.Left()), fmt.Sprint(n)) n.SetType(nil) return n } @@ -1431,14 +1431,15 @@ func typecheck1(n ir.Node, top int) (res ir.Node) { default: n.SetOp(ir.OCALLFUNC) if t.Kind() != types.TFUNC { - name := l.String() - if isBuiltinFuncName(name) && l.Name().Defn != nil { - // be more specific when the function + // TODO(mdempsky): Remove "o.Sym() != nil" once we stop + // using ir.Name for numeric literals. + if o := ir.Orig(l); o.Name() != nil && o.Sym() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil { + // be more specific when the non-function // name matches a predeclared function - base.Errorf("cannot call non-function %s (type %v), declared at %s", - name, t, base.FmtPos(l.Name().Defn.Pos())) + base.Errorf("cannot call non-function %L, declared at %s", + l, base.FmtPos(o.Name().Pos())) } else { - base.Errorf("cannot call non-function %s (type %v)", name, t) + base.Errorf("cannot call non-function %L", l) } n.SetType(nil) return n diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index c592e37497..66ca0d01b3 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -65,17 +65,6 @@ var builtinFuncs = [...]struct { {"recover", ir.ORECOVER}, } -// isBuiltinFuncName reports whether name matches a builtin function -// name. -func isBuiltinFuncName(name string) bool { - for _, fn := range &builtinFuncs { - if fn.name == name { - return true - } - } - return false -} - var unsafeFuncs = [...]struct { name string op ir.Op diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index 7ecdcbf32f..bf221f75ed 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -35,7 +35,6 @@ type miniNode struct { esc uint16 } -func (n *miniNode) String() string { panic(1) } func (n *miniNode) Format(s fmt.State, verb rune) { panic(1) } func (n *miniNode) copy() Node { panic(1) } func (n *miniNode) doChildren(do func(Node) error) error { panic(1) } diff --git a/src/cmd/compile/internal/ir/mknode.go b/src/cmd/compile/internal/ir/mknode.go index 18d768ceb1..f9b398fe28 100644 --- a/src/cmd/compile/internal/ir/mknode.go +++ b/src/cmd/compile/internal/ir/mknode.go @@ -65,7 +65,6 @@ func main() { } fmt.Fprintf(&buf, "\n") - fmt.Fprintf(&buf, "func (n *%s) String() string { return fmt.Sprint(n) }\n", name) fmt.Fprintf(&buf, "func (n *%s) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }\n", name) fmt.Fprintf(&buf, "func (n *%s) copy() Node { c := *n\n", name) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 598659a3db..dc86b6c683 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -20,7 +20,6 @@ import ( type Node interface { // Formatting Format(s fmt.State, verb rune) - String() string // Source position. Pos() src.XPos diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index 264171e797..39d8f03ddc 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -4,7 +4,6 @@ package ir import "fmt" -func (n *AddStringExpr) String() string { return fmt.Sprint(n) } func (n *AddStringExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *AddStringExpr) copy() Node { c := *n @@ -23,7 +22,6 @@ func (n *AddStringExpr) editChildren(edit func(Node) Node) { editList(n.List_, edit) } -func (n *AddrExpr) String() string { return fmt.Sprint(n) } func (n *AddrExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *AddrExpr) copy() Node { c := *n @@ -43,7 +41,6 @@ func (n *AddrExpr) editChildren(edit func(Node) Node) { n.Alloc = maybeEdit(n.Alloc, edit) } -func (n *ArrayType) String() string { return fmt.Sprint(n) } func (n *ArrayType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ArrayType) copy() Node { c := *n @@ -60,7 +57,6 @@ func (n *ArrayType) editChildren(edit func(Node) Node) { n.Elem = maybeEdit(n.Elem, edit) } -func (n *AssignListStmt) String() string { return fmt.Sprint(n) } func (n *AssignListStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *AssignListStmt) copy() Node { c := *n @@ -82,7 +78,6 @@ func (n *AssignListStmt) editChildren(edit func(Node) Node) { editList(n.Rhs, edit) } -func (n *AssignOpStmt) String() string { return fmt.Sprint(n) } func (n *AssignOpStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *AssignOpStmt) copy() Node { c := *n @@ -102,7 +97,6 @@ func (n *AssignOpStmt) editChildren(edit func(Node) Node) { n.Y = maybeEdit(n.Y, edit) } -func (n *AssignStmt) String() string { return fmt.Sprint(n) } func (n *AssignStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *AssignStmt) copy() Node { c := *n @@ -122,7 +116,6 @@ func (n *AssignStmt) editChildren(edit func(Node) Node) { n.Y = maybeEdit(n.Y, edit) } -func (n *BinaryExpr) String() string { return fmt.Sprint(n) } func (n *BinaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *BinaryExpr) copy() Node { c := *n @@ -142,7 +135,6 @@ func (n *BinaryExpr) editChildren(edit func(Node) Node) { n.Y = maybeEdit(n.Y, edit) } -func (n *BlockStmt) String() string { return fmt.Sprint(n) } func (n *BlockStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *BlockStmt) copy() Node { c := *n @@ -161,7 +153,6 @@ func (n *BlockStmt) editChildren(edit func(Node) Node) { editList(n.List_, edit) } -func (n *BranchStmt) String() string { return fmt.Sprint(n) } func (n *BranchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *BranchStmt) copy() Node { c := *n @@ -177,7 +168,6 @@ func (n *BranchStmt) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *CallExpr) String() string { return fmt.Sprint(n) } func (n *CallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *CallExpr) copy() Node { c := *n @@ -204,7 +194,6 @@ func (n *CallExpr) editChildren(edit func(Node) Node) { editList(n.Body_, edit) } -func (n *CallPartExpr) String() string { return fmt.Sprint(n) } func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *CallPartExpr) copy() Node { c := *n @@ -222,7 +211,6 @@ func (n *CallPartExpr) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } -func (n *CaseStmt) String() string { return fmt.Sprint(n) } func (n *CaseStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *CaseStmt) copy() Node { c := *n @@ -249,7 +237,6 @@ func (n *CaseStmt) editChildren(edit func(Node) Node) { editList(n.Body_, edit) } -func (n *ChanType) String() string { return fmt.Sprint(n) } func (n *ChanType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ChanType) copy() Node { c := *n @@ -264,7 +251,6 @@ func (n *ChanType) editChildren(edit func(Node) Node) { n.Elem = maybeEdit(n.Elem, edit) } -func (n *ClosureExpr) String() string { return fmt.Sprint(n) } func (n *ClosureExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ClosureExpr) copy() Node { c := *n @@ -280,7 +266,6 @@ func (n *ClosureExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *ClosureReadExpr) String() string { return fmt.Sprint(n) } func (n *ClosureReadExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ClosureReadExpr) copy() Node { c := *n @@ -296,7 +281,6 @@ func (n *ClosureReadExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *CompLitExpr) String() string { return fmt.Sprint(n) } func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *CompLitExpr) copy() Node { c := *n @@ -317,7 +301,6 @@ func (n *CompLitExpr) editChildren(edit func(Node) Node) { editList(n.List_, edit) } -func (n *ConstExpr) String() string { return fmt.Sprint(n) } func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ConstExpr) copy() Node { c := *n @@ -333,7 +316,6 @@ func (n *ConstExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *ConvExpr) String() string { return fmt.Sprint(n) } func (n *ConvExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ConvExpr) copy() Node { c := *n @@ -351,7 +333,6 @@ func (n *ConvExpr) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } -func (n *Decl) String() string { return fmt.Sprint(n) } func (n *Decl) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *Decl) copy() Node { c := *n @@ -366,7 +347,6 @@ func (n *Decl) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } -func (n *ForStmt) String() string { return fmt.Sprint(n) } func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ForStmt) copy() Node { c := *n @@ -392,7 +372,6 @@ func (n *ForStmt) editChildren(edit func(Node) Node) { editList(n.Body_, edit) } -func (n *Func) String() string { return fmt.Sprint(n) } func (n *Func) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *Func) copy() Node { c := *n @@ -408,7 +387,6 @@ func (n *Func) editChildren(edit func(Node) Node) { editList(n.Body_, edit) } -func (n *FuncType) String() string { return fmt.Sprint(n) } func (n *FuncType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *FuncType) copy() Node { c := *n @@ -432,7 +410,6 @@ func (n *FuncType) editChildren(edit func(Node) Node) { editFields(n.Results, edit) } -func (n *GoDeferStmt) String() string { return fmt.Sprint(n) } func (n *GoDeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *GoDeferStmt) copy() Node { c := *n @@ -450,7 +427,6 @@ func (n *GoDeferStmt) editChildren(edit func(Node) Node) { n.Call = maybeEdit(n.Call, edit) } -func (n *Ident) String() string { return fmt.Sprint(n) } func (n *Ident) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *Ident) copy() Node { c := *n @@ -466,7 +442,6 @@ func (n *Ident) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *IfStmt) String() string { return fmt.Sprint(n) } func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *IfStmt) copy() Node { c := *n @@ -490,7 +465,6 @@ func (n *IfStmt) editChildren(edit func(Node) Node) { editList(n.Else, edit) } -func (n *IndexExpr) String() string { return fmt.Sprint(n) } func (n *IndexExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *IndexExpr) copy() Node { c := *n @@ -510,7 +484,6 @@ func (n *IndexExpr) editChildren(edit func(Node) Node) { n.Index = maybeEdit(n.Index, edit) } -func (n *InlineMarkStmt) String() string { return fmt.Sprint(n) } func (n *InlineMarkStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *InlineMarkStmt) copy() Node { c := *n @@ -526,7 +499,6 @@ func (n *InlineMarkStmt) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *InlinedCallExpr) String() string { return fmt.Sprint(n) } func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *InlinedCallExpr) copy() Node { c := *n @@ -548,7 +520,6 @@ func (n *InlinedCallExpr) editChildren(edit func(Node) Node) { editList(n.ReturnVars, edit) } -func (n *InterfaceType) String() string { return fmt.Sprint(n) } func (n *InterfaceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *InterfaceType) copy() Node { c := *n @@ -564,7 +535,6 @@ func (n *InterfaceType) editChildren(edit func(Node) Node) { editFields(n.Methods, edit) } -func (n *KeyExpr) String() string { return fmt.Sprint(n) } func (n *KeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *KeyExpr) copy() Node { c := *n @@ -584,7 +554,6 @@ func (n *KeyExpr) editChildren(edit func(Node) Node) { n.Value = maybeEdit(n.Value, edit) } -func (n *LabelStmt) String() string { return fmt.Sprint(n) } func (n *LabelStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *LabelStmt) copy() Node { c := *n @@ -600,7 +569,6 @@ func (n *LabelStmt) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *LogicalExpr) String() string { return fmt.Sprint(n) } func (n *LogicalExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *LogicalExpr) copy() Node { c := *n @@ -620,7 +588,6 @@ func (n *LogicalExpr) editChildren(edit func(Node) Node) { n.Y = maybeEdit(n.Y, edit) } -func (n *MakeExpr) String() string { return fmt.Sprint(n) } func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *MakeExpr) copy() Node { c := *n @@ -640,7 +607,6 @@ func (n *MakeExpr) editChildren(edit func(Node) Node) { n.Cap = maybeEdit(n.Cap, edit) } -func (n *MapType) String() string { return fmt.Sprint(n) } func (n *MapType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *MapType) copy() Node { c := *n @@ -657,7 +623,6 @@ func (n *MapType) editChildren(edit func(Node) Node) { n.Elem = maybeEdit(n.Elem, edit) } -func (n *MethodExpr) String() string { return fmt.Sprint(n) } func (n *MethodExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *MethodExpr) copy() Node { c := *n @@ -677,7 +642,6 @@ func (n *MethodExpr) editChildren(edit func(Node) Node) { n.M = maybeEdit(n.M, edit) } -func (n *Name) String() string { return fmt.Sprint(n) } func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *Name) copy() Node { c := *n @@ -690,7 +654,6 @@ func (n *Name) doChildren(do func(Node) error) error { func (n *Name) editChildren(edit func(Node) Node) { } -func (n *NilExpr) String() string { return fmt.Sprint(n) } func (n *NilExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *NilExpr) copy() Node { c := *n @@ -706,7 +669,6 @@ func (n *NilExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *ParenExpr) String() string { return fmt.Sprint(n) } func (n *ParenExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ParenExpr) copy() Node { c := *n @@ -724,7 +686,6 @@ func (n *ParenExpr) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } -func (n *PkgName) String() string { return fmt.Sprint(n) } func (n *PkgName) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *PkgName) copy() Node { c := *n @@ -737,7 +698,6 @@ func (n *PkgName) doChildren(do func(Node) error) error { func (n *PkgName) editChildren(edit func(Node) Node) { } -func (n *RangeStmt) String() string { return fmt.Sprint(n) } func (n *RangeStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *RangeStmt) copy() Node { c := *n @@ -761,7 +721,6 @@ func (n *RangeStmt) editChildren(edit func(Node) Node) { editList(n.Body_, edit) } -func (n *ResultExpr) String() string { return fmt.Sprint(n) } func (n *ResultExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ResultExpr) copy() Node { c := *n @@ -777,7 +736,6 @@ func (n *ResultExpr) editChildren(edit func(Node) Node) { editList(n.init, edit) } -func (n *ReturnStmt) String() string { return fmt.Sprint(n) } func (n *ReturnStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ReturnStmt) copy() Node { c := *n @@ -796,7 +754,6 @@ func (n *ReturnStmt) editChildren(edit func(Node) Node) { editList(n.Results, edit) } -func (n *SelectStmt) String() string { return fmt.Sprint(n) } func (n *SelectStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SelectStmt) copy() Node { c := *n @@ -818,7 +775,6 @@ func (n *SelectStmt) editChildren(edit func(Node) Node) { editList(n.Compiled, edit) } -func (n *SelectorExpr) String() string { return fmt.Sprint(n) } func (n *SelectorExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SelectorExpr) copy() Node { c := *n @@ -836,7 +792,6 @@ func (n *SelectorExpr) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } -func (n *SendStmt) String() string { return fmt.Sprint(n) } func (n *SendStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SendStmt) copy() Node { c := *n @@ -856,7 +811,6 @@ func (n *SendStmt) editChildren(edit func(Node) Node) { n.Value = maybeEdit(n.Value, edit) } -func (n *SliceExpr) String() string { return fmt.Sprint(n) } func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SliceExpr) copy() Node { c := *n @@ -877,7 +831,6 @@ func (n *SliceExpr) editChildren(edit func(Node) Node) { editList(n.List_, edit) } -func (n *SliceHeaderExpr) String() string { return fmt.Sprint(n) } func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SliceHeaderExpr) copy() Node { c := *n @@ -898,7 +851,6 @@ func (n *SliceHeaderExpr) editChildren(edit func(Node) Node) { editList(n.LenCap_, edit) } -func (n *SliceType) String() string { return fmt.Sprint(n) } func (n *SliceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SliceType) copy() Node { c := *n @@ -913,7 +865,6 @@ func (n *SliceType) editChildren(edit func(Node) Node) { n.Elem = maybeEdit(n.Elem, edit) } -func (n *StarExpr) String() string { return fmt.Sprint(n) } func (n *StarExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *StarExpr) copy() Node { c := *n @@ -931,7 +882,6 @@ func (n *StarExpr) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } -func (n *StructKeyExpr) String() string { return fmt.Sprint(n) } func (n *StructKeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *StructKeyExpr) copy() Node { c := *n @@ -949,7 +899,6 @@ func (n *StructKeyExpr) editChildren(edit func(Node) Node) { n.Value = maybeEdit(n.Value, edit) } -func (n *StructType) String() string { return fmt.Sprint(n) } func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *StructType) copy() Node { c := *n @@ -965,7 +914,6 @@ func (n *StructType) editChildren(edit func(Node) Node) { editFields(n.Fields, edit) } -func (n *SwitchStmt) String() string { return fmt.Sprint(n) } func (n *SwitchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *SwitchStmt) copy() Node { c := *n @@ -989,7 +937,6 @@ func (n *SwitchStmt) editChildren(edit func(Node) Node) { editList(n.Compiled, edit) } -func (n *TypeAssertExpr) String() string { return fmt.Sprint(n) } func (n *TypeAssertExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *TypeAssertExpr) copy() Node { c := *n @@ -1012,7 +959,6 @@ func (n *TypeAssertExpr) editChildren(edit func(Node) Node) { editList(n.Itab, edit) } -func (n *TypeSwitchGuard) String() string { return fmt.Sprint(n) } func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *TypeSwitchGuard) copy() Node { c := *n @@ -1033,7 +979,6 @@ func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } -func (n *UnaryExpr) String() string { return fmt.Sprint(n) } func (n *UnaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *UnaryExpr) copy() Node { c := *n @@ -1051,7 +996,6 @@ func (n *UnaryExpr) editChildren(edit func(Node) Node) { n.X = maybeEdit(n.X, edit) } -func (n *typeNode) String() string { return fmt.Sprint(n) } func (n *typeNode) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *typeNode) copy() Node { c := *n diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index 97726a6f95..9bc5aaec02 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -248,7 +248,6 @@ const ( // - a *obj.LSym, for an offset from SB (the global pointer) // - nil, for no offset type Sym interface { - String() string CanBeAnSSASym() CanBeAnSSAAux() } diff --git a/test/fixedbugs/issue22822.go b/test/fixedbugs/issue22822.go index e449ddb186..0e838cb597 100644 --- a/test/fixedbugs/issue22822.go +++ b/test/fixedbugs/issue22822.go @@ -12,5 +12,7 @@ package main func F() { slice := []int{1, 2, 3} len := int(2) - println(len(slice)) // ERROR "cannot call non-function len .type int., declared at" + println(len(slice)) // ERROR "cannot call non-function len .type int., declared at LINE-1" + const iota = 1 + println(iota(slice)) // ERROR "cannot call non-function iota .type int., declared at LINE-1" } From 2b76429eb01ec1752f7622e3011babd7140ab870 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Tue, 24 Nov 2020 18:09:00 -0500 Subject: [PATCH 209/212] [dev.regabi] cmd/compile: refactor type initialization code into helper Create a helper routine for initializing the types package, so as make it easier to use in unit testing (in a follow-on patch). Change-Id: I0f937788dfd34ac6641a4f28c16e47008aa08116 Reviewed-on: https://go-review.googlesource.com/c/go/+/273010 Run-TryBot: Than McIntosh TryBot-Result: Go Bot Trust: Than McIntosh Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/main.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 503dc449d3..368fe1fcab 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -210,13 +210,7 @@ func Main(archInit func(*Arch)) { // initialize types package // (we need to do this to break dependencies that otherwise // would lead to import cycles) - types.Widthptr = Widthptr - types.Dowidth = dowidth - types.TypeLinkSym = func(t *types.Type) *obj.LSym { - return typenamesym(t).Linksym() - } - - initUniverse() + initializeTypesPackage() dclcontext = ir.PEXTERN @@ -1125,3 +1119,13 @@ func parseLang(s string) (lang, error) { } return lang{major: major, minor: minor}, nil } + +func initializeTypesPackage() { + types.Widthptr = Widthptr + types.Dowidth = dowidth + types.TypeLinkSym = func(t *types.Type) *obj.LSym { + return typenamesym(t).Linksym() + } + + initUniverse() +} From 7e17b46c58cbb0aff2b42490a73e807bb04757d7 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Wed, 2 Dec 2020 16:13:45 -0500 Subject: [PATCH 210/212] [dev.regabi] cmd/compile/internal/types: add IsScalar query method Add method Type.IsScalar() method, which returns TRUE for numeric and pointer-shaped types, false for composites such as string/array/slice/struct. Change-Id: Ie53c71c07c5b3fbae11b48addd172343dc6bf3fd Reviewed-on: https://go-review.googlesource.com/c/go/+/274857 Run-TryBot: Than McIntosh TryBot-Result: Go Bot Trust: Than McIntosh Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types/type.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index e968a799e3..4d1d30133c 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1335,6 +1335,20 @@ func (t *Type) IsEmptyInterface() bool { return t.IsInterface() && t.NumFields() == 0 } +// IsScalar reports whether 't' is a scalar Go type, e.g. +// bool/int/float/complex. Note that struct and array types consisting +// of a single scalar element are not considered scalar, likewise +// pointer types are also not considered scalar. +func (t *Type) IsScalar() bool { + switch t.kind { + case TBOOL, TINT8, TUINT8, TINT16, TUINT16, TINT32, + TUINT32, TINT64, TUINT64, TINT, TUINT, + TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64: + return true + } + return false +} + func (t *Type) PtrTo() *Type { return NewPtr(t) } From 8ce37e4110316030159972e17c67152e8f8e9359 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 10 Dec 2020 21:04:41 -0800 Subject: [PATCH 211/212] [dev.regabi] cmd/compile: fix noopt builder The non-simple, phi-insertion algorithm can leave OpFwdRefs in the SSA graph unresolved if they're in dead blocks. Normally, these would be harmlessly removed later during SSA dead-code elimination, but those passes are omitted for -N builds. And so they reach zcse, where the Value.Aux is used within a hash map. This became a problem after golang.org/cl/275788, which added FwdRefAux to wrap OpFwdRef's ir.Node, and to ensure that it's not compared for equality / used as a map key. This CL adds a simple fix: if there are any OpFwdRefs remaining after resolveFwdRef, then they must be dead code and we can simply replace them with OpUnknown. Change-Id: I72e4116d52d3f6441ebb0bf6160906617cd59513 Reviewed-on: https://go-review.googlesource.com/c/go/+/277075 Trust: Matthew Dempsky Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/phi.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmd/compile/internal/gc/phi.go b/src/cmd/compile/internal/gc/phi.go index def11e1be0..32c330b584 100644 --- a/src/cmd/compile/internal/gc/phi.go +++ b/src/cmd/compile/internal/gc/phi.go @@ -188,6 +188,11 @@ levels: if v.Op == ssa.OpPhi { v.AuxInt = 0 } + // Any remaining FwdRefs are dead code. + if v.Op == ssa.OpFwdRef { + v.Op = ssa.OpUnknown + v.Aux = nil + } } } } From 89f38323faa57d3f7475016f778be69fcffbe9fb Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Tue, 24 Nov 2020 18:10:11 -0500 Subject: [PATCH 212/212] [dev.regabi] cmd/compile: add register ABI analysis utilities Introduce a new utility routine for analyzing a given function signature to how its various input and output parameters will be passed (in registers or on the stack) for a given ABI description, along with some unit tests. Change-Id: Id64a98a0a142e42dd9c2dc9f6607c0d827ef84fb Reviewed-on: https://go-review.googlesource.com/c/go/+/273011 Run-TryBot: Than McIntosh Reviewed-by: Jeremy Faller Trust: Than McIntosh --- src/cmd/compile/fmtmap_test.go | 1 + src/cmd/compile/internal/gc/abiutils.go | 351 ++++++++++++++++++ src/cmd/compile/internal/gc/abiutils_test.go | 270 ++++++++++++++ .../compile/internal/gc/abiutilsaux_test.go | 157 ++++++++ 4 files changed, 779 insertions(+) create mode 100644 src/cmd/compile/internal/gc/abiutils.go create mode 100644 src/cmd/compile/internal/gc/abiutils_test.go create mode 100644 src/cmd/compile/internal/gc/abiutilsaux_test.go diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index e62b9613e1..9bc059c2e4 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -36,6 +36,7 @@ var knownFormats = map[string]string{ "*math/big.Int %s": "", "[]cmd/compile/internal/syntax.token %s": "", "cmd/compile/internal/arm.shift %d": "", + "cmd/compile/internal/gc.RegIndex %d": "", "cmd/compile/internal/gc.initKind %d": "", "cmd/compile/internal/ir.Class %d": "", "cmd/compile/internal/ir.Node %+v": "", diff --git a/src/cmd/compile/internal/gc/abiutils.go b/src/cmd/compile/internal/gc/abiutils.go new file mode 100644 index 0000000000..19de14d48c --- /dev/null +++ b/src/cmd/compile/internal/gc/abiutils.go @@ -0,0 +1,351 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gc + +import ( + "cmd/compile/internal/types" + "cmd/internal/src" + "fmt" + "sync" +) + +//...................................................................... +// +// Public/exported bits of the ABI utilities. +// + +// ABIParamResultInfo stores the results of processing a given +// function type to compute stack layout and register assignments. For +// each input and output parameter we capture whether the param was +// register-assigned (and to which register(s)) or the stack offset +// for the param if is not going to be passed in registers according +// to the rules in the Go internal ABI specification (1.17). +type ABIParamResultInfo struct { + inparams []ABIParamAssignment // Includes receiver for method calls. Does NOT include hidden closure pointer. + outparams []ABIParamAssignment + intSpillSlots int + floatSpillSlots int + offsetToSpillArea int64 + config ABIConfig // to enable String() method +} + +// RegIndex stores the index into the set of machine registers used by +// the ABI on a specific architecture for parameter passing. RegIndex +// values 0 through N-1 (where N is the number of integer registers +// used for param passing according to the ABI rules) describe integer +// registers; values N through M (where M is the number of floating +// point registers used). Thus if the ABI says there are 5 integer +// registers and 7 floating point registers, then RegIndex value of 4 +// indicates the 5th integer register, and a RegIndex value of 11 +// indicates the 7th floating point register. +type RegIndex uint8 + +// ABIParamAssignment holds information about how a specific param or +// result will be passed: in registers (in which case 'Registers' is +// populated) or on the stack (in which case 'Offset' is set to a +// non-negative stack offset. The values in 'Registers' are indices (as +// described above), not architected registers. +type ABIParamAssignment struct { + Type *types.Type + Registers []RegIndex + Offset int32 +} + +// RegAmounts holds a specified number of integer/float registers. +type RegAmounts struct { + intRegs int + floatRegs int +} + +// ABIConfig captures the number of registers made available +// by the ABI rules for parameter passing and result returning. +type ABIConfig struct { + // Do we need anything more than this? + regAmounts RegAmounts +} + +// ABIAnalyze takes a function type 't' and an ABI rules description +// 'config' and analyzes the function to determine how its parameters +// and results will be passed (in registers or on the stack), returning +// an ABIParamResultInfo object that holds the results of the analysis. +func ABIAnalyze(t *types.Type, config ABIConfig) ABIParamResultInfo { + setup() + s := assignState{ + rTotal: config.regAmounts, + } + result := ABIParamResultInfo{config: config} + + // Receiver + ft := t.FuncType() + if t.NumRecvs() != 0 { + rfsl := ft.Receiver.FieldSlice() + result.inparams = append(result.inparams, + s.assignParamOrReturn(rfsl[0].Type)) + } + + // Inputs + ifsl := ft.Params.FieldSlice() + for _, f := range ifsl { + result.inparams = append(result.inparams, + s.assignParamOrReturn(f.Type)) + } + s.stackOffset = Rnd(s.stackOffset, int64(Widthreg)) + + // Record number of spill slots needed. + result.intSpillSlots = s.rUsed.intRegs + result.floatSpillSlots = s.rUsed.floatRegs + + // Outputs + s.rUsed = RegAmounts{} + ofsl := ft.Results.FieldSlice() + for _, f := range ofsl { + result.outparams = append(result.outparams, s.assignParamOrReturn(f.Type)) + } + result.offsetToSpillArea = s.stackOffset + + return result +} + +//...................................................................... +// +// Non-public portions. + +// regString produces a human-readable version of a RegIndex. +func (c *RegAmounts) regString(r RegIndex) string { + if int(r) < c.intRegs { + return fmt.Sprintf("I%d", int(r)) + } else if int(r) < c.intRegs+c.floatRegs { + return fmt.Sprintf("F%d", int(r)-c.intRegs) + } + return fmt.Sprintf("%d", r) +} + +// toString method renders an ABIParamAssignment in human-readable +// form, suitable for debugging or unit testing. +func (ri *ABIParamAssignment) toString(config ABIConfig) string { + regs := "R{" + for _, r := range ri.Registers { + regs += " " + config.regAmounts.regString(r) + } + return fmt.Sprintf("%s } offset: %d typ: %v", regs, ri.Offset, ri.Type) +} + +// toString method renders an ABIParamResultInfo in human-readable +// form, suitable for debugging or unit testing. +func (ri *ABIParamResultInfo) String() string { + res := "" + for k, p := range ri.inparams { + res += fmt.Sprintf("IN %d: %s\n", k, p.toString(ri.config)) + } + for k, r := range ri.outparams { + res += fmt.Sprintf("OUT %d: %s\n", k, r.toString(ri.config)) + } + res += fmt.Sprintf("intspill: %d floatspill: %d offsetToSpillArea: %d", + ri.intSpillSlots, ri.floatSpillSlots, ri.offsetToSpillArea) + return res +} + +// assignState holds intermediate state during the register assigning process +// for a given function signature. +type assignState struct { + rTotal RegAmounts // total reg amounts from ABI rules + rUsed RegAmounts // regs used by params completely assigned so far + pUsed RegAmounts // regs used by the current param (or pieces therein) + stackOffset int64 // current stack offset +} + +// stackSlot returns a stack offset for a param or result of the +// specified type. +func (state *assignState) stackSlot(t *types.Type) int64 { + if t.Align > 0 { + state.stackOffset = Rnd(state.stackOffset, int64(t.Align)) + } + rv := state.stackOffset + state.stackOffset += t.Width + return rv +} + +// allocateRegs returns a set of register indices for a parameter or result +// that we've just determined to be register-assignable. The number of registers +// needed is assumed to be stored in state.pUsed. +func (state *assignState) allocateRegs() []RegIndex { + regs := []RegIndex{} + + // integer + for r := state.rUsed.intRegs; r < state.rUsed.intRegs+state.pUsed.intRegs; r++ { + regs = append(regs, RegIndex(r)) + } + state.rUsed.intRegs += state.pUsed.intRegs + + // floating + for r := state.rUsed.floatRegs; r < state.rUsed.floatRegs+state.pUsed.floatRegs; r++ { + regs = append(regs, RegIndex(r+state.rTotal.intRegs)) + } + state.rUsed.floatRegs += state.pUsed.floatRegs + + return regs +} + +// regAllocate creates a register ABIParamAssignment object for a param +// or result with the specified type, as a final step (this assumes +// that all of the safety/suitability analysis is complete). +func (state *assignState) regAllocate(t *types.Type) ABIParamAssignment { + return ABIParamAssignment{ + Type: t, + Registers: state.allocateRegs(), + Offset: -1, + } +} + +// stackAllocate creates a stack memory ABIParamAssignment object for +// a param or result with the specified type, as a final step (this +// assumes that all of the safety/suitability analysis is complete). +func (state *assignState) stackAllocate(t *types.Type) ABIParamAssignment { + return ABIParamAssignment{ + Type: t, + Offset: int32(state.stackSlot(t)), + } +} + +// intUsed returns the number of integer registers consumed +// at a given point within an assignment stage. +func (state *assignState) intUsed() int { + return state.rUsed.intRegs + state.pUsed.intRegs +} + +// floatUsed returns the number of floating point registers consumed at +// a given point within an assignment stage. +func (state *assignState) floatUsed() int { + return state.rUsed.floatRegs + state.pUsed.floatRegs +} + +// regassignIntegral examines a param/result of integral type 't' to +// determines whether it can be register-assigned. Returns TRUE if we +// can register allocate, FALSE otherwise (and updates state +// accordingly). +func (state *assignState) regassignIntegral(t *types.Type) bool { + regsNeeded := int(Rnd(t.Width, int64(Widthptr)) / int64(Widthptr)) + + // Floating point and complex. + if t.IsFloat() || t.IsComplex() { + if regsNeeded+state.floatUsed() > state.rTotal.floatRegs { + // not enough regs + return false + } + state.pUsed.floatRegs += regsNeeded + return true + } + + // Non-floating point + if regsNeeded+state.intUsed() > state.rTotal.intRegs { + // not enough regs + return false + } + state.pUsed.intRegs += regsNeeded + return true +} + +// regassignArray processes an array type (or array component within some +// other enclosing type) to determine if it can be register assigned. +// Returns TRUE if we can register allocate, FALSE otherwise. +func (state *assignState) regassignArray(t *types.Type) bool { + + nel := t.NumElem() + if nel == 0 { + return true + } + if nel > 1 { + // Not an array of length 1: stack assign + return false + } + // Visit element + return state.regassign(t.Elem()) +} + +// regassignStruct processes a struct type (or struct component within +// some other enclosing type) to determine if it can be register +// assigned. Returns TRUE if we can register allocate, FALSE otherwise. +func (state *assignState) regassignStruct(t *types.Type) bool { + for _, field := range t.FieldSlice() { + if !state.regassign(field.Type) { + return false + } + } + return true +} + +// synthOnce ensures that we only create the synth* fake types once. +var synthOnce sync.Once + +// synthSlice, synthString, and syncIface are synthesized struct types +// meant to capture the underlying implementations of string/slice/interface. +var synthSlice *types.Type +var synthString *types.Type +var synthIface *types.Type + +// setup performs setup for the register assignment utilities, manufacturing +// a small set of synthesized types that we'll need along the way. +func setup() { + synthOnce.Do(func() { + fname := types.BuiltinPkg.Lookup + nxp := src.NoXPos + unsp := types.Types[types.TUNSAFEPTR] + ui := types.Types[types.TUINTPTR] + synthSlice = types.NewStruct(types.NoPkg, []*types.Field{ + types.NewField(nxp, fname("ptr"), unsp), + types.NewField(nxp, fname("len"), ui), + types.NewField(nxp, fname("cap"), ui), + }) + synthString = types.NewStruct(types.NoPkg, []*types.Field{ + types.NewField(nxp, fname("data"), unsp), + types.NewField(nxp, fname("len"), ui), + }) + synthIface = types.NewStruct(types.NoPkg, []*types.Field{ + types.NewField(nxp, fname("f1"), unsp), + types.NewField(nxp, fname("f2"), unsp), + }) + }) +} + +// regassign examines a given param type (or component within some +// composite) to determine if it can be register assigned. Returns +// TRUE if we can register allocate, FALSE otherwise. +func (state *assignState) regassign(pt *types.Type) bool { + typ := pt.Kind() + if pt.IsScalar() || pt.IsPtrShaped() { + return state.regassignIntegral(pt) + } + switch typ { + case types.TARRAY: + return state.regassignArray(pt) + case types.TSTRUCT: + return state.regassignStruct(pt) + case types.TSLICE: + return state.regassignStruct(synthSlice) + case types.TSTRING: + return state.regassignStruct(synthString) + case types.TINTER: + return state.regassignStruct(synthIface) + default: + panic("not expected") + } +} + +// assignParamOrReturn processes a given receiver, param, or result +// of type 'pt' to determine whether it can be register assigned. +// The result of the analysis is recorded in the result +// ABIParamResultInfo held in 'state'. +func (state *assignState) assignParamOrReturn(pt *types.Type) ABIParamAssignment { + state.pUsed = RegAmounts{} + if pt.Width == types.BADWIDTH { + panic("should never happen") + } else if pt.Width == 0 { + return state.stackAllocate(pt) + } else if state.regassign(pt) { + return state.regAllocate(pt) + } else { + return state.stackAllocate(pt) + } +} diff --git a/src/cmd/compile/internal/gc/abiutils_test.go b/src/cmd/compile/internal/gc/abiutils_test.go new file mode 100644 index 0000000000..16bd787bea --- /dev/null +++ b/src/cmd/compile/internal/gc/abiutils_test.go @@ -0,0 +1,270 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gc + +import ( + "bufio" + "cmd/compile/internal/base" + "cmd/compile/internal/types" + "cmd/internal/obj" + "cmd/internal/obj/x86" + "cmd/internal/src" + "os" + "testing" +) + +// AMD64 registers available: +// - integer: RAX, RBX, RCX, RDI, RSI, R8, R9, r10, R11 +// - floating point: X0 - X14 +var configAMD64 = ABIConfig{ + regAmounts: RegAmounts{ + intRegs: 9, + floatRegs: 15, + }, +} + +func TestMain(m *testing.M) { + thearch.LinkArch = &x86.Linkamd64 + thearch.REGSP = x86.REGSP + thearch.MAXWIDTH = 1 << 50 + base.Ctxt = obj.Linknew(thearch.LinkArch) + base.Ctxt.DiagFunc = base.Errorf + base.Ctxt.DiagFlush = base.FlushErrors + base.Ctxt.Bso = bufio.NewWriter(os.Stdout) + Widthptr = thearch.LinkArch.PtrSize + Widthreg = thearch.LinkArch.RegSize + initializeTypesPackage() + os.Exit(m.Run()) +} + +func TestABIUtilsBasic1(t *testing.T) { + + // func(x int32) int32 + i32 := types.Types[types.TINT32] + ft := mkFuncType(nil, []*types.Type{i32}, []*types.Type{i32}) + + // expected results + exp := makeExpectedDump(` + IN 0: R{ I0 } offset: -1 typ: int32 + OUT 0: R{ I0 } offset: -1 typ: int32 + intspill: 1 floatspill: 0 offsetToSpillArea: 0 +`) + + abitest(t, ft, exp) +} + +func TestABIUtilsBasic2(t *testing.T) { + // func(x int32, y float64) (int32, float64, float64) + i8 := types.Types[types.TINT8] + i16 := types.Types[types.TINT16] + i32 := types.Types[types.TINT32] + i64 := types.Types[types.TINT64] + f32 := types.Types[types.TFLOAT32] + f64 := types.Types[types.TFLOAT64] + c64 := types.Types[types.TCOMPLEX64] + c128 := types.Types[types.TCOMPLEX128] + ft := mkFuncType(nil, + []*types.Type{ + i8, i16, i32, i64, + f32, f32, f64, f64, + i8, i16, i32, i64, + f32, f32, f64, f64, + c128, c128, c128, c128, c64, + i8, i16, i32, i64, + i8, i16, i32, i64}, + []*types.Type{i32, f64, f64}) + exp := makeExpectedDump(` + IN 0: R{ I0 } offset: -1 typ: int8 + IN 1: R{ I1 } offset: -1 typ: int16 + IN 2: R{ I2 } offset: -1 typ: int32 + IN 3: R{ I3 } offset: -1 typ: int64 + IN 4: R{ F0 } offset: -1 typ: float32 + IN 5: R{ F1 } offset: -1 typ: float32 + IN 6: R{ F2 } offset: -1 typ: float64 + IN 7: R{ F3 } offset: -1 typ: float64 + IN 8: R{ I4 } offset: -1 typ: int8 + IN 9: R{ I5 } offset: -1 typ: int16 + IN 10: R{ I6 } offset: -1 typ: int32 + IN 11: R{ I7 } offset: -1 typ: int64 + IN 12: R{ F4 } offset: -1 typ: float32 + IN 13: R{ F5 } offset: -1 typ: float32 + IN 14: R{ F6 } offset: -1 typ: float64 + IN 15: R{ F7 } offset: -1 typ: float64 + IN 16: R{ F8 F9 } offset: -1 typ: complex128 + IN 17: R{ F10 F11 } offset: -1 typ: complex128 + IN 18: R{ F12 F13 } offset: -1 typ: complex128 + IN 19: R{ } offset: 0 typ: complex128 + IN 20: R{ F14 } offset: -1 typ: complex64 + IN 21: R{ I8 } offset: -1 typ: int8 + IN 22: R{ } offset: 16 typ: int16 + IN 23: R{ } offset: 20 typ: int32 + IN 24: R{ } offset: 24 typ: int64 + IN 25: R{ } offset: 32 typ: int8 + IN 26: R{ } offset: 34 typ: int16 + IN 27: R{ } offset: 36 typ: int32 + IN 28: R{ } offset: 40 typ: int64 + OUT 0: R{ I0 } offset: -1 typ: int32 + OUT 1: R{ F0 } offset: -1 typ: float64 + OUT 2: R{ F1 } offset: -1 typ: float64 + intspill: 9 floatspill: 15 offsetToSpillArea: 48 +`) + + abitest(t, ft, exp) +} + +func TestABIUtilsArrays(t *testing.T) { + i32 := types.Types[types.TINT32] + ae := types.NewArray(i32, 0) + a1 := types.NewArray(i32, 1) + a2 := types.NewArray(i32, 2) + aa1 := types.NewArray(a1, 1) + ft := mkFuncType(nil, []*types.Type{a1, ae, aa1, a2}, + []*types.Type{a2, a1, ae, aa1}) + + exp := makeExpectedDump(` + IN 0: R{ I0 } offset: -1 typ: [1]int32 + IN 1: R{ } offset: 0 typ: [0]int32 + IN 2: R{ I1 } offset: -1 typ: [1][1]int32 + IN 3: R{ } offset: 0 typ: [2]int32 + OUT 0: R{ } offset: 8 typ: [2]int32 + OUT 1: R{ I0 } offset: -1 typ: [1]int32 + OUT 2: R{ } offset: 16 typ: [0]int32 + OUT 3: R{ I1 } offset: -1 typ: [1][1]int32 + intspill: 2 floatspill: 0 offsetToSpillArea: 16 +`) + + abitest(t, ft, exp) +} + +func TestABIUtilsStruct1(t *testing.T) { + i8 := types.Types[types.TINT8] + i16 := types.Types[types.TINT16] + i32 := types.Types[types.TINT32] + i64 := types.Types[types.TINT64] + s := mkstruct([]*types.Type{i8, i8, mkstruct([]*types.Type{}), i8, i16}) + ft := mkFuncType(nil, []*types.Type{i8, s, i64}, + []*types.Type{s, i8, i32}) + + exp := makeExpectedDump(` + IN 0: R{ I0 } offset: -1 typ: int8 + IN 1: R{ I1 I2 I3 I4 } offset: -1 typ: struct { int8; int8; struct {}; int8; int16 } + IN 2: R{ I5 } offset: -1 typ: int64 + OUT 0: R{ I0 I1 I2 I3 } offset: -1 typ: struct { int8; int8; struct {}; int8; int16 } + OUT 1: R{ I4 } offset: -1 typ: int8 + OUT 2: R{ I5 } offset: -1 typ: int32 + intspill: 6 floatspill: 0 offsetToSpillArea: 0 +`) + + abitest(t, ft, exp) +} + +func TestABIUtilsStruct2(t *testing.T) { + f64 := types.Types[types.TFLOAT64] + i64 := types.Types[types.TINT64] + s := mkstruct([]*types.Type{i64, mkstruct([]*types.Type{})}) + fs := mkstruct([]*types.Type{f64, s, mkstruct([]*types.Type{})}) + ft := mkFuncType(nil, []*types.Type{s, s, fs}, + []*types.Type{fs, fs}) + + exp := makeExpectedDump(` + IN 0: R{ I0 } offset: -1 typ: struct { int64; struct {} } + IN 1: R{ I1 } offset: -1 typ: struct { int64; struct {} } + IN 2: R{ I2 F0 } offset: -1 typ: struct { float64; struct { int64; struct {} }; struct {} } + OUT 0: R{ I0 F0 } offset: -1 typ: struct { float64; struct { int64; struct {} }; struct {} } + OUT 1: R{ I1 F1 } offset: -1 typ: struct { float64; struct { int64; struct {} }; struct {} } + intspill: 3 floatspill: 1 offsetToSpillArea: 0 +`) + + abitest(t, ft, exp) +} + +func TestABIUtilsSliceString(t *testing.T) { + i32 := types.Types[types.TINT32] + sli32 := types.NewSlice(i32) + str := types.New(types.TSTRING) + i8 := types.Types[types.TINT8] + i64 := types.Types[types.TINT64] + ft := mkFuncType(nil, []*types.Type{sli32, i8, sli32, i8, str, i8, i64, sli32}, + []*types.Type{str, i64, str, sli32}) + + exp := makeExpectedDump(` + IN 0: R{ I0 I1 I2 } offset: -1 typ: []int32 + IN 1: R{ I3 } offset: -1 typ: int8 + IN 2: R{ I4 I5 I6 } offset: -1 typ: []int32 + IN 3: R{ I7 } offset: -1 typ: int8 + IN 4: R{ } offset: 0 typ: string + IN 5: R{ I8 } offset: -1 typ: int8 + IN 6: R{ } offset: 16 typ: int64 + IN 7: R{ } offset: 24 typ: []int32 + OUT 0: R{ I0 I1 } offset: -1 typ: string + OUT 1: R{ I2 } offset: -1 typ: int64 + OUT 2: R{ I3 I4 } offset: -1 typ: string + OUT 3: R{ I5 I6 I7 } offset: -1 typ: []int32 + intspill: 9 floatspill: 0 offsetToSpillArea: 48 +`) + + abitest(t, ft, exp) +} + +func TestABIUtilsMethod(t *testing.T) { + i16 := types.Types[types.TINT16] + i64 := types.Types[types.TINT64] + f64 := types.Types[types.TFLOAT64] + + s1 := mkstruct([]*types.Type{i16, i16, i16}) + ps1 := types.NewPtr(s1) + a7 := types.NewArray(ps1, 7) + ft := mkFuncType(s1, []*types.Type{ps1, a7, f64, i16, i16, i16}, + []*types.Type{a7, f64, i64}) + + exp := makeExpectedDump(` + IN 0: R{ I0 I1 I2 } offset: -1 typ: struct { int16; int16; int16 } + IN 1: R{ I3 } offset: -1 typ: *struct { int16; int16; int16 } + IN 2: R{ } offset: 0 typ: [7]*struct { int16; int16; int16 } + IN 3: R{ F0 } offset: -1 typ: float64 + IN 4: R{ I4 } offset: -1 typ: int16 + IN 5: R{ I5 } offset: -1 typ: int16 + IN 6: R{ I6 } offset: -1 typ: int16 + OUT 0: R{ } offset: 56 typ: [7]*struct { int16; int16; int16 } + OUT 1: R{ F0 } offset: -1 typ: float64 + OUT 2: R{ I0 } offset: -1 typ: int64 + intspill: 7 floatspill: 1 offsetToSpillArea: 112 +`) + + abitest(t, ft, exp) +} + +func TestABIUtilsInterfaces(t *testing.T) { + ei := types.Types[types.TINTER] // interface{} + pei := types.NewPtr(ei) // *interface{} + fldt := mkFuncType(types.FakeRecvType(), []*types.Type{}, + []*types.Type{types.UntypedString}) + field := types.NewField(src.NoXPos, nil, fldt) + // interface{ ...() string } + nei := types.NewInterface(types.LocalPkg, []*types.Field{field}) + + i16 := types.Types[types.TINT16] + tb := types.Types[types.TBOOL] + s1 := mkstruct([]*types.Type{i16, i16, tb}) + + ft := mkFuncType(nil, []*types.Type{s1, ei, ei, nei, pei, nei, i16}, + []*types.Type{ei, nei, pei}) + + exp := makeExpectedDump(` + IN 0: R{ I0 I1 I2 } offset: -1 typ: struct { int16; int16; bool } + IN 1: R{ I3 I4 } offset: -1 typ: interface {} + IN 2: R{ I5 I6 } offset: -1 typ: interface {} + IN 3: R{ I7 I8 } offset: -1 typ: interface { () untyped string } + IN 4: R{ } offset: 0 typ: *interface {} + IN 5: R{ } offset: 8 typ: interface { () untyped string } + IN 6: R{ } offset: 24 typ: int16 + OUT 0: R{ I0 I1 } offset: -1 typ: interface {} + OUT 1: R{ I2 I3 } offset: -1 typ: interface { () untyped string } + OUT 2: R{ I4 } offset: -1 typ: *interface {} + intspill: 9 floatspill: 0 offsetToSpillArea: 32 +`) + + abitest(t, ft, exp) +} diff --git a/src/cmd/compile/internal/gc/abiutilsaux_test.go b/src/cmd/compile/internal/gc/abiutilsaux_test.go new file mode 100644 index 0000000000..d90d1d45a0 --- /dev/null +++ b/src/cmd/compile/internal/gc/abiutilsaux_test.go @@ -0,0 +1,157 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gc + +// This file contains utility routines and harness infrastructure used +// by the ABI tests in "abiutils_test.go". + +import ( + "cmd/compile/internal/ir" + "cmd/compile/internal/types" + "cmd/internal/src" + "fmt" + "strings" + "testing" + "text/scanner" +) + +func mkParamResultField(t *types.Type, s *types.Sym, which ir.Class) *types.Field { + field := types.NewField(src.NoXPos, s, t) + n := NewName(s) + n.SetClass(which) + field.Nname = n + n.SetType(t) + return field +} + +// mkstruct is a helper routine to create a struct type with fields +// of the types specified in 'fieldtypes'. +func mkstruct(fieldtypes []*types.Type) *types.Type { + fields := make([]*types.Field, len(fieldtypes)) + for k, t := range fieldtypes { + if t == nil { + panic("bad -- field has no type") + } + f := types.NewField(src.NoXPos, nil, t) + fields[k] = f + } + s := types.NewStruct(types.LocalPkg, fields) + return s +} + +func mkFuncType(rcvr *types.Type, ins []*types.Type, outs []*types.Type) *types.Type { + q := lookup("?") + inf := []*types.Field{} + for _, it := range ins { + inf = append(inf, mkParamResultField(it, q, ir.PPARAM)) + } + outf := []*types.Field{} + for _, ot := range outs { + outf = append(outf, mkParamResultField(ot, q, ir.PPARAMOUT)) + } + var rf *types.Field + if rcvr != nil { + rf = mkParamResultField(rcvr, q, ir.PPARAM) + } + return types.NewSignature(types.LocalPkg, rf, inf, outf) +} + +type expectedDump struct { + dump string + file string + line int +} + +func tokenize(src string) []string { + var s scanner.Scanner + s.Init(strings.NewReader(src)) + res := []string{} + for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() { + res = append(res, s.TokenText()) + } + return res +} + +func verifyParamResultOffset(t *testing.T, f *types.Field, r ABIParamAssignment, which string, idx int) int { + n := ir.AsNode(f.Nname) + if n == nil { + panic("not expected") + } + if n.Offset() != int64(r.Offset) { + t.Errorf("%s %d: got offset %d wanted %d t=%v", + which, idx, r.Offset, n.Offset(), f.Type) + return 1 + } + return 0 +} + +func makeExpectedDump(e string) expectedDump { + return expectedDump{dump: e} +} + +func difftokens(atoks []string, etoks []string) string { + if len(atoks) != len(etoks) { + return fmt.Sprintf("expected %d tokens got %d", + len(etoks), len(atoks)) + } + for i := 0; i < len(etoks); i++ { + if etoks[i] == atoks[i] { + continue + } + + return fmt.Sprintf("diff at token %d: expected %q got %q", + i, etoks[i], atoks[i]) + } + return "" +} + +func abitest(t *testing.T, ft *types.Type, exp expectedDump) { + + dowidth(ft) + + // Analyze with full set of registers. + regRes := ABIAnalyze(ft, configAMD64) + regResString := strings.TrimSpace(regRes.String()) + + // Check results. + reason := difftokens(tokenize(regResString), tokenize(exp.dump)) + if reason != "" { + t.Errorf("\nexpected:\n%s\ngot:\n%s\nreason: %s", + strings.TrimSpace(exp.dump), regResString, reason) + } + + // Analyze again with empty register set. + empty := ABIConfig{} + emptyRes := ABIAnalyze(ft, empty) + emptyResString := emptyRes.String() + + // Walk the results and make sure the offsets assigned match + // up with those assiged by dowidth. This checks to make sure that + // when we have no available registers the ABI assignment degenerates + // back to the original ABI0. + + // receiver + failed := 0 + rfsl := ft.Recvs().Fields().Slice() + poff := 0 + if len(rfsl) != 0 { + failed |= verifyParamResultOffset(t, rfsl[0], emptyRes.inparams[0], "receiver", 0) + poff = 1 + } + // params + pfsl := ft.Params().Fields().Slice() + for k, f := range pfsl { + verifyParamResultOffset(t, f, emptyRes.inparams[k+poff], "param", k) + } + // results + ofsl := ft.Results().Fields().Slice() + for k, f := range ofsl { + failed |= verifyParamResultOffset(t, f, emptyRes.outparams[k], "result", k) + } + + if failed != 0 { + t.Logf("emptyres:\n%s\n", emptyResString) + } +}