From 46afa893ebf85e23dd820a11e6007a9adb503419 Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld"
TODO: complete this section
+ The pure Go resolver will now use EDNS(0) to include a suggested
+ maximum reply packet length, permitting reply packets to contain
+ up to 1232 bytes (the previous maximum was 512).
+ In the unlikely event that this causes problems with a local DNS
+ resolver, setting the environment variable
+ Foo \n\n Bar>\n"
d := NewDecoder(strings.NewReader(testInput))
@@ -1060,3 +1073,155 @@ func TestRoundTrip(t *testing.T) {
t.Run(name, func(t *testing.T) { testRoundTrip(t, input) })
}
}
+
+func TestParseErrors(t *testing.T) {
+ withDefaultHeader := func(s string) string {
+ return `` + s
+ }
+ tests := []struct {
+ src string
+ err string
+ }{
+ {withDefaultHeader(``), `unexpected end element `},
+ {withDefaultHeader(`
-A new, initialized slice value for a given element type
-In a union, a term cannot be a type parameter, and the type sets of all
+In a union, a term cannot be a type parameter, and the type sets of all
non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty).
Given a type parameter
Implementation restriction:
-A union with more than one term cannot contain the
+A union (with more than one term) cannot contain the
predeclared identifier
-A value
From 7d7b9bbc7a37d3b83936a8caea08e0be7240a125 Mon Sep 17 00:00:00 2001
From: Lynn Boger GODEBUG=netdns=cgo to use the cgo-based resolver
+ should work.
+ Please report any such problems on the
+ issue tracker.
+
+
+
+
+
+
+
+
abc
`
+
+func BenchmarkHTMLAutoClose(b *testing.B) {
+ b.RunParallel(func(p *testing.PB) {
+ for p.Next() {
+ d := NewDecoder(strings.NewReader(testInputHTMLAutoClose))
+ d.Strict = false
+ d.AutoClose = HTMLAutoClose
+ d.Entity = HTMLEntity
+ for {
+ _, err := d.Token()
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ b.Fatalf("unexpected error: %v", err)
+ }
+ }
+ }
+ })
+}
+
+func TestHTMLAutoClose(t *testing.T) {
+ wantTokens := []Token{
+ ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
+ CharData("\n"),
+ StartElement{Name{"", "br"}, []Attr{}},
+ EndElement{Name{"", "br"}},
+ CharData("\n"),
+ StartElement{Name{"", "br"}, []Attr{}},
+ EndElement{Name{"", "br"}},
+ StartElement{Name{"", "br"}, []Attr{}},
+ EndElement{Name{"", "br"}},
+ CharData("\n"),
+ StartElement{Name{"", "br"}, []Attr{}},
+ EndElement{Name{"", "br"}},
+ StartElement{Name{"", "br"}, []Attr{}},
+ EndElement{Name{"", "br"}},
+ CharData("\n"),
+ StartElement{Name{"", "br"}, []Attr{}},
+ EndElement{Name{"", "br"}},
+ CharData("\n"),
+ StartElement{Name{"", "BR"}, []Attr{}},
+ EndElement{Name{"", "BR"}},
+ CharData("\n"),
+ StartElement{Name{"", "BR"}, []Attr{}},
+ EndElement{Name{"", "BR"}},
+ StartElement{Name{"", "BR"}, []Attr{}},
+ EndElement{Name{"", "BR"}},
+ CharData("\n"),
+ StartElement{Name{"", "Br"}, []Attr{}},
+ EndElement{Name{"", "Br"}},
+ CharData("\n"),
+ StartElement{Name{"", "BR"}, []Attr{}},
+ EndElement{Name{"", "BR"}},
+ StartElement{Name{"", "span"}, []Attr{{Name: Name{"", "id"}, Value: "test"}}},
+ CharData("abc"),
+ EndElement{Name{"", "span"}},
+ StartElement{Name{"", "br"}, []Attr{}},
+ EndElement{Name{"", "br"}},
+ StartElement{Name{"", "br"}, []Attr{}},
+ EndElement{Name{"", "br"}},
+ }
+
+ d := NewDecoder(strings.NewReader(testInputHTMLAutoClose))
+ d.Strict = false
+ d.AutoClose = HTMLAutoClose
+ d.Entity = HTMLEntity
+ var haveTokens []Token
+ for {
+ tok, err := d.Token()
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ t.Fatalf("unexpected error: %v", err)
+ }
+ haveTokens = append(haveTokens, CopyToken(tok))
+ }
+ if len(haveTokens) != len(wantTokens) {
+ t.Errorf("tokens count mismatch: have %d, want %d", len(haveTokens), len(wantTokens))
+ }
+ for i, want := range wantTokens {
+ if i >= len(haveTokens) {
+ t.Errorf("token[%d] expected %#v, have no token", i, want)
+ } else {
+ have := haveTokens[i]
+ if !reflect.DeepEqual(have, want) {
+ t.Errorf("token[%d] mismatch:\nhave: %#v\nwant: %#v", i, have, want)
+ }
+ }
+ }
+}
From bf97c99b62fe7d6652cc8c807dbc91998d488a01 Mon Sep 17 00:00:00 2001
From: uji cap(a).
T is
+A new, initialized slice value for a given element type T may be
made using the built-in function
make,
which takes a slice type
@@ -1422,7 +1422,7 @@ interface {
~int
}
-// An interface representing all types with underlying type int which implement the String method.
+// An interface representing all types with underlying type int that implement the String method.
interface {
~int
String() string
@@ -1455,32 +1455,32 @@ Union elements denote unions of type sets:
-// The Floats interface represents all floating-point types
+// The Float interface represents all floating-point types
// (including any named types whose underlying types are
// either float32 or float64).
-type Floats interface {
+type Float interface {
~float32 | ~float64
}
P:
interface {
- P // illegal: the term P is a type parameter
- int | P // illegal: the term P is a type parameter
- ~int | MyInt // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
- float32 | Floats // overlapping type sets but Floats is an interface
+ P // illegal: P is a type parameter
+ int | P // illegal: P is a type parameter
+ ~int | MyInt // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
+ float32 | Float // overlapping type sets but Float is an interface
}
comparable
or interfaces that specify methods, or embed comparable or interfaces
that specify methods.
@@ -1494,12 +1494,12 @@ non-interface types.
-var x Floats // illegal: Floats is not a basic interface
+var x Float // illegal: Float is not a basic interface
-var x interface{} = Floats(nil) // illegal
+var x interface{} = Float(nil) // illegal
type Floatish struct {
- f Floats // illegal
+ f Float // illegal
}
@@ -1545,7 +1545,7 @@ A type T implements an interface I if
x of type T implements an interface if T
+A value of type T implements an interface if T
implements the interface.
T has an underlying type: If T
is one of the predeclared boolean, numeric, or string types, or a type literal,
the corresponding underlying type is T itself.
Otherwise, T's underlying type is the underlying type of the
-type to which T refers in its type
-declaration. The underlying type of a type parameter is the
-underlying type of its type constraint, which
-is always an interface.
+type to which T refers in its declaration.
+For a type parameter that is the underlying type of its
+type constraint, which is always an interface.
@@ -1755,7 +1754,7 @@ direction.-All other interfaces don't have a core type. +No other interfaces have a core type.
@@ -1795,7 +1794,7 @@ interface{ ~[]*data; String() string } // []*data
-Examples of interfaces whithout core types: +Examples of interfaces without core types:
@@ -1973,21 +1972,21 @@ defined type while the latter is a type literalAssignability
-A value
xis assignable to a variable of typeT+A valuexof typeVis assignable to a variable of typeT("xis assignable toT") if one of the following conditions applies:
x's type is identical to T.
+V and T are identical.
x's type V and T have identical
+V and T have identical
underlying types and at least one of V
or T is not a named type.
x's type V and T are channel types with
+V and T are channel types with
identical element types, V is a bidirectional channel,
and at least one of V or T is not a named type.
-The given type cannot be a type parameter in a type definition. +In a type definition the given type cannot be a type parameter.
@@ -2604,8 +2598,8 @@ func f[T any]() {
-A generic type may also have methods associated with it. In this case, -the method receivers must declare the same number of type parameters as +A generic type may also have methods associated with it. +In this case, the method receivers must declare the same number of type parameters as present in the generic type definition.
@@ -2899,12 +2893,12 @@ func IndexRune(s string, r rune) int {If the function declaration specifies type parameters, the function name denotes a generic function. -Generic functions must be instantiated when they -are used. +A generic function must be instantiated before it can be +called or used as a value.
-func min[T constraints.Ordered](x, y T) T {
+func min[T ~int|~float64](x, y T) T {
if x < y {
return x
}
@@ -2963,7 +2957,7 @@ the non-blank method and field names must be distinct.
-Given defined type Point, the declarations
+Given defined type Point the declarations
@@ -3758,7 +3752,7 @@ The following rules apply:
-If a is not a map:
+If a is neither a map nor a type parameter:
x must be an untyped constant or its
@@ -4298,7 +4292,7 @@ inferrable from the ordinary (non-type) function arguments.
-func min[T constraints.Ordered](x, y T) T { … }
+func min[T ~int|~float64](x, y T) T { … }
f := min // illegal: min must be instantiated when used without being called
minInt := min[int] // minInt has type func(x, y int) int
@@ -4550,7 +4544,7 @@ Example:
-func min[T constraints.Ordered](x, y T) T
+func min[T ~int|~float64](x, y T) T
var x int
min(x, 2.0) // T is int, inferred from typed argument x; 2.0 is assignable to int
From 079a027d27a9eed18c99c0c6a6e2fc70f9dd07b7 Mon Sep 17 00:00:00 2001
From: Jorropo
Date: Mon, 7 Mar 2022 12:56:01 +0000
Subject: [PATCH 030/276] io: add WriterTo to MultiReader
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch allows to zerocopy using MultiReader.
This is done by MultiReader implementing WriterTo.
Each sub reader is copied using usual io copy helper and thus use
WriterTo or ReadFrom with reflection.
There is a special case for when a subreader is a MultiReader.
Instead of using copyBuffer which would call multiReader.WriteTo,
multiReader.writeToWithBuffer is used instead, the difference
is that the temporary copy buffer is passed along, saving
allocations for nested MultiReaders.
The workflow looks like this:
- multiReader.WriteTo (allocates 32k buffer)
- multiReader.writeToWithBuffer
- for each subReader:
- is instance of multiReader ?
- yes, call multiReader.writeToWithBuffer
- no, call copyBuffer(writer, currentReader, buffer)
- does currentReader implements WriterTo ?
- yes, use use currentReader.WriteTo
- no, does writer implement ReadFrom ?
- yes, use writer.ReadFrom
- no, copy using Read / Write with buffer
This can be improved by lazy allocating the 32k buffer.
For example a MultiReader of such types:
MultiReader(
bytes.Reader, // WriterTo-able
bytes.Reader, // WriterTo-able
bytes.Reader, // WriterTo-able
)
Doesn't need any allocation, all copy can be done using bytes.Reader's
internal data slice. However currently we still allocate a 32k buffer
for nothing.
This optimisation has been omitted for a future patch because of high
complexity costs for a non obvious performance cost (it needs a benchmark).
This patch at least is on par with the previous MultiReader.Read
workflow allocation wise.
Fixes #50842
Change-Id: Ib070c8f36337d9dd86090df8a703c5df97a773ae
GitHub-Last-Rev: 8ebe60ceacec6bd52b63d9bdc05cd5b4ada57a6e
GitHub-Pull-Request: golang/go#51502
Reviewed-on: https://go-review.googlesource.com/c/go/+/390215
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gopher Robot
Reviewed-by: Ian Lance Taylor
Reviewed-by: Daniel Martí
Trust: Daniel Martí
---
src/io/multi.go | 25 +++++++++++++++++++++++++
src/io/multi_test.go | 25 +++++++++++++++++++++++++
2 files changed, 50 insertions(+)
diff --git a/src/io/multi.go b/src/io/multi.go
index 24ee71e4ca..909b7e4523 100644
--- a/src/io/multi.go
+++ b/src/io/multi.go
@@ -41,6 +41,31 @@ func (mr *multiReader) Read(p []byte) (n int, err error) {
return 0, EOF
}
+func (mr *multiReader) WriteTo(w Writer) (sum int64, err error) {
+ return mr.writeToWithBuffer(w, make([]byte, 1024 * 32))
+}
+
+func (mr *multiReader) writeToWithBuffer(w Writer, buf []byte) (sum int64, err error) {
+ for i, r := range mr.readers {
+ var n int64
+ if subMr, ok := r.(*multiReader); ok { // reuse buffer with nested multiReaders
+ n, err = subMr.writeToWithBuffer(w, buf)
+ } else {
+ n, err = copyBuffer(w, r, buf)
+ }
+ sum += n
+ if err != nil {
+ mr.readers = mr.readers[i:] // permit resume / retry after error
+ return sum, err
+ }
+ mr.readers[i] = nil // permit early GC
+ }
+ mr.readers = nil
+ return sum, nil
+}
+
+var _ WriterTo = (*multiReader)(nil)
+
// MultiReader returns a Reader that's the logical concatenation of
// the provided input readers. They're read sequentially. Once all
// inputs have returned EOF, Read will return EOF. If any of the readers
diff --git a/src/io/multi_test.go b/src/io/multi_test.go
index e877e54571..679312c23b 100644
--- a/src/io/multi_test.go
+++ b/src/io/multi_test.go
@@ -63,6 +63,31 @@ func TestMultiReader(t *testing.T) {
})
}
+func TestMultiReaderAsWriterTo(t *testing.T) {
+ mr := MultiReader(
+ strings.NewReader("foo "),
+ MultiReader( // Tickle the buffer reusing codepath
+ strings.NewReader(""),
+ strings.NewReader("bar"),
+ ),
+ )
+ mrAsWriterTo, ok := mr.(WriterTo)
+ if !ok {
+ t.Fatalf("expected cast to WriterTo to succeed")
+ }
+ sink := &strings.Builder{}
+ n, err := mrAsWriterTo.WriteTo(sink)
+ if err != nil {
+ t.Fatalf("expected no error; got %v", err)
+ }
+ if n != 7 {
+ t.Errorf("expected read 7 bytes; got %d", n)
+ }
+ if result := sink.String(); result != "foo bar" {
+ t.Errorf(`expected "foo bar"; got %q`, result)
+ }
+}
+
func TestMultiWriter(t *testing.T) {
sink := new(bytes.Buffer)
// Hide bytes.Buffer's WriteString method:
From d9d55724bd8ff10d8de5c13fd77122a37ac73719 Mon Sep 17 00:00:00 2001
From: "Paul E. Murphy"
Date: Thu, 3 Mar 2022 15:41:57 -0600
Subject: [PATCH 031/276] internal/cpu: set PPC64.IsPOWER8
This should always be true, but use the HWCAP2 bit anyways.
Change-Id: Ib164cf05b4c9f0c509f41b7eb339ef32fb63e384
Reviewed-on: https://go-review.googlesource.com/c/go/+/389894
Trust: Paul Murphy
Run-TryBot: Paul Murphy
TryBot-Result: Gopher Robot
Reviewed-by: Cherry Mui
---
src/internal/cpu/cpu_ppc64x_linux.go | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/internal/cpu/cpu_ppc64x_linux.go b/src/internal/cpu/cpu_ppc64x_linux.go
index 7999656f01..0fe8667843 100644
--- a/src/internal/cpu/cpu_ppc64x_linux.go
+++ b/src/internal/cpu/cpu_ppc64x_linux.go
@@ -15,6 +15,7 @@ var HWCap2 uint
// HWCAP bits. These are exposed by Linux.
const (
// ISA Level
+ hwcap2_ARCH_2_07 = 0x80000000
hwcap2_ARCH_3_00 = 0x00800000
// CPU features
@@ -23,6 +24,7 @@ const (
)
func osinit() {
+ PPC64.IsPOWER8 = isSet(HWCap2, hwcap2_ARCH_2_07)
PPC64.IsPOWER9 = isSet(HWCap2, hwcap2_ARCH_3_00)
PPC64.HasDARN = isSet(HWCap2, hwcap2_DARN)
PPC64.HasSCV = isSet(HWCap2, hwcap2_SCV)
From 0043c1efbb53e72cbd1b41c32812ca3c78d8e169 Mon Sep 17 00:00:00 2001
From: Dmitri Shuralyov
Date: Tue, 8 Mar 2022 00:08:49 +0000
Subject: [PATCH 032/276] fmt: use tabs for indentation
Replace 24 spaces added in CL 389434 with 3 tabs,
so the new line is indented like other lines around it.
Updates #51419.
Change-Id: Ic3e50023a01f233c52dda53c36de2c461222d95c
Reviewed-on: https://go-review.googlesource.com/c/go/+/390674
Trust: Dmitri Shuralyov
Run-TryBot: Dmitri Shuralyov
Auto-Submit: Dmitri Shuralyov
TryBot-Result: Gopher Robot
Reviewed-by: Adam Shannon
Reviewed-by: Ian Lance Taylor
---
src/fmt/doc.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fmt/doc.go b/src/fmt/doc.go
index 4a09555734..a7bd02b627 100644
--- a/src/fmt/doc.go
+++ b/src/fmt/doc.go
@@ -125,7 +125,7 @@
put spaces between bytes printing strings or slices in hex (% x, % X)
0 pad with leading zeros rather than spaces;
for numbers, this moves the padding after the sign;
- ignored for strings, byte slices and byte arrays
+ ignored for strings, byte slices and byte arrays
Flags are ignored by verbs that do not expect them.
For example there is no alternate decimal format, so %#d and %d
From 31be6285a879af94c7283e6599e3f9b64266bc1a Mon Sep 17 00:00:00 2001
From: eric fang
Date: Tue, 18 Jan 2022 08:49:56 +0000
Subject: [PATCH 033/276] cmd/internal/obj/arm64: optimize stacksplit prologue
for small stack
When framesize <= objabi.StackSmall, 128B, the stacksplit prologue is:
MOVD 16(g), R16
MOVD SP, R17
CMP R16, R17
BLS morestack_label
The second instruction is not necessary, we can compare R16 with SP
directly, so the sequence becomes:
MOVD 16(g), R16
CMP R16, SP
BLS morestack_label
This CL removes this instruction.
Change-Id: I0567ac52e9be124880957271951e1186da203612
Reviewed-on: https://go-review.googlesource.com/c/go/+/379076
Trust: Eric Fang
Run-TryBot: Eric Fang
TryBot-Result: Gopher Robot
Reviewed-by: Eric Fang
Reviewed-by: Cherry Mui
---
src/cmd/internal/obj/arm64/obj7.go | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go
index e9eb786cb2..2bbc7e37b0 100644
--- a/src/cmd/internal/obj/arm64/obj7.go
+++ b/src/cmd/internal/obj/arm64/obj7.go
@@ -165,21 +165,13 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
q := (*obj.Prog)(nil)
if framesize <= objabi.StackSmall {
// small stack: SP < stackguard
- // MOV SP, RT2
- // CMP stackguard, RT2
- p = obj.Appendp(p, c.newprog)
-
- p.As = AMOVD
- p.From.Type = obj.TYPE_REG
- p.From.Reg = REGSP
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REGRT2
+ // CMP stackguard, SP
p = obj.Appendp(p, c.newprog)
p.As = ACMP
p.From.Type = obj.TYPE_REG
p.From.Reg = REGRT1
- p.Reg = REGRT2
+ p.Reg = REGSP
} else if framesize <= objabi.StackBig {
// large stack: SP-framesize < stackguard-StackSmall
// SUB $(framesize-StackSmall), SP, RT2
From 6e63be7b69aab25ac66029e7dfec47303d3b7505 Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Mon, 7 Mar 2022 14:48:28 -0800
Subject: [PATCH 034/276] spec: document that type inference doesn't apply to
generic types
Type inference for types was always a "nice to have" feature.
Given the under-appreciated complexity of making it work in all
cases, and the fact that we don't have a good understanding of
how it might affect readability of generic code, require explicit
type arguments for generic types.
This matches the current implementation.
Change-Id: Ie7ff6293d3fbea92ddc54c46285a4cabece7fe01
Reviewed-on: https://go-review.googlesource.com/c/go/+/390577
Trust: Robert Griesemer
Run-TryBot: Robert Griesemer
TryBot-Result: Gopher Robot
Reviewed-by: Ian Lance Taylor
Reviewed-by: Robert Findley
---
doc/go_spec.html | 61 +++++++++++++++++++++++-------------------------
1 file changed, 29 insertions(+), 32 deletions(-)
diff --git a/doc/go_spec.html b/doc/go_spec.html
index e8061f94b9..6278b8252d 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -11,11 +11,6 @@ For the pre-Go1.18 specification without generics support see
The Go Programming Language Specification.
-
-
-[For reviewers: Sections where we know of missing prose are marked like this. The markers will be removed before the release.]
-
-
Introduction
@@ -4230,7 +4225,7 @@ with the same underlying array.
A generic function or type is instantiated by substituting type arguments
for the type parameters.
-Instantiation proceeds in two phases:
+Instantiation proceeds in two steps:
@@ -4262,31 +4257,12 @@ type parameter list type arguments after substitution
-Type arguments may be provided explicitly, or they may be partially or completely
-inferred.
-A partially provided type argument list cannot be empty; there must be at least the
-first argument.
-
-
-
-type T[P1 ~int, P2 ~[]P1] struct{ … }
-
-T[] // illegal: at least the first type argument must be present, even if it could be inferred
-T[int] // argument for P1 explicitly provided, argument for P2 inferred
-T[int, []int] // both arguments explicitly provided
-
-
-
-A partial type argument list specifies a prefix of the full list of type arguments, leaving
-the remaining arguments to be inferred. Loosely speaking, type arguments may be omitted from
-"right to left".
-
-
-
-Generic types, and generic functions that are not called,
-require a type argument list for instantiation; if the list is partial, all
+For a generic function, type arguments may be provided explicitly, or they
+may be partially or completely inferred.
+A generic function that is is not called requires a
+type argument list for instantiation; if the list is partial, all
remaining type arguments must be inferrable.
-Calls to generic functions may provide a (possibly partial) type
+A generic function that is called may provide a (possibly partial) type
argument list, or may omit it entirely if the omitted type arguments are
inferrable from the ordinary (non-type) function arguments.
@@ -4294,17 +4270,38 @@ inferrable from the ordinary (non-type) function arguments.
func min[T ~int|~float64](x, y T) T { … }
-f := min // illegal: min must be instantiated when used without being called
+f := min // illegal: min must be instantiated with type arguments when used without being called
minInt := min[int] // minInt has type func(x, y int) int
a := minInt(2, 3) // a has value 2 of type int
b := min[float64](2.0, 3) // b has value 2.0 of type float64
c := min(b, -1) // c has value -1.0 of type float64
+
+A partial type argument list cannot be empty; at least the first argument must be present.
+The list is a prefix of the full list of type arguments, leaving the remaining arguments
+to be inferred. Loosely speaking, type arguments may be omitted from "right to left".
+
+
+
+func apply[S ~[]E, E any](s S, f(E) E) S { … }
+
+f0 := apply[] // illegal: type argument list cannot be empty
+f1 := apply[[]int] // type argument for S explicitly provided, type argument for E inferred
+f2 := apply[[]string, string] // both type arguments explicitly provided
+
+var bytes []byte
+r := apply(bytes, func(byte) byte { … }) // both type arguments inferred from the function arguments
+
+
+
+For a generic type, all type arguments must always be provided explicitly.
+
+
Type inference
-Missing type arguments may be inferred by a series of steps, described below.
+Missing function type arguments may be inferred by a series of steps, described below.
Each step attempts to use known information to infer additional type arguments.
Type inference stops as soon as all type arguments are known.
After type inference is complete, it is still necessary to substitute all type arguments
From 0b76afc75ca687fcd9a1a8e0b19670fb8f37fecb Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Tue, 22 Feb 2022 17:07:49 -0500
Subject: [PATCH 035/276] crypto/rand: simplify Prime to use only rejection
sampling
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The old code picks a random number n and then tests n, n+2, n+4, up to
n+(1<<20) for primality before giving up and picking a new n.
(The chance of finishing the loop and picking a new n is infinitesimally
small.) This approach, called “incremental search” in the Handbook of
Applied Cryptography, section 4.51, demands fewer bits from the random
source and amortizes some of the cost of the small-prime division
checks across the incremented values.
This commit deletes the n+2, n+4, ... checks, instead picking a series
of random n and stopping at the first one that is probably prime.
This approach is called “rejection sampling.”
Reasons to make this change, in decreasing order of importance:
1. Rejection sampling is simpler, and simpler is more clearly correct.
2. The main benefit of incremental search was performance, and that is
less important than before. Incremental search required fewer random
bits and was able to amortize the checks for small primes across the
entire sequence. However, both random bit generation and primality
checks have gotten faster much quicker than typical primes have
gotten longer, so the benefits are not as important today.
Also, random prime generation is not typically on the critical path.
Negating any lingering concerns about performance, rejection sampling
no slower in practice than the incremental search, perhaps because
the incremental search was using a somewhat inefficient test to
eliminate multiples of small primes; ProbablyPrime does it better.
name old time/op new time/op delta
Prime/MathRand 69.3ms ±23% 68.0ms ±37% ~ (p=0.531 n=20+19)
Prime/CryptoRand 69.2ms ±27% 63.8ms ±36% ~ (p=0.076 n=20+20)
(Here, Prime/MathRand is the current Prime benchmark,
and Prime/CryptoRand is an adaptation to use crypto/rand.Reader
instead of math/rand's non-cryptographic randomness source,
just in case the quality of the bits affects the outcome.
If anything, rejection sampling is even better with cryptographically
random bits, but really the two are statistically indistinguishable
over 20 runs.)
3. Incremental search has a clear bias when generating small primes:
a prime is more likely to be returned the larger the gap between
it and the next smaller prime. Although the bias is negligible in
practice for cryptographically large primes, people can measure the
bias for smaller prime sizes, and we have received such reports
extrapolating the bias to larger sizes and claiming a security bug
(which, to be clear, does not exist).
However, given that rejection sampling is simpler, more clearly
correct and at least no slower than incremental search, the bias
is indefensible.
4. Incremental search has a timing leak. If you can tell the incremental
search ran 10 times, then you know that p is such that there are no
primes in the range [p-20, p). To be clear, there are other timing
leaks in our current primality testing, so there's no definitive
benefit to eliminating this one, but there's also no reason to keep
it around.
(See https://bugs.chromium.org/p/boringssl/issues/detail?id=238 for
all the work that would be needed to make RSA key generation
constant-time, which is definitely not something we have planned for
Go crypto.)
5. Rejection sampling moves from matching OpenSSL to matching BoringSSL.
As a general rule BoringSSL is the better role model.
(Everyone started out using incremental search; BoringSSL switched
to rejection sampling in 2019, as part of the constant-time work
linked above.)
Change-Id: Ie67e572a967c12d8728c752045c7e38f21804f8e
Reviewed-on: https://go-review.googlesource.com/c/go/+/387554
Trust: Russ Cox
Run-TryBot: Russ Cox
Reviewed-by: Peter Weinberger
Reviewed-by: Filippo Valsorda
TryBot-Result: Gopher Robot
Auto-Submit: Russ Cox
---
src/crypto/rand/util.go | 61 +++++------------------------------------
1 file changed, 7 insertions(+), 54 deletions(-)
diff --git a/src/crypto/rand/util.go b/src/crypto/rand/util.go
index 4dd1711203..0f143a3830 100644
--- a/src/crypto/rand/util.go
+++ b/src/crypto/rand/util.go
@@ -10,28 +10,11 @@ import (
"math/big"
)
-// smallPrimes is a list of small, prime numbers that allows us to rapidly
-// exclude some fraction of composite candidates when searching for a random
-// prime. This list is truncated at the point where smallPrimesProduct exceeds
-// a uint64. It does not include two because we ensure that the candidates are
-// odd by construction.
-var smallPrimes = []uint8{
- 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
-}
-
-// smallPrimesProduct is the product of the values in smallPrimes and allows us
-// to reduce a candidate prime by this number and then determine whether it's
-// coprime to all the elements of smallPrimes without further big.Int
-// operations.
-var smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365)
-
-// Prime returns a number, p, of the given size, such that p is prime
-// with high probability.
+// Prime returns a number of the given bit length that is prime with high probability.
// Prime will return error for any error returned by rand.Read or if bits < 2.
-func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
+func Prime(rand io.Reader, bits int) (*big.Int, error) {
if bits < 2 {
- err = errors.New("crypto/rand: prime size must be at least 2-bit")
- return
+ return nil, errors.New("crypto/rand: prime size must be at least 2-bit")
}
b := uint(bits % 8)
@@ -40,13 +23,10 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
}
bytes := make([]byte, (bits+7)/8)
- p = new(big.Int)
-
- bigMod := new(big.Int)
+ p := new(big.Int)
for {
- _, err = io.ReadFull(rand, bytes)
- if err != nil {
+ if _, err := io.ReadFull(rand, bytes); err != nil {
return nil, err
}
@@ -69,35 +49,8 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
bytes[len(bytes)-1] |= 1
p.SetBytes(bytes)
-
- // Calculate the value mod the product of smallPrimes. If it's
- // a multiple of any of these primes we add two until it isn't.
- // The probability of overflowing is minimal and can be ignored
- // because we still perform Miller-Rabin tests on the result.
- bigMod.Mod(p, smallPrimesProduct)
- mod := bigMod.Uint64()
-
- NextDelta:
- for delta := uint64(0); delta < 1<<20; delta += 2 {
- m := mod + delta
- for _, prime := range smallPrimes {
- if m%uint64(prime) == 0 && (bits > 6 || m != uint64(prime)) {
- continue NextDelta
- }
- }
-
- if delta > 0 {
- bigMod.SetUint64(delta)
- p.Add(p, bigMod)
- }
- break
- }
-
- // There is a tiny possibility that, by adding delta, we caused
- // the number to be one bit too long. Thus we check BitLen
- // here.
- if p.ProbablyPrime(20) && p.BitLen() == bits {
- return
+ if p.ProbablyPrime(20) {
+ return p, nil
}
}
}
From 7fd9564fcd3715a2aaf2bf4df1096f71ff40ef15 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Tue, 22 Feb 2022 14:43:41 -0500
Subject: [PATCH 036/276] cmd/compile: allow fieldtrack of unexported fields
The fieldtrack support is experimental and used mainly inside Google,
where we have included this change for years. No reason not to make
it in the public copy.
Change-Id: I5233e4e775ccce60a17098c007aed8c82a0425d7
Reviewed-on: https://go-review.googlesource.com/c/go/+/387355
Trust: Russ Cox
Run-TryBot: Russ Cox
TryBot-Result: Gopher Robot
Reviewed-by: Ian Lance Taylor
---
src/cmd/compile/internal/walk/expr.go | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go
index e5bf6cf0b5..43201dbd3d 100644
--- a/src/cmd/compile/internal/walk/expr.go
+++ b/src/cmd/compile/internal/walk/expr.go
@@ -1012,9 +1012,6 @@ func usefield(n *ir.SelectorExpr) {
if outer.Sym() == nil {
base.Errorf("tracked field must be in named struct type")
}
- if !types.IsExported(field.Sym.Name) {
- base.Errorf("tracked field must be exported (upper case)")
- }
sym := reflectdata.TrackSym(outer, field)
if ir.CurFunc.FieldTrack == nil {
From 3c42ebf3e2dccbe228b78ca2e157010a7d3c5b9d Mon Sep 17 00:00:00 2001
From: Joel Sing
Date: Fri, 21 Jan 2022 18:34:03 +1100
Subject: [PATCH 037/276] internal/bytealg: optimise memequal on riscv64
Implement memequal using loops that process 32 bytes, 16 bytes, 4 bytes
or 1 byte depending on size and alignment. For comparisons that are less
than 32 bytes the overhead of checking and adjusting alignment usually
exceeds the overhead of reading and processing 4 bytes at a time.
Updates #50615
name old time/op new time/op delta
Equal/0-4 38.3ns _ 0% 43.1ns _ 0% +12.54% (p=0.000 n=3+3)
Equal/1-4 77.7ns _ 0% 90.3ns _ 0% +16.27% (p=0.000 n=3+3)
Equal/6-4 116ns _ 0% 121ns _ 0% +3.85% (p=0.002 n=3+3)
Equal/9-4 137ns _ 0% 126ns _ 0% -7.98% (p=0.000 n=3+3)
Equal/15-4 179ns _ 0% 170ns _ 0% -4.77% (p=0.001 n=3+3)
Equal/16-4 186ns _ 0% 159ns _ 0% -14.65% (p=0.000 n=3+3)
Equal/20-4 215ns _ 0% 178ns _ 0% -17.18% (p=0.000 n=3+3)
Equal/32-4 298ns _ 0% 101ns _ 0% -66.22% (p=0.000 n=3+3)
Equal/4K-4 28.9_s _ 0% 2.2_s _ 0% -92.56% (p=0.000 n=3+3)
Equal/4M-4 29.6ms _ 0% 2.2ms _ 0% -92.72% (p=0.000 n=3+3)
Equal/64M-4 758ms _75% 35ms _ 0% ~ (p=0.127 n=3+3)
CompareBytesEqual-4 226ns _ 0% 131ns _ 0% -41.76% (p=0.000 n=3+3)
name old speed new speed delta
Equal/1-4 12.9MB/s _ 0% 11.1MB/s _ 0% -13.98% (p=0.000 n=3+3)
Equal/6-4 51.7MB/s _ 0% 49.8MB/s _ 0% -3.72% (p=0.002 n=3+3)
Equal/9-4 65.7MB/s _ 0% 71.4MB/s _ 0% +8.67% (p=0.000 n=3+3)
Equal/15-4 83.8MB/s _ 0% 88.0MB/s _ 0% +5.02% (p=0.001 n=3+3)
Equal/16-4 85.9MB/s _ 0% 100.6MB/s _ 0% +17.19% (p=0.000 n=3+3)
Equal/20-4 93.2MB/s _ 0% 112.6MB/s _ 0% +20.74% (p=0.000 n=3+3)
Equal/32-4 107MB/s _ 0% 317MB/s _ 0% +195.97% (p=0.000 n=3+3)
Equal/4K-4 142MB/s _ 0% 1902MB/s _ 0% +1243.76% (p=0.000 n=3+3)
Equal/4M-4 142MB/s _ 0% 1946MB/s _ 0% +1274.22% (p=0.000 n=3+3)
Equal/64M-4 111MB/s _55% 1941MB/s _ 0% +1641.21% (p=0.000 n=3+3)
Change-Id: I9af7e82de3c4c5af8813772ed139230900c03b92
Reviewed-on: https://go-review.googlesource.com/c/go/+/380075
Trust: Joel Sing
Trust: mzh
Reviewed-by: mzh
Run-TryBot: Joel Sing
TryBot-Result: Gopher Robot
Reviewed-by: Cherry Mui
---
src/internal/bytealg/equal_riscv64.s | 144 +++++++++++++++++++++------
1 file changed, 111 insertions(+), 33 deletions(-)
diff --git a/src/internal/bytealg/equal_riscv64.s b/src/internal/bytealg/equal_riscv64.s
index 22cb4fa97d..959a996f81 100644
--- a/src/internal/bytealg/equal_riscv64.s
+++ b/src/internal/bytealg/equal_riscv64.s
@@ -9,41 +9,119 @@
// func memequal(a, b unsafe.Pointer, size uintptr) bool
TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25
- MOV a+0(FP), A1
- MOV b+8(FP), A2
- BEQ A1, A2, eq
- MOV size+16(FP), A3
- ADD A1, A3, A4
-loop:
- BEQ A1, A4, eq
-
- MOVBU (A1), A6
- ADD $1, A1
- MOVBU (A2), A7
- ADD $1, A2
- BEQ A6, A7, loop
-
- MOVB ZERO, ret+24(FP)
- RET
-eq:
- MOV $1, A1
- MOVB A1, ret+24(FP)
- RET
+ MOV a+0(FP), X5
+ MOV b+8(FP), X6
+ MOV size+16(FP), X7
+ MOV $ret+24(FP), X19
+ JMP memequal<>(SB)
// func memequal_varlen(a, b unsafe.Pointer) bool
-TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
- MOV a+0(FP), A1
- MOV b+8(FP), A2
- BEQ A1, A2, eq
- MOV 8(CTXT), A3 // compiler stores size at offset 8 in the closure
- MOV A1, 8(X2)
- MOV A2, 16(X2)
- MOV A3, 24(X2)
- CALL runtime·memequal(SB)
- MOVBU 32(X2), A1
- MOVB A1, ret+16(FP)
+TEXT runtime·memequal_varlen(SB),NOSPLIT|NOFRAME,$0-17
+ MOV a+0(FP), X5
+ MOV b+8(FP), X6
+ MOV 8(CTXT), X7 // compiler stores size at offset 8 in the closure
+ MOV $ret+16(FP), X19
+ JMP memequal<>(SB)
+
+// On entry X5 and X6 contain pointers, X7 contains length.
+// X19 contains address for return value.
+TEXT memequal<>(SB),NOSPLIT|NOFRAME,$0
+ BEQ X5, X6, eq
+
+ MOV $32, X8
+ BLT X7, X8, loop4_check
+
+ // Check alignment - if alignment differs we have to do one byte at a time.
+ AND $3, X5, X9
+ AND $3, X6, X10
+ BNE X9, X10, loop4_check
+ BEQZ X9, loop32_check
+
+ // Check one byte at a time until we reach 8 byte alignment.
+ SUB X9, X7, X7
+align:
+ ADD $-1, X9
+ MOVBU 0(X5), X10
+ MOVBU 0(X6), X11
+ BNE X10, X11, not_eq
+ ADD $1, X5
+ ADD $1, X6
+ BNEZ X9, align
+
+loop32_check:
+ MOV $32, X9
+ BLT X7, X9, loop16_check
+loop32:
+ MOV 0(X5), X10
+ MOV 0(X6), X11
+ MOV 8(X5), X12
+ MOV 8(X6), X13
+ BNE X10, X11, not_eq
+ BNE X12, X13, not_eq
+ MOV 16(X5), X14
+ MOV 16(X6), X15
+ MOV 24(X5), X16
+ MOV 24(X6), X17
+ BNE X14, X15, not_eq
+ BNE X16, X17, not_eq
+ ADD $32, X5
+ ADD $32, X6
+ ADD $-32, X7
+ BGE X7, X9, loop32
+ BEQZ X7, eq
+
+loop16_check:
+ MOV $16, X8
+ BLT X7, X8, loop4_check
+loop16:
+ MOV 0(X5), X10
+ MOV 0(X6), X11
+ MOV 8(X5), X12
+ MOV 8(X6), X13
+ BNE X10, X11, not_eq
+ BNE X12, X13, not_eq
+ ADD $16, X5
+ ADD $16, X6
+ ADD $-16, X7
+ BGE X7, X8, loop16
+ BEQZ X7, eq
+
+loop4_check:
+ MOV $4, X8
+ BLT X7, X8, loop1
+loop4:
+ MOVBU 0(X5), X10
+ MOVBU 0(X6), X11
+ MOVBU 1(X5), X12
+ MOVBU 1(X6), X13
+ BNE X10, X11, not_eq
+ BNE X12, X13, not_eq
+ MOVBU 2(X5), X14
+ MOVBU 2(X6), X15
+ MOVBU 3(X5), X16
+ MOVBU 3(X6), X17
+ BNE X14, X15, not_eq
+ BNE X16, X17, not_eq
+ ADD $4, X5
+ ADD $4, X6
+ ADD $-4, X7
+ BGE X7, X8, loop4
+
+loop1:
+ BEQZ X7, eq
+ MOVBU 0(X5), X10
+ MOVBU 0(X6), X11
+ BNE X10, X11, not_eq
+ ADD $1, X5
+ ADD $1, X6
+ ADD $-1, X7
+ JMP loop1
+
+not_eq:
+ MOV $0, X5
+ MOVB X5, (X19)
RET
eq:
- MOV $1, A1
- MOVB A1, ret+16(FP)
+ MOV $1, X5
+ MOVB X5, (X19)
RET
From 291bda80e551289e0b8ed3209782ccb2a98a124b Mon Sep 17 00:00:00 2001
From: Joel Sing
Date: Fri, 21 Jan 2022 19:48:26 +1100
Subject: [PATCH 038/276] internal/bytealg: optimise compare on riscv64
Implement compare using loops that process 32 bytes, 16 bytes, 4 bytes
or 1 byte depending on size and alignment. For comparisons that are less
than 32 bytes the overhead of checking and adjusting alignment usually
exceeds the overhead of reading and processing 4 bytes at a time.
Updates #50615
name old time/op new time/op delta
BytesCompare/1-4 68.4ns _ 1% 61.0ns _ 0% -10.78% (p=0.001 n=3+3)
BytesCompare/2-4 82.9ns _ 0% 71.0ns _ 1% -14.31% (p=0.000 n=3+3)
BytesCompare/4-4 107ns _ 0% 70ns _ 0% -34.96% (p=0.000 n=3+3)
BytesCompare/8-4 156ns _ 0% 90ns _ 0% -42.36% (p=0.000 n=3+3)
BytesCompare/16-4 267ns _11% 130ns _ 0% -51.10% (p=0.011 n=3+3)
BytesCompare/32-4 446ns _ 0% 74ns _ 0% -83.31% (p=0.000 n=3+3)
BytesCompare/64-4 840ns _ 2% 91ns _ 0% -89.17% (p=0.000 n=3+3)
BytesCompare/128-4 1.60_s _ 0% 0.13_s _ 0% -92.18% (p=0.000 n=3+3)
BytesCompare/256-4 3.15_s _ 0% 0.19_s _ 0% -93.91% (p=0.000 n=3+3)
BytesCompare/512-4 6.25_s _ 0% 0.33_s _ 0% -94.80% (p=0.000 n=3+3)
BytesCompare/1024-4 12.5_s _ 0% 0.6_s _ 0% -95.23% (p=0.000 n=3+3)
BytesCompare/2048-4 24.8_s _ 0% 1.1_s _ 0% -95.46% (p=0.000 n=3+3)
CompareBytesEqual-4 225ns _ 0% 131ns _ 0% -41.69% (p=0.000 n=3+3)
CompareBytesToNil-4 45.3ns _ 7% 46.7ns _ 0% ~ (p=0.452 n=3+3)
CompareBytesEmpty-4 41.0ns _ 1% 40.6ns _ 0% ~ (p=0.071 n=3+3)
CompareBytesIdentical-4 48.9ns _ 0% 41.3ns _ 1% -15.58% (p=0.000 n=3+3)
CompareBytesSameLength-4 127ns _ 0% 77ns _ 0% -39.48% (p=0.000 n=3+3)
CompareBytesDifferentLength-4 136ns _12% 78ns _ 0% -42.65% (p=0.018 n=3+3)
CompareBytesBigUnaligned-4 14.9ms _ 1% 7.3ms _ 1% -50.95% (p=0.000 n=3+3)
CompareBytesBig-4 14.9ms _ 1% 2.7ms _ 8% -82.10% (p=0.000 n=3+3)
CompareBytesBigIdentical-4 52.5ns _ 0% 44.9ns _ 0% -14.53% (p=0.000 n=3+3)
name old speed new speed delta
CompareBytesBigUnaligned-4 70.5MB/s _ 1% 143.8MB/s _ 1% +103.87% (p=0.000 n=3+3)
CompareBytesBig-4 70.3MB/s _ 1% 393.8MB/s _ 8% +460.43% (p=0.003 n=3+3)
CompareBytesBigIdentical-4 20.0TB/s _ 0% 23.4TB/s _ 0% +17.00% (p=0.000 n=3+3)
Change-Id: Ie18712a9009d425c75e1ab49d5a673d84e73a1eb
Reviewed-on: https://go-review.googlesource.com/c/go/+/380076
Trust: Joel Sing
Trust: mzh
Reviewed-by: Cherry Mui
---
src/internal/bytealg/compare_generic.go | 2 +-
src/internal/bytealg/compare_native.go | 2 +-
src/internal/bytealg/compare_riscv64.s | 185 ++++++++++++++++++++++++
3 files changed, 187 insertions(+), 2 deletions(-)
create mode 100644 src/internal/bytealg/compare_riscv64.s
diff --git a/src/internal/bytealg/compare_generic.go b/src/internal/bytealg/compare_generic.go
index eaea168f2d..c5853f503f 100644
--- a/src/internal/bytealg/compare_generic.go
+++ b/src/internal/bytealg/compare_generic.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.
-//go:build !386 && !amd64 && !s390x && !arm && !arm64 && !ppc64 && !ppc64le && !mips && !mipsle && !wasm && !mips64 && !mips64le
+//go:build !386 && !amd64 && !s390x && !arm && !arm64 && !ppc64 && !ppc64le && !mips && !mipsle && !wasm && !mips64 && !mips64le && !riscv64
package bytealg
diff --git a/src/internal/bytealg/compare_native.go b/src/internal/bytealg/compare_native.go
index 21ff8fe786..ad0fcd7660 100644
--- a/src/internal/bytealg/compare_native.go
+++ b/src/internal/bytealg/compare_native.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.
-//go:build 386 || amd64 || s390x || arm || arm64 || ppc64 || ppc64le || mips || mipsle || wasm || mips64 || mips64le
+//go:build 386 || amd64 || s390x || arm || arm64 || ppc64 || ppc64le || mips || mipsle || wasm || mips64 || mips64le || riscv64
package bytealg
diff --git a/src/internal/bytealg/compare_riscv64.s b/src/internal/bytealg/compare_riscv64.s
new file mode 100644
index 0000000000..0dc62515a1
--- /dev/null
+++ b/src/internal/bytealg/compare_riscv64.s
@@ -0,0 +1,185 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "go_asm.h"
+#include "textflag.h"
+
+TEXT ·Compare(SB),NOSPLIT|NOFRAME,$0-56
+ MOV a_base+0(FP), X5
+ MOV a_len+8(FP), X6
+ MOV b_base+24(FP), X7
+ MOV b_len+32(FP), X8
+ MOV $ret+48(FP), X9
+ JMP compare<>(SB)
+
+TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40
+ MOV a_base+0(FP), X5
+ MOV a_len+8(FP), X6
+ MOV b_base+16(FP), X7
+ MOV b_len+24(FP), X8
+ MOV $ret+32(FP), X9
+ JMP compare<>(SB)
+
+// On entry:
+// X5 points to start of a
+// X6 length of a
+// X7 points to start of b
+// X8 length of b
+// X9 points to the address to store the return value (-1/0/1)
+TEXT compare<>(SB),NOSPLIT|NOFRAME,$0
+ BEQ X5, X7, cmp_len
+
+ MOV X6, X10
+ BGE X8, X10, use_a_len // X10 = min(len(a), len(b))
+ MOV X8, X10
+use_a_len:
+ BEQZ X10, cmp_len
+
+ MOV $32, X11
+ BLT X10, X11, loop4_check
+
+ // Check alignment - if alignment differs we have to do one byte at a time.
+ AND $3, X5, X12
+ AND $3, X7, X13
+ BNE X12, X13, loop4_check
+ BEQZ X12, loop32_check
+
+ // Check one byte at a time until we reach 8 byte alignment.
+ SUB X12, X10, X10
+align:
+ ADD $-1, X12
+ MOVBU 0(X5), X13
+ MOVBU 0(X7), X14
+ BNE X13, X14, cmp
+ ADD $1, X5
+ ADD $1, X7
+ BNEZ X12, align
+
+loop32_check:
+ MOV $32, X12
+ BLT X10, X12, loop16_check
+loop32:
+ MOV 0(X5), X15
+ MOV 0(X7), X16
+ MOV 8(X5), X17
+ MOV 8(X7), X18
+ BEQ X15, X16, loop32a
+ JMP cmp8a
+loop32a:
+ BEQ X17, X18, loop32b
+ JMP cmp8b
+loop32b:
+ MOV 16(X5), X15
+ MOV 16(X7), X16
+ MOV 24(X5), X17
+ MOV 24(X7), X18
+ BEQ X15, X16, loop32c
+ JMP cmp8a
+loop32c:
+ BEQ X17, X18, loop32d
+ JMP cmp8b
+loop32d:
+ ADD $32, X5
+ ADD $32, X7
+ ADD $-32, X10
+ BGE X10, X12, loop32
+ BEQZ X10, cmp_len
+
+loop16_check:
+ MOV $16, X11
+ BLT X10, X11, loop4_check
+loop16:
+ MOV 0(X5), X15
+ MOV 0(X7), X16
+ MOV 8(X5), X17
+ MOV 8(X7), X18
+ BEQ X15, X16, loop16a
+ JMP cmp8a
+loop16a:
+ BEQ X17, X18, loop16b
+ JMP cmp8b
+loop16b:
+ ADD $16, X5
+ ADD $16, X7
+ ADD $-16, X10
+ BGE X10, X11, loop16
+ BEQZ X10, cmp_len
+
+loop4_check:
+ MOV $4, X11
+ BLT X10, X11, loop1
+loop4:
+ MOVBU 0(X5), X13
+ MOVBU 0(X7), X14
+ MOVBU 1(X5), X15
+ MOVBU 1(X7), X16
+ BEQ X13, X14, loop4a
+ SLTU X14, X13, X10
+ SLTU X13, X14, X11
+ JMP cmp_ret
+loop4a:
+ BEQ X15, X16, loop4b
+ SLTU X16, X15, X10
+ SLTU X15, X16, X11
+ JMP cmp_ret
+loop4b:
+ MOVBU 2(X5), X21
+ MOVBU 2(X7), X22
+ MOVBU 3(X5), X23
+ MOVBU 3(X7), X24
+ BEQ X21, X22, loop4c
+ SLTU X22, X21, X10
+ SLTU X21, X22, X11
+ JMP cmp_ret
+loop4c:
+ BEQ X23, X24, loop4d
+ SLTU X24, X23, X10
+ SLTU X23, X24, X11
+ JMP cmp_ret
+loop4d:
+ ADD $4, X5
+ ADD $4, X7
+ ADD $-4, X10
+ BGE X10, X11, loop4
+
+loop1:
+ BEQZ X10, cmp_len
+ MOVBU 0(X5), X13
+ MOVBU 0(X7), X14
+ BNE X13, X14, cmp
+ ADD $1, X5
+ ADD $1, X7
+ ADD $-1, X10
+ JMP loop1
+
+ // Compare 8 bytes of memory in X15/X16 that are known to differ.
+cmp8a:
+ MOV $0xff, X19
+cmp8a_loop:
+ AND X15, X19, X13
+ AND X16, X19, X14
+ BNE X13, X14, cmp
+ SLLI $8, X19
+ JMP cmp8a_loop
+
+ // Compare 8 bytes of memory in X17/X18 that are known to differ.
+cmp8b:
+ MOV $0xff, X19
+cmp8b_loop:
+ AND X17, X19, X13
+ AND X18, X19, X14
+ BNE X13, X14, cmp
+ SLLI $8, X19
+ JMP cmp8b_loop
+
+cmp_len:
+ MOV X6, X13
+ MOV X8, X14
+cmp:
+ SLTU X14, X13, X10
+ SLTU X13, X14, X11
+cmp_ret:
+ SUB X10, X11, X12
+ MOV X12, (X9)
+ RET
From d3070a767bc0ddfdca1f84e2018de1c906b817ca Mon Sep 17 00:00:00 2001
From: thepudds
Date: Tue, 8 Mar 2022 14:51:27 +0000
Subject: [PATCH 039/276] cmd/compile/internal/types2: more consistently print
"check go.mod" if language version < 1.18
If you attempt to instantiate a generic type or func and run 'go build'
with a language version < 1.18 in the 'go' directive inside the go.mod
file, cmd/compile emits a friendly message that includes the suggestion
to 'check go.mod':
type instantiation requires go1.18 or later (-lang was set to go1.17; check go.mod)
However, if the code instead only declares a generic type or func
without instantiating, cmd/compile currently emits a less friendly
message:
type parameters require go1.18 or later
With this CL, the error in that situation becomes:
type parameter requires go1.18 or later (-lang was set to go1.17; check go.mod)
Within cmd/compile/internal/types2, it already calls check.versionErrorf
in a dozen or so places, including three existing calls to
check.versionErrorf within typeset.go (e.g., for embedding a constraint
interface).
This CL adds two more calls to check.versionErrorf, replacing calls to
check.softErrorf. Both check.versionErrorf and check.softErrorf call
check.err(at, , true) after massaging the string message.
Fixes #51531
Change-Id: If54e179f5952b97701d1dfde4abb08101de07811
GitHub-Last-Rev: b0b7c1346f3a92f70e6cd5ff9ef047f441b09895
GitHub-Pull-Request: golang/go#51536
Reviewed-on: https://go-review.googlesource.com/c/go/+/390578
Reviewed-by: Robert Griesemer
Trust: Robert Findley
---
src/cmd/compile/internal/types2/resolver.go | 4 ++--
.../types2/testdata/fixedbugs/issue47818.go2 | 6 +++---
test/fixedbugs/issue51531.go | 13 +++++++++++++
3 files changed, 18 insertions(+), 5 deletions(-)
create mode 100644 test/fixedbugs/issue51531.go
diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go
index 05755f8cfd..61963cb043 100644
--- a/src/cmd/compile/internal/types2/resolver.go
+++ b/src/cmd/compile/internal/types2/resolver.go
@@ -413,7 +413,7 @@ func (check *Checker) collectObjects() {
case *syntax.TypeDecl:
if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) {
- check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
+ check.versionErrorf(s.TParamList[0], "go1.18", "type parameter")
}
obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Value, nil)
check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, tdecl: s})
@@ -458,7 +458,7 @@ func (check *Checker) collectObjects() {
check.recordDef(s.Name, obj)
}
if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError {
- check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
+ check.versionErrorf(s.TParamList[0], "go1.18", "type parameter")
}
info := &declInfo{file: fileScope, fdecl: s}
// Methods are not package-level objects but we still track them in the
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
index 546de1ce31..6069f1f97b 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
@@ -8,13 +8,13 @@
package go1_17
-type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
+type T[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
// for init (and main, but we're not in package main) we should only get one error
func init[P /* ERROR func init must have no type parameters */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
-func main[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
+func main[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
-func f[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) {
+func f[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) {
var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int]
var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int])
_ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{}
diff --git a/test/fixedbugs/issue51531.go b/test/fixedbugs/issue51531.go
new file mode 100644
index 0000000000..a296bbc776
--- /dev/null
+++ b/test/fixedbugs/issue51531.go
@@ -0,0 +1,13 @@
+// errorcheck -lang=go1.17
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type empty interface{}
+
+type Foo[T empty] int // ERROR "type parameter requires go1\.18 or later \(-lang was set to go1\.17; check go.mod\)"
+
+func Bar[T empty]() {} // ERROR "type parameter requires go1\.18 or later \(-lang was set to go1\.17; check go.mod\)"
From 7419bb3ebb8ea2b9b3745cdcbaf747e4dffc52ae Mon Sep 17 00:00:00 2001
From: "Bryan C. Mills"
Date: Mon, 7 Mar 2022 11:26:18 -0500
Subject: [PATCH 040/276] internal/fuzz: fix encoding for out-of-range ints and
runes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Also switch float64 NaN encoding to use hexadecimal, and accept
hexadecimal encoding for all other integer types too. (That gives us
the flexibility to change the encodings in either direction in the
future without breaking earlier Go versions.)
Out-of-range runes encoded using "%q" were previously replaced with
the Unicode replacement charecter, losing their values.
Out-of-range ints and uints on 32-bit platforms were previously
rejected. Now they are wrapped instead: an “interesting” case with a
large int or uint found on a 64-bit platform likely remains
interesting on a 32-bit platform, even if the specific values differ.
To verify the above changes, I have made TestMarshalUnmarshal accept
(and check for) arbitrary differences between input and output, and
added tests cases that include values in valid but non-canonical
encodings.
I have also added round-trip fuzz tests in the opposite direction for
most of the types affected by this change, verifying that a marshaled
value unmarshals to the same bitwise value.
Updates #51258
Updates #51526
Fixes #51528
Change-Id: I7727a9d0582d81be0d954529545678a4374e88ed
Reviewed-on: https://go-review.googlesource.com/c/go/+/390424
Trust: Bryan Mills
Run-TryBot: Bryan Mills
Reviewed-by: Roland Shoemaker
TryBot-Result: Gopher Robot
---
src/internal/fuzz/encoding.go | 84 +++++++--
src/internal/fuzz/encoding_test.go | 272 +++++++++++++++++++++++++----
2 files changed, 311 insertions(+), 45 deletions(-)
diff --git a/src/internal/fuzz/encoding.go b/src/internal/fuzz/encoding.go
index fe070eca34..c95d9e088b 100644
--- a/src/internal/fuzz/encoding.go
+++ b/src/internal/fuzz/encoding.go
@@ -12,6 +12,7 @@ import (
"go/token"
"math"
"strconv"
+ "unicode/utf8"
)
// encVersion1 will be the first line of a file with version 1 encoding.
@@ -32,21 +33,60 @@ func marshalCorpusFile(vals ...any) []byte {
fmt.Fprintf(b, "%T(%v)\n", t, t)
case float32:
if math.IsNaN(float64(t)) && math.Float32bits(t) != math.Float32bits(float32(math.NaN())) {
- fmt.Fprintf(b, "math.Float32frombits(%v)\n", math.Float32bits(t))
+ // We encode unusual NaNs as hex values, because that is how users are
+ // likely to encounter them in literature about floating-point encoding.
+ // This allows us to reproduce fuzz failures that depend on the specific
+ // NaN representation (for float32 there are about 2^24 possibilities!),
+ // not just the fact that the value is *a* NaN.
+ //
+ // Note that the specific value of float32(math.NaN()) can vary based on
+ // whether the architecture represents signaling NaNs using a low bit
+ // (as is common) or a high bit (as commonly implemented on MIPS
+ // hardware before around 2012). We believe that the increase in clarity
+ // from identifying "NaN" with math.NaN() is worth the slight ambiguity
+ // from a platform-dependent value.
+ fmt.Fprintf(b, "math.Float32frombits(0x%x)\n", math.Float32bits(t))
} else {
+ // We encode all other values — including the NaN value that is
+ // bitwise-identical to float32(math.Nan()) — using the default
+ // formatting, which is equivalent to strconv.FormatFloat with format
+ // 'g' and can be parsed by strconv.ParseFloat.
+ //
+ // For an ordinary floating-point number this format includes
+ // sufficiently many digits to reconstruct the exact value. For positive
+ // or negative infinity it is the string "+Inf" or "-Inf". For positive
+ // or negative zero it is "0" or "-0". For NaN, it is the string "NaN".
fmt.Fprintf(b, "%T(%v)\n", t, t)
}
case float64:
if math.IsNaN(t) && math.Float64bits(t) != math.Float64bits(math.NaN()) {
- fmt.Fprintf(b, "math.Float64frombits(%v)\n", math.Float64bits(t))
+ fmt.Fprintf(b, "math.Float64frombits(0x%x)\n", math.Float64bits(t))
} else {
fmt.Fprintf(b, "%T(%v)\n", t, t)
}
case string:
fmt.Fprintf(b, "string(%q)\n", t)
case rune: // int32
- fmt.Fprintf(b, "rune(%q)\n", t)
+ // Although rune and int32 are represented by the same type, only a subset
+ // of valid int32 values can be expressed as rune literals. Notably,
+ // negative numbers, surrogate halves, and values above unicode.MaxRune
+ // have no quoted representation.
+ //
+ // fmt with "%q" (and the corresponding functions in the strconv package)
+ // would quote out-of-range values to the Unicode replacement character
+ // instead of the original value (see https://go.dev/issue/51526), so
+ // they must be treated as int32 instead.
+ //
+ // We arbitrarily draw the line at UTF-8 validity, which biases toward the
+ // "rune" interpretation. (However, we accept either format as input.)
+ if utf8.ValidRune(t) {
+ fmt.Fprintf(b, "rune(%q)\n", t)
+ } else {
+ fmt.Fprintf(b, "int32(%v)\n", t)
+ }
case byte: // uint8
+ // For bytes, we arbitrarily prefer the character interpretation.
+ // (Every byte has a valid character encoding.)
fmt.Fprintf(b, "byte(%q)\n", t)
case []byte: // []uint8
fmt.Fprintf(b, "[]byte(%q)\n", t)
@@ -199,6 +239,14 @@ func parseCorpusValue(line []byte) (any, error) {
}
return strconv.Unquote(val)
case "byte", "rune":
+ if kind == token.INT {
+ switch typ {
+ case "rune":
+ return parseInt(val, typ)
+ case "byte":
+ return parseUint(val, typ)
+ }
+ }
if kind != token.CHAR {
return nil, fmt.Errorf("character literal required for byte/rune types")
}
@@ -265,18 +313,24 @@ func parseCorpusValue(line []byte) (any, error) {
func parseInt(val, typ string) (any, error) {
switch typ {
case "int":
- return strconv.Atoi(val)
+ // The int type may be either 32 or 64 bits. If 32, the fuzz tests in the
+ // corpus may include 64-bit values produced by fuzzing runs on 64-bit
+ // architectures. When running those tests, we implicitly wrap the values to
+ // fit in a regular int. (The test case is still “interesting”, even if the
+ // specific values of its inputs are platform-dependent.)
+ i, err := strconv.ParseInt(val, 0, 64)
+ return int(i), err
case "int8":
- i, err := strconv.ParseInt(val, 10, 8)
+ i, err := strconv.ParseInt(val, 0, 8)
return int8(i), err
case "int16":
- i, err := strconv.ParseInt(val, 10, 16)
+ i, err := strconv.ParseInt(val, 0, 16)
return int16(i), err
- case "int32":
- i, err := strconv.ParseInt(val, 10, 32)
+ case "int32", "rune":
+ i, err := strconv.ParseInt(val, 0, 32)
return int32(i), err
case "int64":
- return strconv.ParseInt(val, 10, 64)
+ return strconv.ParseInt(val, 0, 64)
default:
panic("unreachable")
}
@@ -286,19 +340,19 @@ func parseInt(val, typ string) (any, error) {
func parseUint(val, typ string) (any, error) {
switch typ {
case "uint":
- i, err := strconv.ParseUint(val, 10, 0)
+ i, err := strconv.ParseUint(val, 0, 64)
return uint(i), err
- case "uint8":
- i, err := strconv.ParseUint(val, 10, 8)
+ case "uint8", "byte":
+ i, err := strconv.ParseUint(val, 0, 8)
return uint8(i), err
case "uint16":
- i, err := strconv.ParseUint(val, 10, 16)
+ i, err := strconv.ParseUint(val, 0, 16)
return uint16(i), err
case "uint32":
- i, err := strconv.ParseUint(val, 10, 32)
+ i, err := strconv.ParseUint(val, 0, 32)
return uint32(i), err
case "uint64":
- return strconv.ParseUint(val, 10, 64)
+ return strconv.ParseUint(val, 0, 64)
default:
panic("unreachable")
}
diff --git a/src/internal/fuzz/encoding_test.go b/src/internal/fuzz/encoding_test.go
index 3a614f5bd2..8e3800eb77 100644
--- a/src/internal/fuzz/encoding_test.go
+++ b/src/internal/fuzz/encoding_test.go
@@ -5,85 +5,104 @@
package fuzz
import (
+ "math"
"strconv"
- "strings"
"testing"
+ "unicode"
)
func TestUnmarshalMarshal(t *testing.T) {
var tests = []struct {
- in string
- ok bool
+ desc string
+ in string
+ reject bool
+ want string // if different from in
}{
{
- in: "int(1234)",
- ok: false, // missing version
+ desc: "missing version",
+ in: "int(1234)",
+ reject: true,
},
{
+ desc: "malformed string",
in: `go test fuzz v1
string("a"bcad")`,
- ok: false, // malformed
+ reject: true,
},
{
+ desc: "empty value",
in: `go test fuzz v1
int()`,
- ok: false, // empty value
+ reject: true,
},
{
+ desc: "negative uint",
in: `go test fuzz v1
uint(-32)`,
- ok: false, // invalid negative uint
+ reject: true,
},
{
+ desc: "int8 too large",
in: `go test fuzz v1
int8(1234456)`,
- ok: false, // int8 too large
+ reject: true,
},
{
+ desc: "multiplication in int value",
in: `go test fuzz v1
int(20*5)`,
- ok: false, // expression in int value
+ reject: true,
},
{
+ desc: "double negation",
in: `go test fuzz v1
int(--5)`,
- ok: false, // expression in int value
+ reject: true,
},
{
+ desc: "malformed bool",
in: `go test fuzz v1
bool(0)`,
- ok: false, // malformed bool
+ reject: true,
},
{
+ desc: "malformed byte",
in: `go test fuzz v1
byte('aa)`,
- ok: false, // malformed byte
+ reject: true,
},
{
+ desc: "byte out of range",
in: `go test fuzz v1
byte('☃')`,
- ok: false, // byte out of range
+ reject: true,
},
{
+ desc: "extra newline",
in: `go test fuzz v1
-string("has final newline")
+string("has extra newline")
`,
- ok: true, // has final newline
+ want: `go test fuzz v1
+string("has extra newline")`,
},
{
+ desc: "trailing spaces",
in: `go test fuzz v1
string("extra")
[]byte("spacing")
`,
- ok: true, // extra spaces in the final newline
+ want: `go test fuzz v1
+string("extra")
+[]byte("spacing")`,
},
{
+ desc: "float types",
in: `go test fuzz v1
float64(0)
float32(0)`,
- ok: true, // will be an integer literal since there is no decimal
},
{
+ desc: "various types",
in: `go test fuzz v1
int(-23)
int8(-2)
@@ -101,9 +120,9 @@ bool(true)
string("hello\\xbd\\xb2=\\xbc ⌘")
float64(-12.5)
float32(2.5)`,
- ok: true,
},
{
+ desc: "float edge cases",
// The two IEEE 754 bit patterns used for the math.Float{64,32}frombits
// encodings are non-math.NAN quiet-NaN values. Since they are not equal
// to math.NaN(), they should be re-encoded to their bit patterns. They
@@ -119,21 +138,94 @@ float32(NaN)
float64(+Inf)
float64(-Inf)
float64(NaN)
+math.Float64frombits(0x7ff8000000000002)
+math.Float32frombits(0x7fc00001)`,
+ },
+ {
+ desc: "int variations",
+ // Although we arbitrarily choose default integer bases (0 or 16), we may
+ // want to change those arbitrary choices in the future and should not
+ // break the parser. Verify that integers in the opposite bases still
+ // parse correctly.
+ in: `go test fuzz v1
+int(0x0)
+int32(0x41)
+int64(0xfffffffff)
+uint32(0xcafef00d)
+uint64(0xffffffffffffffff)
+uint8(0b0000000)
+byte(0x0)
+byte('\000')
+byte('\u0000')
+byte('\'')
math.Float64frombits(9221120237041090562)
math.Float32frombits(2143289345)`,
- ok: true,
+ want: `go test fuzz v1
+int(0)
+rune('A')
+int64(68719476735)
+uint32(3405705229)
+uint64(18446744073709551615)
+byte('\x00')
+byte('\x00')
+byte('\x00')
+byte('\x00')
+byte('\'')
+math.Float64frombits(0x7ff8000000000002)
+math.Float32frombits(0x7fc00001)`,
+ },
+ {
+ desc: "rune validation",
+ in: `go test fuzz v1
+rune(0)
+rune(0x41)
+rune(-1)
+rune(0xfffd)
+rune(0xd800)
+rune(0x10ffff)
+rune(0x110000)
+`,
+ want: `go test fuzz v1
+rune('\x00')
+rune('A')
+int32(-1)
+rune('�')
+int32(55296)
+rune('\U0010ffff')
+int32(1114112)`,
+ },
+ {
+ desc: "int overflow",
+ in: `go test fuzz v1
+int(0x7fffffffffffffff)
+uint(0xffffffffffffffff)`,
+ want: func() string {
+ switch strconv.IntSize {
+ case 32:
+ return `go test fuzz v1
+int(-1)
+uint(4294967295)`
+ case 64:
+ return `go test fuzz v1
+int(9223372036854775807)
+uint(18446744073709551615)`
+ default:
+ panic("unreachable")
+ }
+ }(),
},
}
for _, test := range tests {
- t.Run(test.in, func(t *testing.T) {
+ t.Run(test.desc, func(t *testing.T) {
vals, err := unmarshalCorpusFile([]byte(test.in))
- if test.ok && err != nil {
- t.Fatalf("unmarshal unexpected error: %v", err)
- } else if !test.ok && err == nil {
- t.Fatalf("unmarshal unexpected success")
+ if test.reject {
+ if err == nil {
+ t.Fatalf("unmarshal unexpected success")
+ }
+ return
}
- if !test.ok {
- return // skip the rest of the test
+ if err != nil {
+ t.Fatalf("unmarshal unexpected error: %v", err)
}
newB := marshalCorpusFile(vals...)
if err != nil {
@@ -142,9 +234,15 @@ math.Float32frombits(2143289345)`,
if newB[len(newB)-1] != '\n' {
t.Error("didn't write final newline to corpus file")
}
- before, after := strings.TrimSpace(test.in), strings.TrimSpace(string(newB))
- if before != after {
- t.Errorf("values changed after unmarshal then marshal\nbefore: %q\nafter: %q", before, after)
+
+ want := test.want
+ if want == "" {
+ want = test.in
+ }
+ want += "\n"
+ got := string(newB)
+ if got != want {
+ t.Errorf("unexpected marshaled value\ngot:\n%s\nwant:\n%s", got, want)
}
})
}
@@ -190,3 +288,117 @@ func BenchmarkUnmarshalCorpusFile(b *testing.B) {
})
}
}
+
+func TestByteRoundTrip(t *testing.T) {
+ for x := 0; x < 256; x++ {
+ b1 := byte(x)
+ buf := marshalCorpusFile(b1)
+ vs, err := unmarshalCorpusFile(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ b2 := vs[0].(byte)
+ if b2 != b1 {
+ t.Fatalf("unmarshaled %v, want %v:\n%s", b2, b1, buf)
+ }
+ }
+}
+
+func TestInt8RoundTrip(t *testing.T) {
+ for x := -128; x < 128; x++ {
+ i1 := int8(x)
+ buf := marshalCorpusFile(i1)
+ vs, err := unmarshalCorpusFile(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ i2 := vs[0].(int8)
+ if i2 != i1 {
+ t.Fatalf("unmarshaled %v, want %v:\n%s", i2, i1, buf)
+ }
+ }
+}
+
+func FuzzFloat64RoundTrip(f *testing.F) {
+ f.Add(math.Float64bits(0))
+ f.Add(math.Float64bits(math.Copysign(0, -1)))
+ f.Add(math.Float64bits(math.MaxFloat64))
+ f.Add(math.Float64bits(math.SmallestNonzeroFloat64))
+ f.Add(math.Float64bits(math.NaN()))
+ f.Add(uint64(0x7FF0000000000001)) // signaling NaN
+ f.Add(math.Float64bits(math.Inf(1)))
+ f.Add(math.Float64bits(math.Inf(-1)))
+
+ f.Fuzz(func(t *testing.T, u1 uint64) {
+ x1 := math.Float64frombits(u1)
+
+ b := marshalCorpusFile(x1)
+ t.Logf("marshaled math.Float64frombits(0x%x):\n%s", u1, b)
+
+ xs, err := unmarshalCorpusFile(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(xs) != 1 {
+ t.Fatalf("unmarshaled %d values", len(xs))
+ }
+ x2 := xs[0].(float64)
+ u2 := math.Float64bits(x2)
+ if u2 != u1 {
+ t.Errorf("unmarshaled %v (bits 0x%x)", x2, u2)
+ }
+ })
+}
+
+func FuzzRuneRoundTrip(f *testing.F) {
+ f.Add(rune(-1))
+ f.Add(rune(0xd800))
+ f.Add(rune(0xdfff))
+ f.Add(rune(unicode.ReplacementChar))
+ f.Add(rune(unicode.MaxASCII))
+ f.Add(rune(unicode.MaxLatin1))
+ f.Add(rune(unicode.MaxRune))
+ f.Add(rune(unicode.MaxRune + 1))
+ f.Add(rune(-0x80000000))
+ f.Add(rune(0x7fffffff))
+
+ f.Fuzz(func(t *testing.T, r1 rune) {
+ b := marshalCorpusFile(r1)
+ t.Logf("marshaled rune(0x%x):\n%s", r1, b)
+
+ rs, err := unmarshalCorpusFile(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(rs) != 1 {
+ t.Fatalf("unmarshaled %d values", len(rs))
+ }
+ r2 := rs[0].(rune)
+ if r2 != r1 {
+ t.Errorf("unmarshaled rune(0x%x)", r2)
+ }
+ })
+}
+
+func FuzzStringRoundTrip(f *testing.F) {
+ f.Add("")
+ f.Add("\x00")
+ f.Add(string([]rune{unicode.ReplacementChar}))
+
+ f.Fuzz(func(t *testing.T, s1 string) {
+ b := marshalCorpusFile(s1)
+ t.Logf("marshaled %q:\n%s", s1, b)
+
+ rs, err := unmarshalCorpusFile(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(rs) != 1 {
+ t.Fatalf("unmarshaled %d values", len(rs))
+ }
+ s2 := rs[0].(string)
+ if s2 != s1 {
+ t.Errorf("unmarshaled %q", s2)
+ }
+ })
+}
From e030833880b4ed20a7c153e6e58190c5649284ac Mon Sep 17 00:00:00 2001
From: "Bryan C. Mills"
Date: Fri, 4 Mar 2022 17:17:56 -0500
Subject: [PATCH 041/276] cmd/compile/internal/syntax: don't try to parse files
in GOROOT/.git
This test was failing locally in my clone of the go repo due to a Git
branch ending in ".go", which the test found and was attempting to
parse as a file. It's fragile to try to parse .go files in
GOROOT/.git, and wasteful to scan GOROOT/pkg and other non-source
directories; instead, let's only parse the directories we actually
expect to contain source files.
(I was running the test for #51461.)
Change-Id: I5d4e31ec2bcd9b4b6840ec32ad9b12bf44f349a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/390023
Trust: Bryan Mills
Run-TryBot: Bryan Mills
TryBot-Result: Gopher Robot
Reviewed-by: Robert Griesemer
---
src/cmd/compile/internal/syntax/parser_test.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/cmd/compile/internal/syntax/parser_test.go b/src/cmd/compile/internal/syntax/parser_test.go
index e258a17c38..ecb21e070b 100644
--- a/src/cmd/compile/internal/syntax/parser_test.go
+++ b/src/cmd/compile/internal/syntax/parser_test.go
@@ -78,7 +78,8 @@ func TestStdLib(t *testing.T) {
go func() {
defer close(results)
for _, dir := range []string{
- runtime.GOROOT(),
+ filepath.Join(runtime.GOROOT(), "src"),
+ filepath.Join(runtime.GOROOT(), "misc"),
} {
walkDirs(t, dir, func(filename string) {
if skipRx != nil && skipRx.MatchString(filename) {
From de8ddd97accb417450db014d1f45723515cb5d80 Mon Sep 17 00:00:00 2001
From: Tobias Klauser
Date: Tue, 8 Mar 2022 11:13:37 +0100
Subject: [PATCH 042/276] syscall: add Pipe2 on solaris and use it for
forkExecPipe
Other platforms already define Pipe2, so add it for solaris as well.
Change-Id: If0d2dfc9a3613479fb4611a673a20a4aa0af0b2b
Reviewed-on: https://go-review.googlesource.com/c/go/+/390714
Trust: Tobias Klauser
Run-TryBot: Tobias Klauser
Trust: Matt Layher
TryBot-Result: Gopher Robot
Reviewed-by: Ian Lance Taylor
---
src/syscall/forkpipe.go | 2 +-
src/syscall/forkpipe2.go | 2 +-
src/syscall/syscall_solaris.go | 15 +++++++++++++++
src/syscall/zsyscall_solaris_amd64.go | 13 +++++++++++++
4 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/src/syscall/forkpipe.go b/src/syscall/forkpipe.go
index 6f7d29ce67..5082abc41c 100644
--- a/src/syscall/forkpipe.go
+++ b/src/syscall/forkpipe.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.
-//go:build aix || darwin || solaris
+//go:build aix || darwin
package syscall
diff --git a/src/syscall/forkpipe2.go b/src/syscall/forkpipe2.go
index 312244c0d8..6ab1391c12 100644
--- a/src/syscall/forkpipe2.go
+++ b/src/syscall/forkpipe2.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.
-//go:build dragonfly || freebsd || netbsd || openbsd
+//go:build dragonfly || freebsd || netbsd || openbsd || solaris
package syscall
diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go
index f44a9e25ac..3c50343d84 100644
--- a/src/syscall/syscall_solaris.go
+++ b/src/syscall/syscall_solaris.go
@@ -63,6 +63,21 @@ 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)
+ if err == nil {
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
+ }
+ return err
+}
+
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, EINVAL
diff --git a/src/syscall/zsyscall_solaris_amd64.go b/src/syscall/zsyscall_solaris_amd64.go
index 2d8cdfd280..dad0580027 100644
--- a/src/syscall/zsyscall_solaris_amd64.go
+++ b/src/syscall/zsyscall_solaris_amd64.go
@@ -7,6 +7,7 @@ package syscall
import "unsafe"
+//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so"
//go:cgo_import_dynamic libc_Getcwd getcwd "libc.so"
//go:cgo_import_dynamic libc_getgroups getgroups "libc.so"
//go:cgo_import_dynamic libc_setgroups setgroups "libc.so"
@@ -91,6 +92,7 @@ import "unsafe"
//go:cgo_import_dynamic libc_getexecname getexecname "libc.so"
//go:cgo_import_dynamic libc_utimensat utimensat "libc.so"
+//go:linkname libc_pipe2 libc_pipe2
//go:linkname libc_Getcwd libc_Getcwd
//go:linkname libc_getgroups libc_getgroups
//go:linkname libc_setgroups libc_setgroups
@@ -178,6 +180,7 @@ import "unsafe"
type libcFunc uintptr
var (
+ libc_pipe2,
libc_Getcwd,
libc_getgroups,
libc_setgroups,
@@ -265,6 +268,16 @@ var (
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func pipe2(p *[2]_C_int, flags int) (err error) {
+ _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&libc_pipe2)), 2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0, 0, 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func Getcwd(buf []byte) (n int, err error) {
var _p0 *byte
if len(buf) > 0 {
From 085ef537c4a2c57d373e72f4a110d9fae9a287be Mon Sep 17 00:00:00 2001
From: Tobias Klauser
Date: Tue, 8 Mar 2022 14:54:53 +0100
Subject: [PATCH 043/276] os, internal/syscall/unix: consolidate Pipe
implementations
All platforms with the pipe2 syscall now provide syscall.Pipe2. Use it
to implement os.Pipe.
This also allows to drop the illumos-specific wrapper in
internal/sys/unix.
Change-Id: Ieb712a1498e86a389bad261e4e97c61c11d4bdd0
Reviewed-on: https://go-review.googlesource.com/c/go/+/390715
Trust: Tobias Klauser
Run-TryBot: Tobias Klauser
Trust: Matt Layher
TryBot-Result: Gopher Robot
Reviewed-by: Ian Lance Taylor
---
src/internal/syscall/unix/pipe2_illumos.go | 34 ----------------------
src/os/pipe2_illumos.go | 25 ----------------
src/os/{pipe2_bsd.go => pipe2_unix.go} | 4 +--
src/os/pipe_linux.go | 20 -------------
src/os/{pipe_bsd.go => pipe_unix.go} | 2 +-
5 files changed, 3 insertions(+), 82 deletions(-)
delete mode 100644 src/internal/syscall/unix/pipe2_illumos.go
delete mode 100644 src/os/pipe2_illumos.go
rename src/os/{pipe2_bsd.go => pipe2_unix.go} (81%)
delete mode 100644 src/os/pipe_linux.go
rename src/os/{pipe_bsd.go => pipe_unix.go} (91%)
diff --git a/src/internal/syscall/unix/pipe2_illumos.go b/src/internal/syscall/unix/pipe2_illumos.go
deleted file mode 100644
index c6280f85e5..0000000000
--- a/src/internal/syscall/unix/pipe2_illumos.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build illumos
-
-package unix
-
-import (
- "syscall"
- "unsafe"
-)
-
-//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so"
-
-//go:linkname procpipe2 libc_pipe2
-
-var procpipe2 uintptr
-
-type _C_int int32
-
-func Pipe2(p []int, flags int) error {
- if len(p) != 2 {
- return syscall.EINVAL
- }
- var pp [2]_C_int
- _, _, errno := syscall6(uintptr(unsafe.Pointer(&procpipe2)), 2, uintptr(unsafe.Pointer(&pp)), uintptr(flags), 0, 0, 0, 0)
- if errno != 0 {
- return errno
- }
- p[0] = int(pp[0])
- p[1] = int(pp[1])
- return nil
-}
diff --git a/src/os/pipe2_illumos.go b/src/os/pipe2_illumos.go
deleted file mode 100644
index 354b35cc46..0000000000
--- a/src/os/pipe2_illumos.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build illumos
-
-package os
-
-import (
- "internal/syscall/unix"
- "syscall"
-)
-
-// Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an error, if any.
-func Pipe() (r *File, w *File, err error) {
- var p [2]int
-
- e := unix.Pipe2(p[0:], syscall.O_CLOEXEC)
- if e != nil {
- return nil, nil, NewSyscallError("pipe", e)
- }
-
- return newFile(uintptr(p[0]), "|0", kindPipe), newFile(uintptr(p[1]), "|1", kindPipe), nil
-}
diff --git a/src/os/pipe2_bsd.go b/src/os/pipe2_unix.go
similarity index 81%
rename from src/os/pipe2_bsd.go
rename to src/os/pipe2_unix.go
index 7eb1350d02..1e2e8ccb67 100644
--- a/src/os/pipe2_bsd.go
+++ b/src/os/pipe2_unix.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.
-//go:build dragonfly || freebsd || netbsd || openbsd
+//go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris
package os
@@ -15,7 +15,7 @@ func Pipe() (r *File, w *File, err error) {
e := syscall.Pipe2(p[0:], syscall.O_CLOEXEC)
if e != nil {
- return nil, nil, NewSyscallError("pipe", e)
+ return nil, nil, NewSyscallError("pipe2", e)
}
return newFile(uintptr(p[0]), "|0", kindPipe), newFile(uintptr(p[1]), "|1", kindPipe), nil
diff --git a/src/os/pipe_linux.go b/src/os/pipe_linux.go
deleted file mode 100644
index 52f4e21e7c..0000000000
--- a/src/os/pipe_linux.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package os
-
-import "syscall"
-
-// Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an error, if any.
-func Pipe() (r *File, w *File, err error) {
- var p [2]int
-
- e := syscall.Pipe2(p[0:], syscall.O_CLOEXEC)
- if e != nil {
- return nil, nil, NewSyscallError("pipe2", e)
- }
-
- return newFile(uintptr(p[0]), "|0", kindPipe), newFile(uintptr(p[1]), "|1", kindPipe), nil
-}
diff --git a/src/os/pipe_bsd.go b/src/os/pipe_unix.go
similarity index 91%
rename from src/os/pipe_bsd.go
rename to src/os/pipe_unix.go
index 554d62111a..710f77670e 100644
--- a/src/os/pipe_bsd.go
+++ b/src/os/pipe_unix.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.
-//go:build aix || darwin || (js && wasm) || (solaris && !illumos)
+//go:build aix || darwin || (js && wasm)
package os
From c3c74777bc5dcd351af6dc4811011241efe07d21 Mon Sep 17 00:00:00 2001
From: Tobias Klauser
Date: Tue, 8 Mar 2022 14:55:26 +0100
Subject: [PATCH 044/276] runtime, syscall: implement syscall.Pipe using
syscall.Pipe2 on solaris
All other platforms providing the pipe2 syscall already implement it
that way. Do so as well on solaris, which allows to drop
runtime.syscall_pipe and its dependencies as well.
Change-Id: Icf04777f21d1804da74325d173fefdc87caa42eb
Reviewed-on: https://go-review.googlesource.com/c/go/+/390716
Trust: Tobias Klauser
Run-TryBot: Tobias Klauser
Trust: Matt Layher
TryBot-Result: Gopher Robot
Reviewed-by: Ian Lance Taylor
---
src/runtime/os3_solaris.go | 3 ---
src/runtime/sys_solaris_amd64.s | 12 ------------
src/runtime/syscall_solaris.go | 18 ------------------
src/syscall/asm_solaris_amd64.s | 3 ---
src/syscall/syscall_solaris.go | 14 +-------------
5 files changed, 1 insertion(+), 49 deletions(-)
diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go
index 5aee04d5a8..f465a3aa3f 100644
--- a/src/runtime/os3_solaris.go
+++ b/src/runtime/os3_solaris.go
@@ -47,7 +47,6 @@ import (
//go:cgo_import_dynamic libc_sysconf sysconf "libc.so"
//go:cgo_import_dynamic libc_usleep usleep "libc.so"
//go:cgo_import_dynamic libc_write write "libc.so"
-//go:cgo_import_dynamic libc_pipe pipe "libc.so"
//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so"
//go:linkname libc____errno libc____errno
@@ -83,7 +82,6 @@ import (
//go:linkname libc_sysconf libc_sysconf
//go:linkname libc_usleep libc_usleep
//go:linkname libc_write libc_write
-//go:linkname libc_pipe libc_pipe
//go:linkname libc_pipe2 libc_pipe2
var (
@@ -120,7 +118,6 @@ var (
libc_sysconf,
libc_usleep,
libc_write,
- libc_pipe,
libc_pipe2 libcFunc
)
diff --git a/src/runtime/sys_solaris_amd64.s b/src/runtime/sys_solaris_amd64.s
index 05fd187517..24d2d61df0 100644
--- a/src/runtime/sys_solaris_amd64.s
+++ b/src/runtime/sys_solaris_amd64.s
@@ -29,18 +29,6 @@ TEXT runtime·miniterrno(SB),NOSPLIT,$0
MOVQ AX, (m_mOS+mOS_perrno)(BX)
RET
-// pipe(3c) wrapper that returns fds in AX, DX.
-// NOT USING GO CALLING CONVENTION.
-TEXT runtime·pipe1(SB),NOSPLIT,$0
- SUBQ $16, SP // 8 bytes will do, but stack has to be 16-byte aligned
- MOVQ SP, DI
- LEAQ libc_pipe(SB), AX
- CALL AX
- MOVL 0(SP), AX
- MOVL 4(SP), DX
- ADDQ $16, SP
- RET
-
// Call a library function with SysV calling conventions.
// The called function can take a maximum of 6 INTEGER class arguments,
// see
diff --git a/src/runtime/syscall_solaris.go b/src/runtime/syscall_solaris.go
index e270e271c0..79775711ae 100644
--- a/src/runtime/syscall_solaris.go
+++ b/src/runtime/syscall_solaris.go
@@ -25,11 +25,6 @@ var (
libc_wait4 libcFunc
)
-//go:linkname pipe1x runtime.pipe1
-var pipe1x libcFunc // name to take addr of pipe1
-
-func pipe1() // declared for vet; do NOT call
-
// Many of these are exported via linkname to assembly in the syscall
// package.
@@ -196,19 +191,6 @@ func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
return call.err
}
-//go:linkname syscall_pipe
-func syscall_pipe() (r, w, err uintptr) {
- call := libcall{
- fn: uintptr(unsafe.Pointer(&pipe1x)),
- n: 0,
- args: uintptr(unsafe.Pointer(&pipe1x)), // it's unused but must be non-nil, otherwise crashes
- }
- entersyscallblock()
- asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call))
- exitsyscall()
- return call.r1, call.r2, call.err
-}
-
// This is syscall.RawSyscall, it exists to satisfy some build dependency,
// but it doesn't work.
//
diff --git a/src/syscall/asm_solaris_amd64.s b/src/syscall/asm_solaris_amd64.s
index c61e04a42f..3672d3667f 100644
--- a/src/syscall/asm_solaris_amd64.s
+++ b/src/syscall/asm_solaris_amd64.s
@@ -48,9 +48,6 @@ TEXT ·getpid(SB),NOSPLIT,$0
TEXT ·ioctl(SB),NOSPLIT,$0
JMP runtime·syscall_ioctl(SB)
-TEXT ·pipe(SB),NOSPLIT,$0
- JMP runtime·syscall_pipe(SB)
-
TEXT ·RawSyscall(SB),NOSPLIT,$0
JMP runtime·syscall_rawsyscall(SB)
diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go
index 3c50343d84..d01070b2ec 100644
--- a/src/syscall/syscall_solaris.go
+++ b/src/syscall/syscall_solaris.go
@@ -47,20 +47,8 @@ func direntNamlen(buf []byte) (uint64, bool) {
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
}
-func pipe() (r uintptr, w uintptr, err uintptr)
-
func Pipe(p []int) (err error) {
- if len(p) != 2 {
- return EINVAL
- }
- r0, w0, e1 := pipe()
- if e1 != 0 {
- err = Errno(e1)
- }
- if err == nil {
- p[0], p[1] = int(r0), int(w0)
- }
- return
+ return Pipe2(p, 0)
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
From bd77d6e24048e5a8b7b07d2d0b7cf552d21905f5 Mon Sep 17 00:00:00 2001
From: Rhys Hiltner
Date: Tue, 8 Feb 2022 14:51:41 -0800
Subject: [PATCH 045/276] runtime/pprof: check if PC is reused for inlining
When describing call stacks that include inlined function calls, the
runtime uses "fake" PCs to represent the frames that inlining removed.
Those PCs correspond to real NOP instructions that the compiler inserts
for this purpose.
Describing the call stack in a protobuf-formatted profile requires the
runtime/pprof package to collapse any sequences of fake call sites back
into single PCs, removing the NOPs but retaining their line info.
But because the NOP instructions are part of the function, they can
appear as leaf nodes in a CPU profile. That results in an address that
should sometimes be ignored (when it appears as a call site) and that
sometimes should be present in the profile (when it is observed
consuming CPU time).
When processing a PC address, consider it first as a fake PC to add to
the current inlining deck, and then as a previously-seen (real) PC.
Fixes #50996
Change-Id: I80802369978bd7ac9969839ecfc9995ea4f84ab4
Reviewed-on: https://go-review.googlesource.com/c/go/+/384239
Reviewed-by: Cherry Mui
Reviewed-by: Michael Pratt
---
src/runtime/pprof/proto.go | 50 +++++++++++++++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go
index 073a076802..215bd0bf96 100644
--- a/src/runtime/pprof/proto.go
+++ b/src/runtime/pprof/proto.go
@@ -244,6 +244,10 @@ type locInfo struct {
// to represent inlined functions
// https://github.com/golang/go/blob/d6f2f833c93a41ec1c68e49804b8387a06b131c5/src/runtime/traceback.go#L347-L368
pcs []uintptr
+
+ // results of allFrames call for this PC
+ frames []runtime.Frame
+ symbolizeResult symbolizeFlag
}
// newProfileBuilder returns a new profileBuilder.
@@ -399,6 +403,24 @@ func (b *profileBuilder) appendLocsForStack(locs []uint64, stk []uintptr) (newLo
for len(stk) > 0 {
addr := stk[0]
if l, ok := b.locs[addr]; ok {
+ // When generating code for an inlined function, the compiler adds
+ // NOP instructions to the outermost function as a placeholder for
+ // each layer of inlining. When the runtime generates tracebacks for
+ // stacks that include inlined functions, it uses the addresses of
+ // those NOPs as "fake" PCs on the stack as if they were regular
+ // function call sites. But if a profiling signal arrives while the
+ // CPU is executing one of those NOPs, its PC will show up as a leaf
+ // in the profile with its own Location entry. So, always check
+ // whether addr is a "fake" PC in the context of the current call
+ // stack by trying to add it to the inlining deck before assuming
+ // that the deck is complete.
+ if len(b.deck.pcs) > 0 {
+ if added := b.deck.tryAdd(addr, l.frames, l.symbolizeResult); added {
+ stk = stk[1:]
+ continue
+ }
+ }
+
// first record the location if there is any pending accumulated info.
if id := b.emitLocation(); id > 0 {
locs = append(locs, id)
@@ -451,6 +473,27 @@ func (b *profileBuilder) appendLocsForStack(locs []uint64, stk []uintptr) (newLo
return locs
}
+// Here's an example of how Go 1.17 writes out inlined functions, compiled for
+// linux/amd64. The disassembly of main.main shows two levels of inlining: main
+// calls b, b calls a, a does some work.
+//
+// inline.go:9 0x4553ec 90 NOPL // func main() { b(v) }
+// inline.go:6 0x4553ed 90 NOPL // func b(v *int) { a(v) }
+// inline.go:5 0x4553ee 48c7002a000000 MOVQ $0x2a, 0(AX) // func a(v *int) { *v = 42 }
+//
+// If a profiling signal arrives while executing the MOVQ at 0x4553ee (for line
+// 5), the runtime will report the stack as the MOVQ frame being called by the
+// NOPL at 0x4553ed (for line 6) being called by the NOPL at 0x4553ec (for line
+// 9).
+//
+// The role of pcDeck is to collapse those three frames back into a single
+// location at 0x4553ee, with file/line/function symbolization info representing
+// the three layers of calls. It does that via sequential calls to pcDeck.tryAdd
+// starting with the leaf-most address. The fourth call to pcDeck.tryAdd will be
+// for the caller of main.main. Because main.main was not inlined in its caller,
+// the deck will reject the addition, and the fourth PC on the stack will get
+// its own location.
+
// pcDeck is a helper to detect a sequence of inlined functions from
// a stack trace returned by the runtime.
//
@@ -535,7 +578,12 @@ func (b *profileBuilder) emitLocation() uint64 {
newFuncs := make([]newFunc, 0, 8)
id := uint64(len(b.locs)) + 1
- b.locs[addr] = locInfo{id: id, pcs: append([]uintptr{}, b.deck.pcs...)}
+ b.locs[addr] = locInfo{
+ id: id,
+ pcs: append([]uintptr{}, b.deck.pcs...),
+ symbolizeResult: b.deck.symbolizeResult,
+ frames: append([]runtime.Frame{}, b.deck.frames...),
+ }
start := b.pb.startMessage()
b.pb.uint64Opt(tagLocation_ID, id)
From 67f1a436b9c4055e02d9d031c6c2e9d6c9456bf0 Mon Sep 17 00:00:00 2001
From: Michael Pratt
Date: Mon, 13 Dec 2021 17:32:07 -0500
Subject: [PATCH 046/276] cmd/dist: log CPU model when testing
Knowing whether test failures are correlated with specific CPU models on
has proven useful on several issues. Log it for prior to testing so it
is always available.
internal/sysinfo provides the CPU model, but it is not available in the
bootstrap toolchain, so we can't access this in cmd/dist. Instead use a
separate binary which cmd/dist will only build once testing begins.
The addition of new data to the beginning of cmd/dist output will break
x/build/cmd/coordinator's banner parsing, leaving extra lines in the log
output, though information will not be lost.
https://golang.org/cl/372538 fixes up the coordinator and should be
submitted and deployed before this CL is submitted.
This is a redo of CL 371474. It switches back to the original approach
of using a separate binary, as the bootstap toolchain won't allow
cmd/dist to import internal packages.
For #46272.
For #49209.
For #50146.
Change-Id: I906bbda987902a2120c5183290a4e89a2440de58
Reviewed-on: https://go-review.googlesource.com/c/go/+/378589
Reviewed-by: Austin Clements
Trust: Michael Pratt
Run-TryBot: Michael Pratt
TryBot-Result: Gopher Robot
---
src/cmd/dist/test.go | 25 +++++++++++++++++++++++++
src/cmd/internal/metadata/main.go | 19 +++++++++++++++++++
2 files changed, 44 insertions(+)
create mode 100644 src/cmd/internal/metadata/main.go
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
index ab30089881..cd3c26ab3a 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -218,6 +218,15 @@ func (t *tester) run() {
}
}
+ if err := t.maybeLogMetadata(); err != nil {
+ t.failed = true
+ if t.keepGoing {
+ log.Printf("Failed logging metadata: %v", err)
+ } else {
+ fatalf("Failed logging metadata: %v", err)
+ }
+ }
+
for _, dt := range t.tests {
if !t.shouldRunTest(dt.name) {
t.partial = true
@@ -268,6 +277,22 @@ func (t *tester) shouldRunTest(name string) bool {
return false
}
+func (t *tester) maybeLogMetadata() error {
+ if t.compileOnly {
+ // We need to run a subprocess to log metadata. Don't do that
+ // on compile-only runs.
+ return nil
+ }
+ t.out("Test execution environment.")
+ // Helper binary to print system metadata (CPU model, etc). This is a
+ // separate binary from dist so it need not build with the bootstrap
+ // toolchain.
+ //
+ // TODO(prattmic): If we split dist bootstrap and dist test then this
+ // could be simplified to directly use internal/sysinfo here.
+ return t.dirCmd(filepath.Join(goroot, "src/cmd/internal/metadata"), "go", []string{"run", "."}).Run()
+}
+
// short returns a -short flag value to use with 'go test'
// or a test binary for tests intended to run in short mode.
// It returns "true", unless the environment variable
diff --git a/src/cmd/internal/metadata/main.go b/src/cmd/internal/metadata/main.go
new file mode 100644
index 0000000000..2df048fad6
--- /dev/null
+++ b/src/cmd/internal/metadata/main.go
@@ -0,0 +1,19 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Metadata prints basic system metadata to include in test logs. This is
+// separate from cmd/dist so it does not need to build with the bootstrap
+// toolchain.
+package main
+
+import (
+ "fmt"
+ "internal/sysinfo"
+ "runtime"
+)
+
+func main() {
+ fmt.Printf("# GOARCH: %s\n", runtime.GOARCH)
+ fmt.Printf("# CPU: %s\n", sysinfo.CPU.Name())
+}
From dbbe4cca5d7069482983316694334bdf2fe6a7ec Mon Sep 17 00:00:00 2001
From: Michael Pratt
Date: Mon, 13 Dec 2021 17:34:16 -0500
Subject: [PATCH 047/276] cmd/dist: log OS version when testing
As a follow-up to https://golang.org/cl/371474, add the OS version to
the metadata printed for each test.
This is a redo of CL 371475. This version updates go.mod and conforms to
the changes made in the parent commit.
Fixes #50146.
Change-Id: Iba5541cc8dd2c85c1fa3a215e30c8c3f9b6aaaab
Reviewed-on: https://go-review.googlesource.com/c/go/+/378590
Reviewed-by: Austin Clements
Trust: Michael Pratt
Run-TryBot: Michael Pratt
TryBot-Result: Gopher Robot
---
src/cmd/go.mod | 2 +-
src/cmd/internal/metadata/main.go | 8 ++++++
src/cmd/internal/osinfo/doc.go | 6 +++++
src/cmd/internal/osinfo/os_js.go | 21 ++++++++++++++++
src/cmd/internal/osinfo/os_plan9.go | 21 ++++++++++++++++
src/cmd/internal/osinfo/os_unix.go | 36 +++++++++++++++++++++++++++
src/cmd/internal/osinfo/os_windows.go | 19 ++++++++++++++
7 files changed, 112 insertions(+), 1 deletion(-)
create mode 100644 src/cmd/internal/osinfo/doc.go
create mode 100644 src/cmd/internal/osinfo/os_js.go
create mode 100644 src/cmd/internal/osinfo/os_plan9.go
create mode 100644 src/cmd/internal/osinfo/os_unix.go
create mode 100644 src/cmd/internal/osinfo/os_windows.go
diff --git a/src/cmd/go.mod b/src/cmd/go.mod
index 48fc888f94..fd54a88630 100644
--- a/src/cmd/go.mod
+++ b/src/cmd/go.mod
@@ -7,6 +7,7 @@ require (
golang.org/x/arch v0.0.0-20210923205945-b76863e36670
golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
+ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
golang.org/x/tools v0.1.9-0.20220124164225-97de9ec46646
)
@@ -14,6 +15,5 @@ require (
require (
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
- golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)
diff --git a/src/cmd/internal/metadata/main.go b/src/cmd/internal/metadata/main.go
index 2df048fad6..157226e890 100644
--- a/src/cmd/internal/metadata/main.go
+++ b/src/cmd/internal/metadata/main.go
@@ -8,6 +8,7 @@
package main
import (
+ "cmd/internal/osinfo"
"fmt"
"internal/sysinfo"
"runtime"
@@ -16,4 +17,11 @@ import (
func main() {
fmt.Printf("# GOARCH: %s\n", runtime.GOARCH)
fmt.Printf("# CPU: %s\n", sysinfo.CPU.Name())
+
+ fmt.Printf("# GOOS: %s\n", runtime.GOOS)
+ ver, err := osinfo.Version()
+ if err != nil {
+ ver = fmt.Sprintf("UNKNOWN: error determining OS version: %v", err)
+ }
+ fmt.Printf("# OS Version: %s\n", ver)
}
diff --git a/src/cmd/internal/osinfo/doc.go b/src/cmd/internal/osinfo/doc.go
new file mode 100644
index 0000000000..1b5469d53a
--- /dev/null
+++ b/src/cmd/internal/osinfo/doc.go
@@ -0,0 +1,6 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package osinfo provides OS metadata.
+package osinfo
diff --git a/src/cmd/internal/osinfo/os_js.go b/src/cmd/internal/osinfo/os_js.go
new file mode 100644
index 0000000000..882580d652
--- /dev/null
+++ b/src/cmd/internal/osinfo/os_js.go
@@ -0,0 +1,21 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build js
+
+package osinfo
+
+import (
+ "fmt"
+)
+
+// Version returns the OS version name/number.
+func Version() (string, error) {
+ // Version detection on wasm varies depending on the underlying runtime
+ // (browser, node, etc), nor is there a standard via something like
+ // WASI (see https://go.dev/issue/31105). We could attempt multiple
+ // combinations, but for now we leave this unimplemented for
+ // simplicity.
+ return "", fmt.Errorf("unimplemented")
+}
diff --git a/src/cmd/internal/osinfo/os_plan9.go b/src/cmd/internal/osinfo/os_plan9.go
new file mode 100644
index 0000000000..e0225a93a2
--- /dev/null
+++ b/src/cmd/internal/osinfo/os_plan9.go
@@ -0,0 +1,21 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build plan9
+
+package osinfo
+
+import (
+ "os"
+)
+
+// Version returns the OS version name/number.
+func Version() (string, error) {
+ b, err := os.ReadFile("/dev/osversion")
+ if err != nil {
+ return "", err
+ }
+
+ return string(b), nil
+}
diff --git a/src/cmd/internal/osinfo/os_unix.go b/src/cmd/internal/osinfo/os_unix.go
new file mode 100644
index 0000000000..fab9e08f82
--- /dev/null
+++ b/src/cmd/internal/osinfo/os_unix.go
@@ -0,0 +1,36 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
+
+package osinfo
+
+import (
+ "bytes"
+
+ "golang.org/x/sys/unix"
+)
+
+func utsString(b []byte) string {
+ i := bytes.IndexByte(b, 0)
+ if i == -1 {
+ return string(b)
+ }
+ return string(b[:i])
+}
+
+// Version returns the OS version name/number.
+func Version() (string, error) {
+ var uts unix.Utsname
+ if err := unix.Uname(&uts); err != nil {
+ return "", err
+ }
+
+ sysname := utsString(uts.Sysname[:])
+ release := utsString(uts.Release[:])
+ version := utsString(uts.Version[:])
+ machine := utsString(uts.Machine[:])
+
+ return sysname + " " + release + " " + version + " " + machine, nil
+}
diff --git a/src/cmd/internal/osinfo/os_windows.go b/src/cmd/internal/osinfo/os_windows.go
new file mode 100644
index 0000000000..8ffe4f3f6d
--- /dev/null
+++ b/src/cmd/internal/osinfo/os_windows.go
@@ -0,0 +1,19 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build windows
+
+package osinfo
+
+import (
+ "fmt"
+
+ "golang.org/x/sys/windows"
+)
+
+// Version returns the OS version name/number.
+func Version() (string, error) {
+ major, minor, patch := windows.RtlGetNtVersionNumbers()
+ return fmt.Sprintf("%d.%d.%d", major, minor, patch), nil
+}
From 4469557974a95b1f4bc1c700aee6779a0f15d22e Mon Sep 17 00:00:00 2001
From: "Bryan C. Mills"
Date: Tue, 8 Feb 2022 15:24:33 -0500
Subject: [PATCH 048/276] net/http/pprof: skip TestDeltaProfile on all arm and
arm64 architectures
Given that we have seen failures with the same failure mode on both
openbsd/arm and android/arm64, it seems likely that the underlying bug
affects at least all ARM-based architectures.
It appears that either these architectures are not able to sample at
the frequency expected by the test, or the samples are for some reason
being dropped.
For #50218
Change-Id: I42a6c8ecda57448f8068e8facb42a4a2cecbbb37
Reviewed-on: https://go-review.googlesource.com/c/go/+/383997
Trust: Bryan Mills
Run-TryBot: Bryan Mills
TryBot-Result: Gopher Robot
Reviewed-by: Cherry Mui
---
src/net/http/pprof/pprof_test.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/net/http/pprof/pprof_test.go b/src/net/http/pprof/pprof_test.go
index 1a4d653a62..f82ad45bf6 100644
--- a/src/net/http/pprof/pprof_test.go
+++ b/src/net/http/pprof/pprof_test.go
@@ -153,7 +153,7 @@ func mutexHog(duration time.Duration, hogger func(mu1, mu2 *sync.Mutex, start ti
}
func TestDeltaProfile(t *testing.T) {
- if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
+ if strings.HasPrefix(runtime.GOARCH, "arm") {
testenv.SkipFlaky(t, 50218)
}
From 0add0647d80f8ec794042b4608275830372fe298 Mon Sep 17 00:00:00 2001
From: Robert Findley
Date: Tue, 8 Mar 2022 16:43:47 -0500
Subject: [PATCH 049/276] go/printer: don't print unnecesary commas for func
type param lists
Type parameter lists are not ambiguous for function declarations in the
way that they are ambiguous for type declarations. Avoid printing an
extra comma to disambiguate.
Fixes #51548
Change-Id: I8ca2b21e271982013653b9e220f92ee74f577ba2
Reviewed-on: https://go-review.googlesource.com/c/go/+/390914
Trust: Robert Findley
Run-TryBot: Robert Findley
Reviewed-by: Robert Griesemer
TryBot-Result: Gopher Robot
---
src/go/printer/nodes.go | 24 +++++++++++++++--------
src/go/printer/testdata/generics.golden | 26 +++++++++++++++++++++++++
src/go/printer/testdata/generics.input | 25 ++++++++++++++++++++++++
3 files changed, 67 insertions(+), 8 deletions(-)
diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go
index f2170dbc4f..9a09d58eb2 100644
--- a/src/go/printer/nodes.go
+++ b/src/go/printer/nodes.go
@@ -319,9 +319,17 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
}
}
-func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) {
+type paramMode int
+
+const (
+ funcParam paramMode = iota
+ funcTParam
+ typeTParam
+)
+
+func (p *printer) parameters(fields *ast.FieldList, mode paramMode) {
openTok, closeTok := token.LPAREN, token.RPAREN
- if isTypeParam {
+ if mode != funcParam {
openTok, closeTok = token.LBRACK, token.RBRACK
}
p.print(fields.Opening, openTok)
@@ -373,7 +381,7 @@ func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) {
if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing {
p.print(token.COMMA)
p.linebreak(closing, 0, ignore, true)
- } else if isTypeParam && fields.NumFields() == 1 {
+ } else if mode == typeTParam && fields.NumFields() == 1 {
// Otherwise, if we are in a type parameter list that could be confused
// with the constant array length expression [P*C], print a comma so that
// parsing is unambiguous.
@@ -411,10 +419,10 @@ func isTypeLit(x ast.Expr) bool {
func (p *printer) signature(sig *ast.FuncType) {
if sig.TypeParams != nil {
- p.parameters(sig.TypeParams, true)
+ p.parameters(sig.TypeParams, funcTParam)
}
if sig.Params != nil {
- p.parameters(sig.Params, false)
+ p.parameters(sig.Params, funcParam)
} else {
p.print(token.LPAREN, token.RPAREN)
}
@@ -428,7 +436,7 @@ func (p *printer) signature(sig *ast.FuncType) {
p.expr(stripParensAlways(res.List[0].Type))
return
}
- p.parameters(res, false)
+ p.parameters(res, funcParam)
}
}
@@ -1639,7 +1647,7 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
p.setComment(s.Doc)
p.expr(s.Name)
if s.TypeParams != nil {
- p.parameters(s.TypeParams, true)
+ p.parameters(s.TypeParams, typeTParam)
}
if n == 1 {
p.print(blank)
@@ -1829,7 +1837,7 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
// FUNC is emitted).
startCol := p.out.Column - len("func ")
if d.Recv != nil {
- p.parameters(d.Recv, false) // method: print receiver
+ p.parameters(d.Recv, funcParam) // method: print receiver
p.print(blank)
}
p.expr(d.Name)
diff --git a/src/go/printer/testdata/generics.golden b/src/go/printer/testdata/generics.golden
index 4fac2c9c58..c3a7df8372 100644
--- a/src/go/printer/testdata/generics.golden
+++ b/src/go/printer/testdata/generics.golden
@@ -64,3 +64,29 @@ type _ [P*T - T]struct{}
type _[
P *T,
] struct{}
+
+// equivalent test cases for potentially ambiguous type parameter lists, except
+// for function declarations there is no ambiguity (issue #51548)
+func _[P *T]() {}
+func _[P *T, _ any]() {}
+func _[P *T]() {}
+func _[P *T, _ any]() {}
+func _[P T]() {}
+func _[P T, _ any]() {}
+
+func _[P *struct{}]() {}
+func _[P *struct{}]() {}
+func _[P []int]() {}
+
+func _[P T]() {}
+func _[P T]() {}
+func _[P **T]() {}
+func _[P *T]() {}
+func _[P *T]() {}
+func _[P **T]() {}
+func _[P *T]() {}
+
+func _[
+ P *T,
+]() {
+}
diff --git a/src/go/printer/testdata/generics.input b/src/go/printer/testdata/generics.input
index fde9d32ef0..66e1554f7f 100644
--- a/src/go/printer/testdata/generics.input
+++ b/src/go/printer/testdata/generics.input
@@ -61,3 +61,28 @@ type _ [P * T - T]struct{}
type _[
P *T,
] struct{}
+
+// equivalent test cases for potentially ambiguous type parameter lists, except
+// for function declarations there is no ambiguity (issue #51548)
+func _[P *T,]() {}
+func _[P *T, _ any]() {}
+func _[P (*T),]() {}
+func _[P (*T), _ any]() {}
+func _[P (T),]() {}
+func _[P (T), _ any]() {}
+
+func _[P *struct{}] () {}
+func _[P (*struct{})] () {}
+func _[P ([]int)] () {}
+
+func _ [P(T)]() {}
+func _ [P((T))]() {}
+func _ [P * *T]() {}
+func _ [P * T]() {}
+func _ [P(*T)]() {}
+func _ [P(**T)]() {}
+func _ [P * T]() {}
+
+func _[
+ P *T,
+]() {}
From 20d333b6f48545cd9900a39fb10f390584d4ba2c Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Tue, 8 Mar 2022 13:32:34 -0800
Subject: [PATCH 050/276] cmd/go: for gccgo expect one fewer file in
TestScript/list_swigcxx
One of the files in CompileGoFiles is actually _cgo_import.go, but
that file is only generated for gc, not for gccgo.
Change-Id: I87bb55552e1409cc57da8f35a32b37ce4a3df60c
Reviewed-on: https://go-review.googlesource.com/c/go/+/390895
Trust: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gopher Robot
Reviewed-by: Bryan Mills
---
src/cmd/go/testdata/script/list_swigcxx.txt | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/cmd/go/testdata/script/list_swigcxx.txt b/src/cmd/go/testdata/script/list_swigcxx.txt
index d4227a80e8..4220487a28 100644
--- a/src/cmd/go/testdata/script/list_swigcxx.txt
+++ b/src/cmd/go/testdata/script/list_swigcxx.txt
@@ -6,7 +6,7 @@
# CompiledGoFiles should contain 4 files:
# a.go
-# a.swigcxx.go
+# _cgo_import.go [gc only]
# _cgo_gotypes.go
# a.cgo1.go
#
@@ -16,7 +16,8 @@
go list -f '{{.CompiledGoFiles}}' -compiled=true example/swig
stdout a\.go
-stdout -count=3 $GOCACHE
+[gc] stdout -count=3 $GOCACHE
+[gccgo] stdout -count=2 $GOCACHE
-- go.mod --
module example
From 1045faa38c660b8a0ac3fbf5b0a01dde26a3cf75 Mon Sep 17 00:00:00 2001
From: Meng Zhuo
Date: Tue, 19 Oct 2021 10:22:20 +0800
Subject: [PATCH 051/276] cmd/compile/internal: add ABI register information
for riscv64
This CL adds the defines for ABI registers on riscv64.
Updates #40724
Change-Id: I53a89d88b6feb1a88cf7008b8484d444791e8a55
Reviewed-on: https://go-review.googlesource.com/c/go/+/356519
Trust: mzh
Run-TryBot: mzh
Reviewed-by: Joel Sing
Reviewed-by: Cherry Mui
TryBot-Result: Gopher Robot
---
src/cmd/compile/abi-internal.md | 51 +++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/src/cmd/compile/abi-internal.md b/src/cmd/compile/abi-internal.md
index 53eaa84d54..72232bd151 100644
--- a/src/cmd/compile/abi-internal.md
+++ b/src/cmd/compile/abi-internal.md
@@ -730,6 +730,57 @@ The floating point status and control register (FPSCR) is initialized
to 0 by the kernel at startup of the Go program and not changed by
the Go generated code.
+### riscv64 architecture
+
+The riscv64 architecture uses X10 – X17, X8, X9, X18 – X23 for integer arguments
+and results.
+
+It uses F10 – F17, F8, F9, F18 – F23 for floating-point arguments and results.
+
+Special-purpose registers used within Go generated code and Go
+assembly code are as follows:
+
+| Register | Call meaning | Return meaning | Body meaning |
+| --- | --- | --- | --- |
+| X0 | Zero value | Same | Same |
+| X1 | Link register | Link register | Scratch |
+| X2 | Stack pointer | Same | Same |
+| X3 | Global pointer | Same | Used by dynamic linker |
+| X4 | TLS (thread pointer) | TLS | Scratch |
+| X24,X25 | Scratch | Scratch | Used by duffcopy, duffzero |
+| X26 | Closure context pointer | Scratch | Scratch |
+| X27 | Current goroutine | Same | Same |
+| X31 | Scratch | Scratch | Scratch |
+
+*Rationale*: These register meanings are compatible with Go’s
+stack-based calling convention. Context register X20 will change to X26,
+duffcopy, duffzero register will change to X24, X25 before this register ABI been adopted.
+X10 – X17, X8, X9, X18 – X23, is the same order as A0 – A7, S0 – S7 in platform ABI.
+F10 – F17, F8, F9, F18 – F23, is the same order as FA0 – FA7, FS0 – FS7 in platform ABI.
+X8 – X23, F8 – F15 are used for compressed instruction (RVC) which will benefit code size in the future.
+
+#### Stack layout
+
+The stack pointer, X2, grows down and is aligned to 8 bytes.
+
+A function's stack frame, after the frame is created, is laid out as
+follows:
+
+ +------------------------------+
+ | ... locals ... |
+ | ... outgoing arguments ... |
+ | return PC | ← X2 points to
+ +------------------------------+ ↓ lower addresses
+
+The "return PC" is loaded to the link register, X1, as part of the
+riscv64 `CALL` operation.
+
+#### Flags
+
+The riscv64 has Zicsr extension for control and status register (CSR) and
+treated as scratch register.
+All bits in CSR are system flags and are not modified by Go.
+
## Future directions
### Spill path improvements
From c6d9b38dd82fea8775f1dff9a4a70a017463035d Mon Sep 17 00:00:00 2001
From: eric fang
Date: Tue, 18 Jan 2022 02:52:08 +0000
Subject: [PATCH 052/276] cmd/internal/obj/arm64: optimize function
prologue/epilogue with STP/LDP
In function prologue and epilogue, we save and restore FP and LR
registers, and adjust RSP. The current instruction sequence is as
follow.
For frame size <= 240B,
prologue:
MOVD.W R30, -offset(RSP)
MOVD R29, -8(RSP)
epilogue:
MOVD -8(RSP), R29
MOVD.P offset(RSP), R30
For frame size > 240B,
prologue:
SUB $offset, RSP, R27
MOVD R30, (R27)
MOVD R27, RSP
MOVD R29, -8(RSP)
epilogue:
MOVD -8(RSP), R29
MOVD (RSP), R30
ADD $offset, RSP
Each sequence uses two load or store instructions, actually we can load
or store two registers with one LDP or STP instruction. This CL changes
the sequences as follow.
For frame size <= 496B,
prologue:
STP (R29, R30), -(offset+8)(RSP)
SUB $offset, RSP, RSP
epilogue:
LDP -8(RSP), (R29, R30)
ADD $offset, RSP, RSP
For frame size > 496B,
prologue:
SUB $offset, RSP, R20
STP (R29, R30), -8(R20)
MOVD R20, RSP
epilogue:
LDP -8(RSP), (R29, R30)
ADD $offset, RSP, RSP
Change-Id: Ia58af85fc81cce9b7c393dc38df43bffb203baad
Reviewed-on: https://go-review.googlesource.com/c/go/+/379075
Reviewed-by: Cherry Mui
Trust: Eric Fang
Run-TryBot: Eric Fang
---
src/cmd/internal/obj/arm64/obj7.go | 196 +++++++++++++++--------------
1 file changed, 104 insertions(+), 92 deletions(-)
diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go
index 2bbc7e37b0..43f7b16d6e 100644
--- a/src/cmd/internal/obj/arm64/obj7.go
+++ b/src/cmd/internal/obj/arm64/obj7.go
@@ -622,92 +622,124 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
var prologueEnd *obj.Prog
aoffset := c.autosize
- if aoffset > 0xF0 {
- aoffset = 0xF0
+ if aoffset > 0x1f0 {
+ // LDP offset variant range is -512 to 504, SP should be 16-byte aligned,
+ // so the maximum aoffset value is 496.
+ aoffset = 0x1f0
}
// Frame is non-empty. Make sure to save link register, even if
// it is a leaf function, so that traceback works.
q = p
if c.autosize > aoffset {
- // Frame size is too large for a MOVD.W instruction.
- // Store link register before decrementing SP, so if a signal comes
- // during the execution of the function prologue, the traceback
- // code will not see a half-updated stack frame.
- // This sequence is not async preemptible, as if we open a frame
- // at the current SP, it will clobber the saved LR.
- q = c.ctxt.StartUnsafePoint(q, c.newprog)
-
- q = obj.Appendp(q, c.newprog)
- q.Pos = p.Pos
- q.As = ASUB
- q.From.Type = obj.TYPE_CONST
- q.From.Offset = int64(c.autosize)
- q.Reg = REGSP
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REGTMP
-
- prologueEnd = q
-
- q = obj.Appendp(q, c.newprog)
- q.Pos = p.Pos
- q.As = AMOVD
- q.From.Type = obj.TYPE_REG
- q.From.Reg = REGLINK
- q.To.Type = obj.TYPE_MEM
- q.To.Reg = REGTMP
+ // Frame size is too large for a STP instruction. Store the frame pointer
+ // register and link register before decrementing SP, so if a signal comes
+ // during the execution of the function prologue, the traceback code will
+ // not see a half-updated stack frame.
+ // SUB $autosize, RSP, R20
q1 = obj.Appendp(q, c.newprog)
q1.Pos = p.Pos
+ q1.As = ASUB
+ q1.From.Type = obj.TYPE_CONST
+ q1.From.Offset = int64(c.autosize)
+ q1.Reg = REGSP
+ q1.To.Type = obj.TYPE_REG
+ q1.To.Reg = REG_R20
+
+ prologueEnd = q1
+
+ // STP (R29, R30), -8(R20)
+ q1 = obj.Appendp(q1, c.newprog)
+ q1.Pos = p.Pos
+ q1.As = ASTP
+ q1.From.Type = obj.TYPE_REGREG
+ q1.From.Reg = REGFP
+ q1.From.Offset = REGLINK
+ q1.To.Type = obj.TYPE_MEM
+ q1.To.Reg = REG_R20
+ q1.To.Offset = -8
+
+ // This is not async preemptible, as if we open a frame
+ // at the current SP, it will clobber the saved LR.
+ q1 = c.ctxt.StartUnsafePoint(q1, c.newprog)
+
+ // MOVD R20, RSP
+ q1 = obj.Appendp(q1, c.newprog)
+ q1.Pos = p.Pos
q1.As = AMOVD
q1.From.Type = obj.TYPE_REG
- q1.From.Reg = REGTMP
+ q1.From.Reg = REG_R20
q1.To.Type = obj.TYPE_REG
q1.To.Reg = REGSP
q1.Spadj = c.autosize
+ q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1)
+
if buildcfg.GOOS == "ios" {
// iOS does not support SA_ONSTACK. We will run the signal handler
// on the G stack. If we write below SP, it may be clobbered by
- // the signal handler. So we save LR after decrementing SP.
+ // the signal handler. So we save FP and LR after decrementing SP.
+ // STP (R29, R30), -8(RSP)
q1 = obj.Appendp(q1, c.newprog)
q1.Pos = p.Pos
- q1.As = AMOVD
- q1.From.Type = obj.TYPE_REG
- q1.From.Reg = REGLINK
+ q1.As = ASTP
+ q1.From.Type = obj.TYPE_REGREG
+ q1.From.Reg = REGFP
+ q1.From.Offset = REGLINK
q1.To.Type = obj.TYPE_MEM
q1.To.Reg = REGSP
+ q1.To.Offset = -8
}
-
- q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1)
} else {
- // small frame, update SP and save LR in a single MOVD.W instruction
+ // small frame, save FP and LR with one STP instruction, then update SP.
+ // Store first, so if a signal comes during the execution of the function
+ // prologue, the traceback code will not see a half-updated stack frame.
+ // STP (R29, R30), -aoffset-8(RSP)
q1 = obj.Appendp(q, c.newprog)
- q1.As = AMOVD
+ q1.As = ASTP
q1.Pos = p.Pos
- q1.From.Type = obj.TYPE_REG
- q1.From.Reg = REGLINK
+ q1.From.Type = obj.TYPE_REGREG
+ q1.From.Reg = REGFP
+ q1.From.Offset = REGLINK
q1.To.Type = obj.TYPE_MEM
- q1.Scond = C_XPRE
- q1.To.Offset = int64(-aoffset)
+ q1.To.Offset = int64(-aoffset - 8)
+ q1.To.Reg = REGSP
+
+ prologueEnd = q1
+
+ q1 = c.ctxt.StartUnsafePoint(q1, c.newprog)
+ // This instruction is not async preemptible, see the above comment.
+ // SUB $aoffset, RSP, RSP
+ q1 = obj.Appendp(q1, c.newprog)
+ q1.Pos = p.Pos
+ q1.As = ASUB
+ q1.From.Type = obj.TYPE_CONST
+ q1.From.Offset = int64(aoffset)
+ q1.Reg = REGSP
+ q1.To.Type = obj.TYPE_REG
q1.To.Reg = REGSP
q1.Spadj = aoffset
- prologueEnd = q1
+ q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1)
+
+ if buildcfg.GOOS == "ios" {
+ // See the above comment.
+ // STP (R29, R30), -8(RSP)
+ q1 = obj.Appendp(q1, c.newprog)
+ q1.As = ASTP
+ q1.Pos = p.Pos
+ q1.From.Type = obj.TYPE_REGREG
+ q1.From.Reg = REGFP
+ q1.From.Offset = REGLINK
+ q1.To.Type = obj.TYPE_MEM
+ q1.To.Offset = int64(-8)
+ q1.To.Reg = REGSP
+ }
}
prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd)
- // Frame pointer.
- q1 = obj.Appendp(q1, c.newprog)
- q1.Pos = p.Pos
- q1.As = AMOVD
- q1.From.Type = obj.TYPE_REG
- q1.From.Reg = REGFP
- q1.To.Type = obj.TYPE_MEM
- q1.To.Reg = REGSP
- q1.To.Offset = -8
-
q1 = obj.Appendp(q1, c.newprog)
q1.Pos = p.Pos
q1.As = ASUB
@@ -850,48 +882,28 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.To.Reg = REGFP
}
} else {
- /* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
-
- // Frame pointer.
- p.As = AMOVD
- p.From.Type = obj.TYPE_MEM
- p.From.Reg = REGSP
- p.From.Offset = -8
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REGFP
- p = obj.Appendp(p, c.newprog)
-
aoffset := c.autosize
+ // LDP -8(RSP), (R29, R30)
+ p.As = ALDP
+ p.From.Type = obj.TYPE_MEM
+ p.From.Offset = -8
+ p.From.Reg = REGSP
+ p.To.Type = obj.TYPE_REGREG
+ p.To.Reg = REGFP
+ p.To.Offset = REGLINK
- if aoffset <= 0xF0 {
- p.As = AMOVD
- p.From.Type = obj.TYPE_MEM
- p.Scond = C_XPOST
- p.From.Offset = int64(aoffset)
- p.From.Reg = REGSP
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REGLINK
- p.Spadj = -aoffset
- } else {
- p.As = AMOVD
- p.From.Type = obj.TYPE_MEM
- p.From.Offset = 0
- p.From.Reg = REGSP
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REGLINK
-
- q = newprog()
- q.As = AADD
- q.From.Type = obj.TYPE_CONST
- q.From.Offset = int64(aoffset)
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REGSP
- q.Link = p.Link
- q.Spadj = int32(-q.From.Offset)
- q.Pos = p.Pos
- p.Link = q
- p = q
- }
+ // ADD $aoffset, RSP, RSP
+ q = newprog()
+ q.As = AADD
+ q.From.Type = obj.TYPE_CONST
+ q.From.Offset = int64(aoffset)
+ q.To.Type = obj.TYPE_REG
+ q.To.Reg = REGSP
+ q.Spadj = -aoffset
+ q.Pos = p.Pos
+ q.Link = p.Link
+ p.Link = q
+ p = q
}
// If enabled, this code emits 'MOV PC, R27' before every 'MOV LR, PC',
From 7160e3252991d9462ee3a155b5504c564a6cffe5 Mon Sep 17 00:00:00 2001
From: Matthew Dempsky
Date: Tue, 8 Mar 2022 14:59:32 -0800
Subject: [PATCH 053/276] cmd/compile: mark instantiated generic functions as
DUPOK
Unified IR wasn't marking instantiated generic functions as DUPOK,
even though they can appear in multiple compilation units, which
evidently interfered with cmd/link's dead code elimination logic.
Manually confirmed to fix the issue, but non-trivial to test within
$GOROOT/test currently, because it's only reproducible when
cmd/compile is invoked with -p. @rsc is currently investigating
updating test/run.go appropriately, after which I'll revisit writing a
test case.
Fixes #51519.
Change-Id: I74a79ed0ca15b25b826e419714af5ceb6e567012
Reviewed-on: https://go-review.googlesource.com/c/go/+/390956
Trust: Matthew Dempsky
Run-TryBot: Matthew Dempsky
TryBot-Result: Gopher Robot
Reviewed-by: Cherry Mui
---
src/cmd/compile/internal/noder/reader.go | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index 004630236d..73e4ddbbed 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -644,6 +644,10 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node
name.Func = ir.NewFunc(r.pos())
name.Func.Nname = name
+ if r.hasTypeParams() {
+ name.Func.SetDupok(true)
+ }
+
rext.funcExt(name)
return name
@@ -790,6 +794,10 @@ func (r *reader) method(rext *reader) *types.Field {
name.Func = ir.NewFunc(r.pos())
name.Func.Nname = name
+ if r.hasTypeParams() {
+ name.Func.SetDupok(true)
+ }
+
rext.funcExt(name)
meth := types.NewField(name.Func.Pos(), sym, typ)
From 0d33a9967540fe06f5ce7b14790e9be8da576936 Mon Sep 17 00:00:00 2001
From: Rhys Hiltner
Date: Wed, 9 Mar 2022 07:56:04 -0800
Subject: [PATCH 054/276] runtime/pprof: fix pcDeck's frame indexing
When building the inlining deck, correctly identify which is the last
frame in the deck. Otherwise, when some forms of inlining cause a PC to
expand to multiple frames, the length of the deck's two slices will
diverge.
Fixes #51567
Change-Id: I24e7ba32cb16b167f4307178b3f03c29e5362c4b
Reviewed-on: https://go-review.googlesource.com/c/go/+/391134
Reviewed-by: Michael Pratt
Trust: Than McIntosh
---
src/runtime/pprof/proto.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go
index 215bd0bf96..68dac42d20 100644
--- a/src/runtime/pprof/proto.go
+++ b/src/runtime/pprof/proto.go
@@ -530,7 +530,7 @@ func (d *pcDeck) reset() {
// since the stack trace is already fully expanded) and the symbolizeResult
// to the deck. If it fails the caller needs to flush the deck and retry.
func (d *pcDeck) tryAdd(pc uintptr, frames []runtime.Frame, symbolizeResult symbolizeFlag) (success bool) {
- if existing := len(d.pcs); existing > 0 {
+ if existing := len(d.frames); existing > 0 {
// 'd.frames' are all expanded from one 'pc' and represent all
// inlined functions so we check only the last one.
newFrame := frames[0]
From 7026eeb8cfdc5801adddaaa678fb6495a998db0e Mon Sep 17 00:00:00 2001
From: Mark Pulford
Date: Sun, 27 Feb 2022 23:22:22 +1030
Subject: [PATCH 055/276] cmd/go: fix buildvcs when using older git versions
Git versions before v2.10.0 do not support --no-show-signature.
Using "-c" allows Git to ignore the configuration option if it does not
exist.
Fixes #51253
Change-Id: I2b1adaca0eb18ae31f2e1119e354ce515b00cfc2
Reviewed-on: https://go-review.googlesource.com/c/go/+/388194
Trust: Dmitri Shuralyov
Run-TryBot: Dmitri Shuralyov
TryBot-Result: Gopher Robot
Reviewed-by: Bryan Mills
---
src/cmd/go/internal/vcs/vcs.go | 2 +-
src/cmd/go/testdata/script/version_buildvcs_git.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go
index fd521b2eb1..2acabf7aaf 100644
--- a/src/cmd/go/internal/vcs/vcs.go
+++ b/src/cmd/go/internal/vcs/vcs.go
@@ -312,7 +312,7 @@ func gitStatus(vcsGit *Cmd, rootDir string) (Status, error) {
// uncommitted files and skip tagging revision / committime.
var rev string
var commitTime time.Time
- out, err = vcsGit.runOutputVerboseOnly(rootDir, "show -s --no-show-signature --format=%H:%ct")
+ out, err = vcsGit.runOutputVerboseOnly(rootDir, "-c log.showsignature=false show -s --format=%H:%ct")
if err != nil && !uncommitted {
return Status{}, err
} else if err == nil {
diff --git a/src/cmd/go/testdata/script/version_buildvcs_git.txt b/src/cmd/go/testdata/script/version_buildvcs_git.txt
index 86d1de06df..44706870e2 100644
--- a/src/cmd/go/testdata/script/version_buildvcs_git.txt
+++ b/src/cmd/go/testdata/script/version_buildvcs_git.txt
@@ -111,7 +111,7 @@ rm $GOBIN/d$GOEXE
go list -x ./...
stdout -count=3 '^example.com'
stderr -count=1 '^git status'
-stderr -count=1 '^git show'
+stderr -count=1 '^git -c log.showsignature=false show'
-- $WORK/fakebin/git --
#!/bin/sh
From b8248fab897da9bee2211a98df1656883ccecd6d Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Wed, 9 Mar 2022 10:01:24 -0800
Subject: [PATCH 056/276] go/types, types2: disable field accesses through type
parameters
This is a feature that is not understood well enough and may have
subtle repercussions impacting future changes. Disable for Go 1.18.
The actual change is trivial: disable a branch through a flag.
The remaining changes are adjustments to tests.
Fixes #51576.
Change-Id: Ib77b038b846711a808315a8889b3904e72367bce
Reviewed-on: https://go-review.googlesource.com/c/go/+/391135
Trust: Robert Griesemer
Run-TryBot: Robert Griesemer
Reviewed-by: Robert Findley
TryBot-Result: Gopher Robot
---
src/cmd/compile/internal/types2/lookup.go | 3 +-
.../types2/testdata/fixedbugs/issue50417.go2 | 24 +++++++-----
.../types2/testdata/fixedbugs/issue50782.go2 | 13 +++++--
src/go/types/lookup.go | 3 +-
.../types/testdata/fixedbugs/issue50417.go2 | 24 +++++++-----
.../types/testdata/fixedbugs/issue50782.go2 | 13 +++++--
test/typeparam/absdiff2.go | 32 +++++++++++-----
test/typeparam/absdiffimp2.dir/a.go | 32 +++++++++++-----
test/typeparam/issue50417.go | 6 +++
test/typeparam/issue50417b.go | 8 ++++
test/typeparam/issue50690a.go | 37 +++++++++++++------
test/typeparam/issue50690b.go | 26 +++++++++----
test/typeparam/issue50690c.go | 30 +++++++++++----
13 files changed, 177 insertions(+), 74 deletions(-)
diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index 0a2d2a5790..0832877226 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -70,7 +70,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
// see if there is a matching field (but not a method, those need to be declared
// explicitly in the constraint). If the constraint is a named pointer type (see
// above), we are ok here because only fields are accepted as results.
- if obj == nil && isTypeParam(T) {
+ const enableTParamFieldLookup = false // see issue #51576
+ if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
if t := coreType(T); t != nil {
obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
if _, ok := obj.(*Var); !ok {
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2
index 50487fa2ff..2caef1b986 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
package p
type Sf struct {
@@ -9,13 +13,13 @@ type Sf struct {
}
func f0[P Sf](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
}
func f0t[P ~struct{f int}](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
}
var _ = f0[Sf]
@@ -25,8 +29,8 @@ var _ = f0[Sm /* ERROR does not implement */ ]
var _ = f0t[Sm /* ERROR does not implement */ ]
func f1[P interface{ Sf; m() }](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
p.m()
}
@@ -44,8 +48,8 @@ type Sfm struct {
func (Sfm) m() {}
func f2[P interface{ Sfm; m() }](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
p.m()
}
@@ -56,8 +60,8 @@ var _ = f2[Sfm]
type PSfm *Sfm
func f3[P interface{ PSfm }](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
p.m /* ERROR type P has no field or method m */ ()
}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50782.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50782.go2
index 8f41b84163..fd1ab11b8c 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50782.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50782.go2
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
package p
// The first example from the issue.
@@ -18,9 +22,12 @@ type numericAbs[T Numeric] interface {
// AbsDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a, b T) T {
- // TODO: the error below should probably be positioned on the '-'.
- d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
- return d.Abs()
+ // Field accesses are not permitted for now. Keep an error so
+ // we can find and fix this code once the situation changes.
+ return a.Value // ERROR a\.Value undefined
+ // TODO: The error below should probably be positioned on the '-'.
+ // d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
+ // return d.Abs()
}
// The second example from the issue.
diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go
index 501c230357..335fada7b7 100644
--- a/src/go/types/lookup.go
+++ b/src/go/types/lookup.go
@@ -70,7 +70,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
// see if there is a matching field (but not a method, those need to be declared
// explicitly in the constraint). If the constraint is a named pointer type (see
// above), we are ok here because only fields are accepted as results.
- if obj == nil && isTypeParam(T) {
+ const enableTParamFieldLookup = false // see issue #51576
+ if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
if t := coreType(T); t != nil {
obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
if _, ok := obj.(*Var); !ok {
diff --git a/src/go/types/testdata/fixedbugs/issue50417.go2 b/src/go/types/testdata/fixedbugs/issue50417.go2
index 50487fa2ff..2caef1b986 100644
--- a/src/go/types/testdata/fixedbugs/issue50417.go2
+++ b/src/go/types/testdata/fixedbugs/issue50417.go2
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
package p
type Sf struct {
@@ -9,13 +13,13 @@ type Sf struct {
}
func f0[P Sf](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
}
func f0t[P ~struct{f int}](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
}
var _ = f0[Sf]
@@ -25,8 +29,8 @@ var _ = f0[Sm /* ERROR does not implement */ ]
var _ = f0t[Sm /* ERROR does not implement */ ]
func f1[P interface{ Sf; m() }](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
p.m()
}
@@ -44,8 +48,8 @@ type Sfm struct {
func (Sfm) m() {}
func f2[P interface{ Sfm; m() }](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
p.m()
}
@@ -56,8 +60,8 @@ var _ = f2[Sfm]
type PSfm *Sfm
func f3[P interface{ PSfm }](p P) {
- _ = p.f
- p.f = 0
+ _ = p.f // ERROR p\.f undefined
+ p.f /* ERROR p\.f undefined */ = 0
p.m /* ERROR type P has no field or method m */ ()
}
diff --git a/src/go/types/testdata/fixedbugs/issue50782.go2 b/src/go/types/testdata/fixedbugs/issue50782.go2
index 8f41b84163..fd1ab11b8c 100644
--- a/src/go/types/testdata/fixedbugs/issue50782.go2
+++ b/src/go/types/testdata/fixedbugs/issue50782.go2
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
package p
// The first example from the issue.
@@ -18,9 +22,12 @@ type numericAbs[T Numeric] interface {
// AbsDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a, b T) T {
- // TODO: the error below should probably be positioned on the '-'.
- d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
- return d.Abs()
+ // Field accesses are not permitted for now. Keep an error so
+ // we can find and fix this code once the situation changes.
+ return a.Value // ERROR a\.Value undefined
+ // TODO: The error below should probably be positioned on the '-'.
+ // d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
+ // return d.Abs()
}
// The second example from the issue.
diff --git a/test/typeparam/absdiff2.go b/test/typeparam/absdiff2.go
index f3e058d468..87a1ec6de1 100644
--- a/test/typeparam/absdiff2.go
+++ b/test/typeparam/absdiff2.go
@@ -23,15 +23,16 @@ type Numeric interface {
// numericAbs matches a struct containing a numeric type that has an Abs method.
type numericAbs[T Numeric] interface {
- ~struct{ Value T }
+ ~struct{ Value_ T }
Abs() T
+ Value() T
}
// absDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
- d := a.Value - b.Value
- dt := U{Value: d}
+ d := a.Value() - b.Value()
+ dt := U{Value_: d}
return dt.Abs()
}
@@ -50,20 +51,29 @@ type Complex interface {
// orderedAbs is a helper type that defines an Abs method for
// a struct containing an ordered numeric type.
type orderedAbs[T orderedNumeric] struct {
- Value T
+ Value_ T
}
func (a orderedAbs[T]) Abs() T {
- if a.Value < 0 {
- return -a.Value
+ if a.Value_ < 0 {
+ return -a.Value_
}
- return a.Value
+ return a.Value_
+}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor method instead.
+
+func (a orderedAbs[T]) Value() T {
+ return a.Value_
}
// complexAbs is a helper type that defines an Abs method for
// a struct containing a complex type.
type complexAbs[T Complex] struct {
- Value T
+ Value_ T
}
func realimag(x any) (re, im float64) {
@@ -82,13 +92,17 @@ func realimag(x any) (re, im float64) {
func (a complexAbs[T]) Abs() T {
// TODO use direct conversion instead of realimag once #50937 is fixed
- r, i := realimag(a.Value)
+ r, i := realimag(a.Value_)
// r := float64(real(a.Value))
// i := float64(imag(a.Value))
d := math.Sqrt(r*r + i*i)
return T(complex(d, 0))
}
+func (a complexAbs[T]) Value() T {
+ return a.Value_
+}
+
// OrderedAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of an ordered type.
func OrderedAbsDifference[T orderedNumeric](a, b T) T {
diff --git a/test/typeparam/absdiffimp2.dir/a.go b/test/typeparam/absdiffimp2.dir/a.go
index 43493e1430..dc64f2dcbe 100644
--- a/test/typeparam/absdiffimp2.dir/a.go
+++ b/test/typeparam/absdiffimp2.dir/a.go
@@ -17,15 +17,16 @@ type Numeric interface {
// numericAbs matches a struct containing a numeric type that has an Abs method.
type numericAbs[T Numeric] interface {
- ~struct{ Value T }
+ ~struct{ Value_ T }
Abs() T
+ Value() T
}
// absDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
- d := a.Value - b.Value
- dt := U{Value: d}
+ d := a.Value() - b.Value()
+ dt := U{Value_: d}
return dt.Abs()
}
@@ -44,20 +45,29 @@ type Complex interface {
// orderedAbs is a helper type that defines an Abs method for
// a struct containing an ordered numeric type.
type orderedAbs[T orderedNumeric] struct {
- Value T
+ Value_ T
}
func (a orderedAbs[T]) Abs() T {
- if a.Value < 0 {
- return -a.Value
+ if a.Value_ < 0 {
+ return -a.Value_
}
- return a.Value
+ return a.Value_
+}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor method instead.
+
+func (a orderedAbs[T]) Value() T {
+ return a.Value_
}
// complexAbs is a helper type that defines an Abs method for
// a struct containing a complex type.
type complexAbs[T Complex] struct {
- Value T
+ Value_ T
}
func realimag(x any) (re, im float64) {
@@ -76,13 +86,17 @@ func realimag(x any) (re, im float64) {
func (a complexAbs[T]) Abs() T {
// TODO use direct conversion instead of realimag once #50937 is fixed
- r, i := realimag(a.Value)
+ r, i := realimag(a.Value_)
// r := float64(real(a.Value))
// i := float64(imag(a.Value))
d := math.Sqrt(r*r + i*i)
return T(complex(d, 0))
}
+func (a complexAbs[T]) Value() T {
+ return a.Value_
+}
+
// OrderedAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of an ordered type.
func OrderedAbsDifference[T orderedNumeric](a, b T) T {
diff --git a/test/typeparam/issue50417.go b/test/typeparam/issue50417.go
index 3d5f2f2538..b32e270bdf 100644
--- a/test/typeparam/issue50417.go
+++ b/test/typeparam/issue50417.go
@@ -8,6 +8,11 @@ package main
func main() {}
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
+/*
type Sf struct {
f int
}
@@ -138,3 +143,4 @@ func f8[P Int4](p P) {
}
var _ = f8[*Sf]
+*/
diff --git a/test/typeparam/issue50417b.go b/test/typeparam/issue50417b.go
index 8c13a4ee36..1c803b09bd 100644
--- a/test/typeparam/issue50417b.go
+++ b/test/typeparam/issue50417b.go
@@ -6,6 +6,13 @@
package main
+func main() {}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+
+/*
import "fmt"
type MyStruct struct {
@@ -48,3 +55,4 @@ func main() {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
}
+*/
diff --git a/test/typeparam/issue50690a.go b/test/typeparam/issue50690a.go
index 35e8c20e07..6691af0a07 100644
--- a/test/typeparam/issue50690a.go
+++ b/test/typeparam/issue50690a.go
@@ -29,34 +29,47 @@ func Sum[T Numeric](args ...T) T {
// Ledger is an identifiable, financial record.
type Ledger[T ~string, K Numeric] struct {
-
// ID identifies the ledger.
- ID T
+ ID_ T
// Amounts is a list of monies associated with this ledger.
- Amounts []K
+ Amounts_ []K
// SumFn is a function that can be used to sum the amounts
// in this ledger.
- SumFn func(...K) K
+ SumFn_ func(...K) K
}
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor methods instead.
+
+func (l Ledger[T, _]) ID() T { return l.ID_ }
+func (l Ledger[_, K]) Amounts() []K { return l.Amounts_ }
+func (l Ledger[_, K]) SumFn() func(...K) K { return l.SumFn_ }
+
func PrintLedger[
T ~string,
K Numeric,
- L ~struct {
- ID T
- Amounts []K
- SumFn func(...K) K
+ L interface {
+ ~struct {
+ ID_ T
+ Amounts_ []K
+ SumFn_ func(...K) K
+ }
+ ID() T
+ Amounts() []K
+ SumFn() func(...K) K
},
](l L) {
- fmt.Printf("%s has a sum of %v\n", l.ID, l.SumFn(l.Amounts...))
+ fmt.Printf("%s has a sum of %v\n", l.ID(), l.SumFn()(l.Amounts()...))
}
func main() {
PrintLedger(Ledger[string, int]{
- ID: "fake",
- Amounts: []int{1, 2, 3},
- SumFn: Sum[int],
+ ID_: "fake",
+ Amounts_: []int{1, 2, 3},
+ SumFn_: Sum[int],
})
}
diff --git a/test/typeparam/issue50690b.go b/test/typeparam/issue50690b.go
index 13e725ae0a..09c84e089d 100644
--- a/test/typeparam/issue50690b.go
+++ b/test/typeparam/issue50690b.go
@@ -18,24 +18,34 @@ func Print[T ~string](s T) {
fmt.Println(s)
}
-func PrintWithPrinter[T ~string, S ~struct {
- ID T
- PrintFn func(T)
+func PrintWithPrinter[T ~string, S interface {
+ ~struct {
+ ID T
+ PrintFn_ func(T)
+ }
+ PrintFn() func(T)
}](message T, obj S) {
- obj.PrintFn(message)
+ obj.PrintFn()(message)
}
type PrintShop[T ~string] struct {
- ID T
- PrintFn func(T)
+ ID T
+ PrintFn_ func(T)
}
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor method instead.
+
+func (s PrintShop[T]) PrintFn() func(T) { return s.PrintFn_ }
+
func main() {
PrintWithPrinter(
"Hello, world.",
PrintShop[string]{
- ID: "fake",
- PrintFn: Print[string],
+ ID: "fake",
+ PrintFn_: Print[string],
},
)
}
diff --git a/test/typeparam/issue50690c.go b/test/typeparam/issue50690c.go
index 75e772cccd..2db1487ecb 100644
--- a/test/typeparam/issue50690c.go
+++ b/test/typeparam/issue50690c.go
@@ -18,19 +18,33 @@ func Print[T ~string](s T) {
fmt.Println(s)
}
-func PrintWithPrinter[T ~string, S struct {
- ID T
- PrintFn func(T)
+func PrintWithPrinter[T ~string, S interface {
+ ~struct {
+ ID T
+ PrintFn_ func(T)
+ }
+ PrintFn() func(T)
}](message T, obj S) {
- obj.PrintFn(message)
+ obj.PrintFn()(message)
}
func main() {
PrintWithPrinter(
"Hello, world.",
- struct {
- ID string
- PrintFn func(string)
- }{ID: "fake", PrintFn: Print[string]},
+ StructWithPrinter{ID: "fake", PrintFn_: Print[string]},
)
}
+
+type StructWithPrinter struct {
+ ID string
+ PrintFn_ func(string)
+}
+
+// Field accesses through type parameters are disabled
+// until we have a more thorough understanding of the
+// implications on the spec. See issue #51576.
+// Use accessor method instead.
+
+func (s StructWithPrinter) PrintFn() func(string) {
+ return s.PrintFn_
+}
From a987aaf5f7a5f64215ff75ac93a2c1b39967a8c9 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Tue, 8 Mar 2022 18:16:35 -0500
Subject: [PATCH 057/276] cmd/compile: require -p flag
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The -p flag specifies the import path of the package being compiled.
This CL makes it required when invoking the compiler and
adjusts tests that invoke the compiler directly to conform to this
new requirement. The go command already passes the flag, so it
is unmodified in this CL. It is expected that any other Go build systems
also already pass -p, or else they will need to arrange to do so before
updating to Go 1.19. Of particular note, Bazel already does for rules
with an importpath= attribute, which includes all Gazelle-generated rules.
There is more cleanup possible now in cmd/compile, cmd/link,
and other consumers of Go object files, but that is left to future CLs.
Additional historical background follows but can be ignored.
Long ago, before the go command, or modules, or any kind of
versioning, symbols in Go archive files were named using just the
package name, so that for example func F in math/rand and func F in
crypto/rand would both be the object file symbol 'rand.F'. This led to
collisions even in small source trees, which made certain packages
unusable in the presence of other packages and generally was a problem
for Go's goal of scaling to very large source trees.
Fixing this problem required changing from package names to import
paths in symbol names, which was mostly straightforward. One wrinkle,
though, is that the compiler did not know the import path of the
package being compiled; it only knew the package name. At the time,
there was no go command, just Makefiles that people had invoking 6g
(now “go tool compile”) and then copying the resulting object file to
an importable location. That is, everyone had a custom build setup for
Go, because there was no standard one. So it was not particularly
attractive to change how the compiler was invoked, since that would
break approximately every Go user at the time. Instead, we arranged
for the compiler to emit, and other tools reading object files to
recognize, a special import path (the empty string, it turned out)
denoting “the import path of this object file”. This worked well
enough at the time and maintained complete command-line compatibility
with existing Go usage.
The changes implementing this transition can be found by searching
the Git history for “package global name space”, which is what they
eliminated. In particular, CL 190076 (a6736fa4), CL 186263 (758f2bc5),
CL 193080 (1cecac81), CL 194053 (19126320), and CL 194071 (531e6b77)
did the bulk of this transformation in January 2010.
Later, in September 2011, we added the -p flag to the compiler for
diagnostic purposes. The problem was that it was easy to create import
cycles, especially in tests, and these could not be diagnosed until
link time. You'd really want the compiler to diagnose these, for
example if the compilation of package sort noticed it was importing a
package that itself imported "sort". But the compilation of package
sort didn't know its own import path, and so it could not tell whether
it had found itself as a transitive dependency. Adding the -p flag
solved this problem, and its use was optional, since the linker would
still diagnose the import cycle in builds that had not updated to
start passing -p. This was CL 4972057 (1e480cd1).
There was still no go command at this point, but when we introduced
the go command we made it pass -p, which it has for many years at this
point.
Over time, parts of the compiler began to depend on the presence of
the -p flag for various reasonable purposes. For example:
In CL 6497074 (041fc8bf; Oct 2012), the race detector used -p to
detect packages that should not have race annotations, such as
runtime/race and sync/atomic.
In CL 13367052 (7276c02b; Sep 2013), a bug fix used -p to detect the
compilation of package reflect.
In CL 30539 (8aadcc55; Oct 2016), the compiler started using -p to
identify package math, to be able to intrinsify calls to Sqrt inside
that package.
In CL 61019 (9daee931; Sep 2017), CL 71430 (2c1d2e06; Oct 2017), and
later related CLs, the compiler started using the -p value when
creating various DWARF debugging information.
In CL 174657 (cc5eaf93; May 2019), the compiler started writing
symbols without the magic empty string whenever -p was used, to reduce
the amount of work required in the linker.
In CL 179861 (dde7c770; Jun 2019), the compiler made the second
argument to //go:linkname optional when -p is used, because in that
case the compiler can derive an appropriate default.
There are more examples. Today it is impossible to compile the Go
standard library without using -p, and DWARF debug information is
incomplete without using -p.
All known Go build systems pass -p. In particular, the go command
does, which is what nearly all Go developers invoke to build Go code.
And Bazel does, for go_library rules that set the importpath
attribute, which is all rules generated by Gazelle.
Gccgo has an equivalent of -p and has required its use in order to
disambiguate packages with the same name but different import paths
since 2010.
On top of all this, various parts of code generation for generics
are made more complicated by needing to cope with the case where -p
is not specified, even though it's essentially always specified.
In summary, the current state is:
- Use of the -p flag with cmd/compile is required for building
the standard library, and for complete DWARF information,
and to enable certain linker speedups.
- The go command and Bazel, which we expect account for just
about 100% of Go builds, both invoke cmd/compile with -p.
- The code in cmd/compile to support builds without -p is
complex and has become more complex with generics, but it is
almost always dead code and therefore not worth maintaining.
- Gccgo already requires its equivalent of -p in any build
where two packages have the same name.
All this supports the change in this CL, which makes -p required
and adjusts tests that invoke cmd/compile to add -p appropriately.
Future CLs will be able to remove all the code dealing with the
possibility of -p not having been specified.
Change-Id: I6b95b9d4cffe59c7bac82eb273ef6c4a67bb0e43
Reviewed-on: https://go-review.googlesource.com/c/go/+/391014
Trust: Russ Cox
Run-TryBot: Russ Cox
TryBot-Result: Gopher Robot
Reviewed-by: Matthew Dempsky
---
src/cmd/compile/internal/base/flag.go | 4 ++
.../internal/importer/gcimporter_test.go | 2 +-
.../compile/internal/logopt/logopt_test.go | 6 +-
.../compile/internal/test/fixedbugs_test.go | 2 +-
src/cmd/compile/internal/test/lang_test.go | 2 +-
.../internal/test/reproduciblebuilds_test.go | 4 +-
src/cmd/internal/archive/archive_test.go | 4 +-
src/cmd/internal/obj/objfile_test.go | 2 +-
src/cmd/link/link_test.go | 14 ++--
src/cmd/objdump/objdump_test.go | 2 +-
src/cmd/pack/pack_test.go | 16 ++---
src/go/internal/gcimporter/gcimporter_test.go | 2 +-
src/internal/abi/abi_test.go | 2 +-
test/const7.go | 2 +-
test/fixedbugs/bug302.go | 4 +-
test/fixedbugs/bug369.go | 6 +-
test/fixedbugs/issue11771.go | 2 +-
test/fixedbugs/issue21317.go | 2 +-
test/fixedbugs/issue22660.go | 2 +-
test/fixedbugs/issue22662b.go | 2 +-
test/fixedbugs/issue26411.go | 2 +-
test/fixedbugs/issue30908.go | 3 +-
test/fixedbugs/issue9355.go | 2 +-
test/interface/embed1.dir/embed0.go | 5 +-
test/linkmain_run.go | 8 +--
test/linkname2.go | 21 ------
test/linkobj.go | 14 ++--
test/run.go | 69 +++++++++----------
test/sinit_run.go | 2 +-
29 files changed, 94 insertions(+), 114 deletions(-)
delete mode 100644 test/linkname2.go
diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go
index 6377091ce0..0b04f62e1c 100644
--- a/src/cmd/compile/internal/base/flag.go
+++ b/src/cmd/compile/internal/base/flag.go
@@ -201,6 +201,10 @@ func ParseFlags() {
Exit(2)
}
+ if *Flag.LowerP == "" {
+ log.Fatalf("-p is required")
+ }
+
if Flag.LowerO == "" {
p := flag.Arg(0)
if i := strings.LastIndex(p, "/"); i >= 0 {
diff --git a/src/cmd/compile/internal/importer/gcimporter_test.go b/src/cmd/compile/internal/importer/gcimporter_test.go
index 5d80db244b..cc804aabbc 100644
--- a/src/cmd/compile/internal/importer/gcimporter_test.go
+++ b/src/cmd/compile/internal/importer/gcimporter_test.go
@@ -38,7 +38,7 @@ func compile(t *testing.T, dirname, filename, outdirname string) string {
}
basename := filepath.Base(filename)
outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", outname, filename)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-o", outname, filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
diff --git a/src/cmd/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go
index 902cbc8091..8d07a49cc0 100644
--- a/src/cmd/compile/internal/logopt/logopt_test.go
+++ b/src/cmd/compile/internal/logopt/logopt_test.go
@@ -226,7 +226,7 @@ func s15a8(x *[15]int64) [15]int64 {
}
func testLogOpt(t *testing.T, flag, src, outfile string) (string, error) {
- run := []string{testenv.GoToolPath(t), "tool", "compile", flag, "-o", outfile, src}
+ run := []string{testenv.GoToolPath(t), "tool", "compile", "-p=p", flag, "-o", outfile, src}
t.Log(run)
cmd := exec.Command(run[0], run[1:]...)
out, err := cmd.CombinedOutput()
@@ -236,7 +236,7 @@ func testLogOpt(t *testing.T, flag, src, outfile string) (string, error) {
func testLogOptDir(t *testing.T, dir, flag, src, outfile string) (string, error) {
// Notice the specified import path "x"
- run := []string{testenv.GoToolPath(t), "tool", "compile", "-p", "x", flag, "-o", outfile, src}
+ run := []string{testenv.GoToolPath(t), "tool", "compile", "-p=x", flag, "-o", outfile, src}
t.Log(run)
cmd := exec.Command(run[0], run[1:]...)
cmd.Dir = dir
@@ -247,7 +247,7 @@ func testLogOptDir(t *testing.T, dir, flag, src, outfile string) (string, error)
func testCopy(t *testing.T, dir, goarch, goos, src, outfile string) (string, error) {
// Notice the specified import path "x"
- run := []string{testenv.GoToolPath(t), "tool", "compile", "-p", "x", "-json=0,file://log/opt", "-o", outfile, src}
+ run := []string{testenv.GoToolPath(t), "tool", "compile", "-p=x", "-json=0,file://log/opt", "-o", outfile, src}
t.Log(run)
cmd := exec.Command(run[0], run[1:]...)
cmd.Dir = dir
diff --git a/src/cmd/compile/internal/test/fixedbugs_test.go b/src/cmd/compile/internal/test/fixedbugs_test.go
index 376b45edfc..cd0d5fc353 100644
--- a/src/cmd/compile/internal/test/fixedbugs_test.go
+++ b/src/cmd/compile/internal/test/fixedbugs_test.go
@@ -72,7 +72,7 @@ func TestIssue16214(t *testing.T) {
t.Fatalf("could not write file: %v", err)
}
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-S", "-o", filepath.Join(dir, "out.o"), src)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=main", "-S", "-o", filepath.Join(dir, "out.o"), src)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("go tool compile: %v\n%s", err, out)
diff --git a/src/cmd/compile/internal/test/lang_test.go b/src/cmd/compile/internal/test/lang_test.go
index 67c1551292..66ab8401c6 100644
--- a/src/cmd/compile/internal/test/lang_test.go
+++ b/src/cmd/compile/internal/test/lang_test.go
@@ -56,7 +56,7 @@ func TestInvalidLang(t *testing.T) {
}
func testLang(t *testing.T, lang, src, outfile string) error {
- run := []string{testenv.GoToolPath(t), "tool", "compile", "-lang", lang, "-o", outfile, src}
+ run := []string{testenv.GoToolPath(t), "tool", "compile", "-p=p", "-lang", lang, "-o", outfile, src}
t.Log(run)
out, err := exec.Command(run[0], run[1:]...).CombinedOutput()
t.Logf("%s", out)
diff --git a/src/cmd/compile/internal/test/reproduciblebuilds_test.go b/src/cmd/compile/internal/test/reproduciblebuilds_test.go
index 4d84f9cdef..0a1a5e9b99 100644
--- a/src/cmd/compile/internal/test/reproduciblebuilds_test.go
+++ b/src/cmd/compile/internal/test/reproduciblebuilds_test.go
@@ -41,7 +41,7 @@ func TestReproducibleBuilds(t *testing.T) {
for i := 0; i < iters; i++ {
// Note: use -c 2 to expose any nondeterminism which is the result
// of the runtime scheduler.
- out, err := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-c", "2", "-o", tmp.Name(), filepath.Join("testdata", "reproducible", test)).CombinedOutput()
+ out, err := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-c", "2", "-o", tmp.Name(), filepath.Join("testdata", "reproducible", test)).CombinedOutput()
if err != nil {
t.Fatalf("failed to compile: %v\n%s", err, out)
}
@@ -89,7 +89,7 @@ func TestIssue38068(t *testing.T) {
s := &scenarios[i]
s.libpath = filepath.Join(tmpdir, s.tag+".a")
// Note: use of "-p" required in order for DWARF to be generated.
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-trimpath", "-p=issue38068", "-buildid=", s.args, "-o", s.libpath, src)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=issue38068", "-buildid=", s.args, "-o", s.libpath, src)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("%v: %v:\n%s", cmd.Args, err, out)
diff --git a/src/cmd/internal/archive/archive_test.go b/src/cmd/internal/archive/archive_test.go
index c284a9cf0d..9573495dec 100644
--- a/src/cmd/internal/archive/archive_test.go
+++ b/src/cmd/internal/archive/archive_test.go
@@ -109,11 +109,11 @@ func buildGoobj() error {
go1src := filepath.Join("testdata", "go1.go")
go2src := filepath.Join("testdata", "go2.go")
- out, err := exec.Command(gotool, "tool", "compile", "-o", go1obj, go1src).CombinedOutput()
+ out, err := exec.Command(gotool, "tool", "compile", "-p=p", "-o", go1obj, go1src).CombinedOutput()
if err != nil {
return fmt.Errorf("go tool compile -o %s %s: %v\n%s", go1obj, go1src, err, out)
}
- out, err = exec.Command(gotool, "tool", "compile", "-o", go2obj, go2src).CombinedOutput()
+ out, err = exec.Command(gotool, "tool", "compile", "-p=p", "-o", go2obj, go2src).CombinedOutput()
if err != nil {
return fmt.Errorf("go tool compile -o %s %s: %v\n%s", go2obj, go2src, err, out)
}
diff --git a/src/cmd/internal/obj/objfile_test.go b/src/cmd/internal/obj/objfile_test.go
index 146627b62b..f5a4016eec 100644
--- a/src/cmd/internal/obj/objfile_test.go
+++ b/src/cmd/internal/obj/objfile_test.go
@@ -111,7 +111,7 @@ func TestSymbolTooLarge(t *testing.T) { // Issue 42054
t.Fatalf("failed to write source file: %v\n", err)
}
obj := filepath.Join(tmpdir, "p.o")
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", obj, src)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-o", obj, src)
out, err := cmd.CombinedOutput()
if err == nil {
t.Fatalf("did not fail\noutput: %s", out)
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go
index ad7658bb25..0492feaf0d 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/link/link_test.go
@@ -55,7 +55,7 @@ func main() {}
t.Fatalf("failed to write main.go: %v\n", err)
}
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "main.go")
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=main", "main.go")
cmd.Dir = tmpdir
out, err := cmd.CombinedOutput()
if err != nil {
@@ -100,7 +100,7 @@ func TestIssue28429(t *testing.T) {
// Compile a main package.
write("main.go", "package main; func main() {}")
- runGo("tool", "compile", "-p", "main", "main.go")
+ runGo("tool", "compile", "-p=main", "main.go")
runGo("tool", "pack", "c", "main.a", "main.o")
// Add an extra section with a short, non-.o name.
@@ -236,7 +236,7 @@ void foo() {
// Compile, assemble and pack the Go and C code.
runGo("tool", "asm", "-gensymabis", "-o", "symabis", "x.s")
- runGo("tool", "compile", "-symabis", "symabis", "-p", "main", "-o", "x1.o", "main.go")
+ runGo("tool", "compile", "-symabis", "symabis", "-p=main", "-o", "x1.o", "main.go")
runGo("tool", "asm", "-o", "x2.o", "x.s")
run(cc, append(cflags, "-c", "-o", "x3.o", "x.c")...)
runGo("tool", "pack", "c", "x.a", "x1.o", "x2.o", "x3.o")
@@ -431,7 +431,7 @@ func TestIssue34788Android386TLSSequence(t *testing.T) {
}
obj := filepath.Join(tmpdir, "blah.o")
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", obj, src)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=blah", "-o", obj, src)
cmd.Env = append(os.Environ(), "GOARCH=386", "GOOS=android")
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("failed to compile blah.go: %v, output: %s\n", err, out)
@@ -765,13 +765,13 @@ func TestIndexMismatch(t *testing.T) {
exe := filepath.Join(tmpdir, "main.exe")
// Build a program with main package importing package a.
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", aObj, aSrc)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=a", "-o", aObj, aSrc)
t.Log(cmd)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("compiling a.go failed: %v\n%s", err, out)
}
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-I", tmpdir, "-o", mObj, mSrc)
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=main", "-I", tmpdir, "-o", mObj, mSrc)
t.Log(cmd)
out, err = cmd.CombinedOutput()
if err != nil {
@@ -786,7 +786,7 @@ func TestIndexMismatch(t *testing.T) {
// Now, overwrite a.o with the object of b.go. This should
// result in an index mismatch.
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", aObj, bSrc)
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=a", "-o", aObj, bSrc)
t.Log(cmd)
out, err = cmd.CombinedOutput()
if err != nil {
diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go
index ff43161030..313cc7a809 100644
--- a/src/cmd/objdump/objdump_test.go
+++ b/src/cmd/objdump/objdump_test.go
@@ -267,7 +267,7 @@ func TestDisasmGoobj(t *testing.T) {
mustHaveDisasm(t)
hello := filepath.Join(tmp, "hello.o")
- args := []string{"tool", "compile", "-o", hello}
+ args := []string{"tool", "compile", "-p=main", "-o", hello}
args = append(args, "testdata/fmthello.go")
out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput()
if err != nil {
diff --git a/src/cmd/pack/pack_test.go b/src/cmd/pack/pack_test.go
index 81e78f53e2..6eec1f50ef 100644
--- a/src/cmd/pack/pack_test.go
+++ b/src/cmd/pack/pack_test.go
@@ -179,7 +179,7 @@ func TestHello(t *testing.T) {
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
- run(goBin, "tool", "compile", "hello.go")
+ run(goBin, "tool", "compile", "-p=main", "hello.go")
run("./pack", "grc", "hello.a", "hello.o")
run(goBin, "tool", "link", "-o", "a.out", "hello.a")
out := run("./a.out")
@@ -246,9 +246,9 @@ func TestLargeDefs(t *testing.T) {
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
- run(goBin, "tool", "compile", "large.go")
+ run(goBin, "tool", "compile", "-p=large", "large.go")
run("./pack", "grc", "large.a", "large.o")
- run(goBin, "tool", "compile", "-I", ".", "main.go")
+ run(goBin, "tool", "compile", "-p=main", "-I", ".", "main.go")
run(goBin, "tool", "link", "-L", ".", "-o", "a.out", "main.o")
out := run("./a.out")
if out != "ok\n" {
@@ -281,9 +281,9 @@ func TestIssue21703(t *testing.T) {
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
- run(goBin, "tool", "compile", "a.go")
+ run(goBin, "tool", "compile", "-p=a", "a.go")
run("./pack", "c", "a.a", "a.o")
- run(goBin, "tool", "compile", "-I", ".", "b.go")
+ run(goBin, "tool", "compile", "-p=b", "-I", ".", "b.go")
}
// Test the "c" command can "see through" the archive generated by the compiler.
@@ -305,7 +305,7 @@ func TestCreateWithCompilerObj(t *testing.T) {
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
- run(goBin, "tool", "compile", "-pack", "-o", "p.a", "p.go")
+ run(goBin, "tool", "compile", "-pack", "-p=p", "-o", "p.a", "p.go")
run("./pack", "c", "packed.a", "p.a")
fi, err := os.Stat(filepath.Join(dir, "p.a"))
if err != nil {
@@ -323,7 +323,7 @@ func TestCreateWithCompilerObj(t *testing.T) {
}
// Test -linkobj flag as well.
- run(goBin, "tool", "compile", "-linkobj", "p2.a", "-o", "p.x", "p.go")
+ run(goBin, "tool", "compile", "-p=p", "-linkobj", "p2.a", "-o", "p.x", "p.go")
run("./pack", "c", "packed2.a", "p2.a")
fi, err = os.Stat(filepath.Join(dir, "p2.a"))
if err != nil {
@@ -369,7 +369,7 @@ func TestRWithNonexistentFile(t *testing.T) {
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
- run(goBin, "tool", "compile", "-o", "p.o", "p.go")
+ run(goBin, "tool", "compile", "-p=p", "-o", "p.o", "p.go")
run("./pack", "r", "p.a", "p.o") // should succeed
}
diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go
index c9c5946d9f..51511ea620 100644
--- a/src/go/internal/gcimporter/gcimporter_test.go
+++ b/src/go/internal/gcimporter/gcimporter_test.go
@@ -45,7 +45,7 @@ func compile(t *testing.T, dirname, filename, outdirname string) string {
}
basename := filepath.Base(filename)
outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", outname, filename)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-o", outname, filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
diff --git a/src/internal/abi/abi_test.go b/src/internal/abi/abi_test.go
index 5a3b6b616d..51d26f69ae 100644
--- a/src/internal/abi/abi_test.go
+++ b/src/internal/abi/abi_test.go
@@ -50,7 +50,7 @@ func TestFuncPCCompileError(t *testing.T) {
}
// compile go code.
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-symabis", symabi, "-o", obj, goSrc)
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-symabis", symabi, "-o", obj, goSrc)
out, err = cmd.CombinedOutput()
if err == nil {
t.Fatalf("go tool compile did not fail")
diff --git a/test/const7.go b/test/const7.go
index e625671278..6acd7fde3a 100644
--- a/test/const7.go
+++ b/test/const7.go
@@ -37,7 +37,7 @@ func testProg(dir, name string, length int, ok bool) {
log.Fatal(err)
}
- cmd := exec.Command("go", "tool", "compile", filename)
+ cmd := exec.Command("go", "tool", "compile", "-p=p", filename)
cmd.Dir = dir
output, err := cmd.CombinedOutput()
diff --git a/test/fixedbugs/bug302.go b/test/fixedbugs/bug302.go
index a2ab661277..b3b958c3aa 100644
--- a/test/fixedbugs/bug302.go
+++ b/test/fixedbugs/bug302.go
@@ -28,9 +28,9 @@ func main() {
}
defer os.RemoveAll(tmpDir)
- run("go", "tool", "compile", filepath.Join(fb, "bug302.dir", "p.go"))
+ run("go", "tool", "compile", "-p=p", filepath.Join(fb, "bug302.dir", "p.go"))
run("go", "tool", "pack", "grc", "pp.a", "p.o")
- run("go", "tool", "compile", "-I", ".", filepath.Join(fb, "bug302.dir", "main.go"))
+ run("go", "tool", "compile", "-p=main", "-I", ".", filepath.Join(fb, "bug302.dir", "main.go"))
}
func run(cmd string, args ...string) {
diff --git a/test/fixedbugs/bug369.go b/test/fixedbugs/bug369.go
index 83f638d046..8e50678c89 100644
--- a/test/fixedbugs/bug369.go
+++ b/test/fixedbugs/bug369.go
@@ -29,9 +29,9 @@ func main() {
return filepath.Join(tmpDir, name)
}
- run("go", "tool", "compile", "-N", "-o", tmp("slow.o"), "pkg.go")
- run("go", "tool", "compile", "-o", tmp("fast.o"), "pkg.go")
- run("go", "tool", "compile", "-D", tmpDir, "-o", tmp("main.o"), "main.go")
+ run("go", "tool", "compile", "-p=pkg", "-N", "-o", tmp("slow.o"), "pkg.go")
+ run("go", "tool", "compile", "-p=pkg", "-o", tmp("fast.o"), "pkg.go")
+ run("go", "tool", "compile", "-p=main", "-D", tmpDir, "-o", tmp("main.o"), "main.go")
run("go", "tool", "link", "-o", tmp("a.exe"), tmp("main.o"))
run(tmp("a.exe"))
}
diff --git a/test/fixedbugs/issue11771.go b/test/fixedbugs/issue11771.go
index c95dd6ba39..e5bed186bb 100644
--- a/test/fixedbugs/issue11771.go
+++ b/test/fixedbugs/issue11771.go
@@ -52,7 +52,7 @@ func x() {
log.Fatal(err)
}
- cmd := exec.Command("go", "tool", "compile", "x.go")
+ cmd := exec.Command("go", "tool", "compile", "-p=p", "x.go")
cmd.Dir = dir
output, err := cmd.CombinedOutput()
if err == nil {
diff --git a/test/fixedbugs/issue21317.go b/test/fixedbugs/issue21317.go
index 32b660c163..fe51ef1738 100644
--- a/test/fixedbugs/issue21317.go
+++ b/test/fixedbugs/issue21317.go
@@ -38,7 +38,7 @@ func main() {
defer os.RemoveAll(f.Name())
// compile and test output
- cmd := exec.Command("go", "tool", "compile", f.Name())
+ cmd := exec.Command("go", "tool", "compile", "-p=main", f.Name())
out, err := cmd.CombinedOutput()
if err == nil {
log.Fatalf("expected cmd/compile to fail")
diff --git a/test/fixedbugs/issue22660.go b/test/fixedbugs/issue22660.go
index 9ce9c4d732..7f542c5153 100644
--- a/test/fixedbugs/issue22660.go
+++ b/test/fixedbugs/issue22660.go
@@ -35,7 +35,7 @@ func main() {
log.Fatal(err)
}
- out, err := exec.Command("go", "tool", "compile", fmt.Sprintf("-trimpath=%s", path), f.Name()).CombinedOutput()
+ out, err := exec.Command("go", "tool", "compile", "-p=p", fmt.Sprintf("-trimpath=%s", path), f.Name()).CombinedOutput()
if err == nil {
log.Fatalf("expected compiling %s to fail", f.Name())
}
diff --git a/test/fixedbugs/issue22662b.go b/test/fixedbugs/issue22662b.go
index 8da17679be..df4f28429c 100644
--- a/test/fixedbugs/issue22662b.go
+++ b/test/fixedbugs/issue22662b.go
@@ -48,7 +48,7 @@ func main() {
log.Fatal(err)
}
- out, err := exec.Command("go", "tool", "compile", f.Name()).CombinedOutput()
+ out, err := exec.Command("go", "tool", "compile", "-p=p", f.Name()).CombinedOutput()
if err == nil {
log.Fatalf("expected compiling\n---\n%s\n---\nto fail", test.src)
}
diff --git a/test/fixedbugs/issue26411.go b/test/fixedbugs/issue26411.go
index 5f40bf2522..eb17960c47 100644
--- a/test/fixedbugs/issue26411.go
+++ b/test/fixedbugs/issue26411.go
@@ -75,7 +75,7 @@ bar :
log.Printf("#%d: failed to create file %s", i, filename)
continue
}
- output, _ := exec.Command("go", "tool", "compile", filename).CombinedOutput()
+ output, _ := exec.Command("go", "tool", "compile", "-p=p", filename).CombinedOutput()
// remove each matching error from the output
for _, err := range test.errors {
diff --git a/test/fixedbugs/issue30908.go b/test/fixedbugs/issue30908.go
index 60fbd11457..27f070ecec 100644
--- a/test/fixedbugs/issue30908.go
+++ b/test/fixedbugs/issue30908.go
@@ -1,9 +1,10 @@
-// rundir -P -ldflags -strictdups=2 -w=0
+// rundir -ldflags -strictdups=2 -w=0
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build !nacl && !js
// +build !nacl,!js
package ignored
diff --git a/test/fixedbugs/issue9355.go b/test/fixedbugs/issue9355.go
index 319a2a90df..31376153ac 100644
--- a/test/fixedbugs/issue9355.go
+++ b/test/fixedbugs/issue9355.go
@@ -27,7 +27,7 @@ func main() {
}
f.Close()
- out := run("go", "tool", "compile", "-o", f.Name(), "-S", "a.go")
+ out := run("go", "tool", "compile", "-p=p", "-o", f.Name(), "-S", "a.go")
os.Remove(f.Name())
// 6g/8g print the offset as dec, but 5g/9g print the offset as hex.
diff --git a/test/interface/embed1.dir/embed0.go b/test/interface/embed1.dir/embed0.go
index 728bec74e8..4aed391b63 100644
--- a/test/interface/embed1.dir/embed0.go
+++ b/test/interface/embed1.dir/embed0.go
@@ -7,10 +7,11 @@
package p
type T int
+
func (t T) m() {}
-type I interface { m() }
-type J interface { I }
+type I interface{ m() }
+type J interface{ I }
func main() {
var i I
diff --git a/test/linkmain_run.go b/test/linkmain_run.go
index 077f7ee917..6bc82dfafc 100644
--- a/test/linkmain_run.go
+++ b/test/linkmain_run.go
@@ -62,14 +62,14 @@ func main() {
}
// helloworld.go is package main
- run("go tool compile -o", tmp("linkmain.o"), "helloworld.go")
- run("go tool compile -pack -o", tmp("linkmain.a"), "helloworld.go")
+ run("go tool compile -p=main -o", tmp("linkmain.o"), "helloworld.go")
+ run("go tool compile -p=main -pack -o", tmp("linkmain.a"), "helloworld.go")
run("go tool link -o", tmp("linkmain.exe"), tmp("linkmain.o"))
run("go tool link -o", tmp("linkmain.exe"), tmp("linkmain.a"))
// linkmain.go is not
- run("go tool compile -o", tmp("linkmain1.o"), "linkmain.go")
- run("go tool compile -pack -o", tmp("linkmain1.a"), "linkmain.go")
+ run("go tool compile -p=notmain -o", tmp("linkmain1.o"), "linkmain.go")
+ run("go tool compile -p=notmain -pack -o", tmp("linkmain1.a"), "linkmain.go")
runFail("go tool link -o", tmp("linkmain.exe"), tmp("linkmain1.o"))
runFail("go tool link -o", tmp("linkmain.exe"), tmp("linkmain1.a"))
cleanup()
diff --git a/test/linkname2.go b/test/linkname2.go
deleted file mode 100644
index 5eb250f9c4..0000000000
--- a/test/linkname2.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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"
-
-//line linkname2.go:18
-//go:linkname y
diff --git a/test/linkobj.go b/test/linkobj.go
index 4c9bd24568..023996aa30 100644
--- a/test/linkobj.go
+++ b/test/linkobj.go
@@ -37,28 +37,28 @@ func main() {
writeFile("p1.go", `
package p1
-
+
func F() {
println("hello from p1")
}
`)
writeFile("p2.go", `
package p2
-
+
import "./p1"
func F() {
p1.F()
println("hello from p2")
}
-
+
func main() {}
`)
writeFile("p3.go", `
package main
import "./p2"
-
+
func main() {
p2.F()
println("hello from main")
@@ -76,9 +76,9 @@ func main() {
}
// inlining is disabled to make sure that the link objects contain needed code.
- run("go", "tool", "compile", pkg, "-D", ".", "-I", ".", "-l", "-o", "p1."+o, "-linkobj", "p1.lo", "p1.go")
- run("go", "tool", "compile", pkg, "-D", ".", "-I", ".", "-l", "-o", "p2."+o, "-linkobj", "p2.lo", "p2.go")
- run("go", "tool", "compile", pkg, "-D", ".", "-I", ".", "-l", "-o", "p3."+o, "-linkobj", "p3.lo", "p3.go")
+ run("go", "tool", "compile", "-p=p1", pkg, "-D", ".", "-I", ".", "-l", "-o", "p1."+o, "-linkobj", "p1.lo", "p1.go")
+ run("go", "tool", "compile", "-p=p2", pkg, "-D", ".", "-I", ".", "-l", "-o", "p2."+o, "-linkobj", "p2.lo", "p2.go")
+ run("go", "tool", "compile", "-p=main", pkg, "-D", ".", "-I", ".", "-l", "-o", "p3."+o, "-linkobj", "p3.lo", "p3.go")
cp("p1."+o, "p1.oo")
cp("p2."+o, "p2.oo")
diff --git a/test/run.go b/test/run.go
index 869911a426..e5dd0e443c 100644
--- a/test/run.go
+++ b/test/run.go
@@ -184,7 +184,7 @@ func main() {
resCount[status]++
dt := fmt.Sprintf("%.3fs", test.dt.Seconds())
if status == "FAIL" {
- fmt.Printf("# go run run.go %s\n%s\nFAIL\t%s\t%s\n",
+ fmt.Printf("# go run run.go -- %s\n%s\nFAIL\t%s\t%s\n",
path.Join(test.dir, test.gofile),
errStr, test.goFileName(), dt)
continue
@@ -254,7 +254,7 @@ func goFiles(dir string) []string {
type runCmd func(...string) ([]byte, error)
func compileFile(runcmd runCmd, longname string, flags []string) (out []byte, err error) {
- cmd := []string{goTool(), "tool", "compile", "-e"}
+ cmd := []string{goTool(), "tool", "compile", "-e", "-p=p"}
cmd = append(cmd, flags...)
if *linkshared {
cmd = append(cmd, "-dynlink", "-installsuffix=dynlink")
@@ -263,8 +263,11 @@ func compileFile(runcmd runCmd, longname string, flags []string) (out []byte, er
return runcmd(cmd...)
}
-func compileInDir(runcmd runCmd, dir string, flags []string, localImports bool, names ...string) (out []byte, err error) {
- cmd := []string{goTool(), "tool", "compile", "-e"}
+func compileInDir(runcmd runCmd, dir string, flags []string, localImports bool, pkgname string, names ...string) (out []byte, err error) {
+ if pkgname != "main" {
+ pkgname = strings.TrimSuffix(names[0], ".go")
+ }
+ cmd := []string{goTool(), "tool", "compile", "-e", "-p=" + pkgname}
if localImports {
// Set relative path for local imports and import search path to current dir.
cmd = append(cmd, "-D", ".", "-I", ".")
@@ -415,28 +418,33 @@ func getPackageNameFromSource(fn string) (string, error) {
return pkgname[1], nil
}
+type goDirPkg struct {
+ name string
+ files []string
+}
+
// If singlefilepkgs is set, each file is considered a separate package
// even if the package names are the same.
-func goDirPackages(longdir string, singlefilepkgs bool) ([][]string, error) {
+func goDirPackages(longdir string, singlefilepkgs bool) ([]*goDirPkg, error) {
files, err := goDirFiles(longdir)
if err != nil {
return nil, err
}
- var pkgs [][]string
- m := make(map[string]int)
+ var pkgs []*goDirPkg
+ m := make(map[string]*goDirPkg)
for _, file := range files {
name := file.Name()
pkgname, err := getPackageNameFromSource(filepath.Join(longdir, name))
if err != nil {
log.Fatal(err)
}
- i, ok := m[pkgname]
+ p, ok := m[pkgname]
if singlefilepkgs || !ok {
- i = len(pkgs)
- pkgs = append(pkgs, nil)
- m[pkgname] = i
+ p = &goDirPkg{name: pkgname}
+ pkgs = append(pkgs, p)
+ m[pkgname] = p
}
- pkgs[i] = append(pkgs[i], name)
+ p.files = append(p.files, name)
}
return pkgs, nil
}
@@ -607,7 +615,6 @@ func (t *test) run() {
wantError := false
wantAuto := false
singlefilepkgs := false
- setpkgpaths := false
localImports := true
f, err := splitQuoted(action)
if err != nil {
@@ -652,8 +659,6 @@ func (t *test) run() {
wantError = false
case "-s":
singlefilepkgs = true
- case "-P":
- setpkgpaths = true
case "-n":
// Do not set relative path for local imports to current dir,
// e.g. do not pass -D . -I . to the compiler.
@@ -843,7 +848,7 @@ func (t *test) run() {
// Fail if wantError is true and compilation was successful and vice versa.
// Match errors produced by gc against errors in comments.
// TODO(gri) remove need for -C (disable printing of columns in error messages)
- cmdline := []string{goTool(), "tool", "compile", "-d=panic", "-C", "-e", "-o", "a.o"}
+ cmdline := []string{goTool(), "tool", "compile", "-p=p", "-d=panic", "-C", "-e", "-o", "a.o"}
// No need to add -dynlink even if linkshared if we're just checking for errors...
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, long)
@@ -880,8 +885,8 @@ func (t *test) run() {
t.err = err
return
}
- for _, gofiles := range pkgs {
- _, t.err = compileInDir(runcmd, longdir, flags, localImports, gofiles...)
+ for _, pkg := range pkgs {
+ _, t.err = compileInDir(runcmd, longdir, flags, localImports, pkg.name, pkg.files...)
if t.err != nil {
return
}
@@ -904,8 +909,8 @@ func (t *test) run() {
// Preceding pkg must return an error from compileInDir.
errPkg--
}
- for i, gofiles := range pkgs {
- out, err := compileInDir(runcmd, longdir, flags, localImports, gofiles...)
+ for i, pkg := range pkgs {
+ out, err := compileInDir(runcmd, longdir, flags, localImports, pkg.name, pkg.files...)
if i == errPkg {
if wantError && err == nil {
t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out)
@@ -919,7 +924,7 @@ func (t *test) run() {
return
}
var fullshort []string
- for _, name := range gofiles {
+ for _, name := range pkg.files {
fullshort = append(fullshort, filepath.Join(longdir, name), name)
}
t.err = t.errorCheck(string(out), wantAuto, fullshort...)
@@ -953,18 +958,8 @@ func (t *test) run() {
}
}
- for i, gofiles := range pkgs {
- pflags := []string{}
- pflags = append(pflags, flags...)
- if setpkgpaths {
- fp := filepath.Join(longdir, gofiles[0])
- pkgname, err := getPackageNameFromSource(fp)
- if err != nil {
- log.Fatal(err)
- }
- pflags = append(pflags, "-p", pkgname)
- }
- _, err := compileInDir(runcmd, longdir, pflags, localImports, gofiles...)
+ for i, pkg := range pkgs {
+ _, err := compileInDir(runcmd, longdir, flags, localImports, pkg.name, pkg.files...)
// Allow this package compilation fail based on conditions below;
// its errors were checked in previous case.
if err != nil && !(wantError && action == "errorcheckandrundir" && i == len(pkgs)-2) {
@@ -972,7 +967,7 @@ func (t *test) run() {
return
}
if i == len(pkgs)-1 {
- err = linkFile(runcmd, gofiles[0], ldflags)
+ err = linkFile(runcmd, pkg.files[0], ldflags)
if err != nil {
t.err = err
return
@@ -1071,7 +1066,7 @@ func (t *test) run() {
}
}
var objs []string
- cmd := []string{goTool(), "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"}
+ cmd := []string{goTool(), "tool", "compile", "-p=main", "-e", "-D", ".", "-I", ".", "-o", "go.o"}
if len(asms) > 0 {
cmd = append(cmd, "-asmhdr", "go_asm.h", "-symabis", "symabis")
}
@@ -1156,7 +1151,7 @@ func (t *test) run() {
// Because we run lots of trivial test programs,
// the time adds up.
pkg := filepath.Join(t.tempDir, "pkg.a")
- if _, err := runcmd(goTool(), "tool", "compile", "-o", pkg, t.goFileName()); err != nil {
+ if _, err := runcmd(goTool(), "tool", "compile", "-p=main", "-o", pkg, t.goFileName()); err != nil {
t.err = err
return
}
@@ -1238,7 +1233,7 @@ func (t *test) run() {
t.err = fmt.Errorf("write tempfile:%s", err)
return
}
- cmdline := []string{goTool(), "tool", "compile", "-d=panic", "-e", "-o", "a.o"}
+ cmdline := []string{goTool(), "tool", "compile", "-p=p", "-d=panic", "-e", "-o", "a.o"}
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, tfile)
out, err = runcmd(cmdline...)
diff --git a/test/sinit_run.go b/test/sinit_run.go
index dcaf338331..e01502bd56 100644
--- a/test/sinit_run.go
+++ b/test/sinit_run.go
@@ -25,7 +25,7 @@ func main() {
}
f.Close()
- cmd := exec.Command("go", "tool", "compile", "-o", f.Name(), "-S", "sinit.go")
+ cmd := exec.Command("go", "tool", "compile", "-p=sinit", "-o", f.Name(), "-S", "sinit.go")
out, err := cmd.CombinedOutput()
os.Remove(f.Name())
if err != nil {
From e189b5e06d4831025758c0b152838fa1a0375525 Mon Sep 17 00:00:00 2001
From: Robert Findley
Date: Wed, 9 Mar 2022 11:35:10 -0500
Subject: [PATCH 058/276] go/types, types2: clarify documentation with respect
to generic types
Address several areas where documentation was inaccurate or unclear
regarding generic types. Also prefer the use of the word 'generic' over
'parameterized', and add additional documentation for the use of
SetConstraint.
For #49593
Change-Id: Iccac60d1b3e2c45a57a3d03b3c10984293af57dd
Reviewed-on: https://go-review.googlesource.com/c/go/+/391154
Trust: Robert Findley
Run-TryBot: Robert Findley
Reviewed-by: Robert Griesemer
TryBot-Result: Gopher Robot
---
src/cmd/compile/internal/types2/api.go | 6 +++---
src/cmd/compile/internal/types2/instantiate.go | 8 ++++----
src/cmd/compile/internal/types2/named.go | 12 ++++++++----
src/cmd/compile/internal/types2/typeparam.go | 9 ++++++---
src/go/types/api.go | 6 +++---
src/go/types/eval.go | 4 ++--
src/go/types/instantiate.go | 8 ++++----
src/go/types/named.go | 12 ++++++++----
src/go/types/typeparam.go | 9 ++++++---
9 files changed, 44 insertions(+), 30 deletions(-)
diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go
index 584f613a64..d864c96fb6 100644
--- a/src/cmd/compile/internal/types2/api.go
+++ b/src/cmd/compile/internal/types2/api.go
@@ -204,12 +204,12 @@ type Info struct {
// qualified identifiers are collected in the Uses map.
Types map[syntax.Expr]TypeAndValue
- // Instances maps identifiers denoting parameterized types or functions to
- // their type arguments and instantiated type.
+ // Instances maps identifiers denoting generic types or functions to their
+ // type arguments and instantiated type.
//
// For example, Instances will map the identifier for 'T' in the type
// instantiation T[int, string] to the type arguments [int, string] and
- // resulting instantiated *Named type. Given a parameterized function
+ // resulting instantiated *Named type. Given a generic function
// func F[A any](A), Instances will map the identifier for 'F' in the call
// expression F(int(1)) to the inferred type arguments [int], and resulting
// instantiated *Signature.
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index c2653a3834..9eced489dc 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -15,10 +15,10 @@ import (
// Instantiate instantiates the type orig with the given type arguments targs.
// orig must be a *Named or a *Signature type. If there is no error, the
-// resulting Type is a new, instantiated (not parameterized) type of the same
-// kind (either a *Named or a *Signature). Methods attached to a *Named type
-// are also instantiated, and associated with a new *Func that has the same
-// position as the original method, but nil function scope.
+// resulting Type is an instantiated type of the same kind (either a *Named or
+// a *Signature). Methods attached to a *Named type are also instantiated, and
+// associated with a new *Func that has the same position as the original
+// method, but nil function scope.
//
// If ctxt is non-nil, it may be used to de-duplicate the instance against
// previous instances with the same identity. As a special case, generic
diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go
index 5c6a1cf5d8..daf8fdc986 100644
--- a/src/cmd/compile/internal/types2/named.go
+++ b/src/cmd/compile/internal/types2/named.go
@@ -98,10 +98,10 @@ func (t *Named) cleanup() {
}
// Obj returns the type name for the declaration defining the named type t. For
-// instantiated types, this is the type name of the base type.
+// instantiated types, this is same as the type name of the origin type.
func (t *Named) Obj() *TypeName { return t.orig.obj } // for non-instances this is the same as t.obj
-// Origin returns the parameterized type from which the named type t is
+// Origin returns the generic type from which the named type t is
// instantiated. If t is not an instantiated type, the result is t.
func (t *Named) Origin() *Named { return t.orig }
@@ -109,7 +109,7 @@ func (t *Named) Origin() *Named { return t.orig }
// between parameterized instantiated and non-instantiated types.
// TypeParams returns the type parameters of the named type t, or nil.
-// The result is non-nil for an (originally) parameterized type even if it is instantiated.
+// The result is non-nil for an (originally) generic type even if it is instantiated.
func (t *Named) TypeParams() *TypeParamList { return t.resolve(nil).tparams }
// SetTypeParams sets the type parameters of the named type t.
@@ -122,7 +122,11 @@ func (t *Named) SetTypeParams(tparams []*TypeParam) {
// TypeArgs returns the type arguments used to instantiate the named type t.
func (t *Named) TypeArgs() *TypeList { return t.targs }
-// NumMethods returns the number of explicit methods whose receiver is named type t.
+// NumMethods returns the number of explicit methods defined for t.
+//
+// For an ordinary or instantiated type t, the receiver base type of these
+// methods will be the named type t. For an uninstantiated generic type t, each
+// method receiver will be instantiated with its receiver type parameters.
func (t *Named) NumMethods() int { return t.resolve(nil).methods.Len() }
// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go
index 9ed3369ff4..2e9a2adae6 100644
--- a/src/cmd/compile/internal/types2/typeparam.go
+++ b/src/cmd/compile/internal/types2/typeparam.go
@@ -31,7 +31,8 @@ func (t *TypeParam) Obj() *TypeName { return t.obj }
// or Signature type by calling SetTypeParams. Setting a type parameter on more
// than one type will result in a panic.
//
-// The constraint argument can be nil, and set later via SetConstraint.
+// The constraint argument can be nil, and set later via SetConstraint. If the
+// constraint is non-nil, it must be fully defined.
func NewTypeParam(obj *TypeName, constraint Type) *TypeParam {
return (*Checker)(nil).newTypeParam(obj, constraint)
}
@@ -71,8 +72,10 @@ func (t *TypeParam) Constraint() Type {
// SetConstraint sets the type constraint for t.
//
-// SetConstraint should not be called concurrently, but once SetConstraint
-// returns the receiver t is safe for concurrent use.
+// It must be called by users of NewTypeParam after the bound's underlying is
+// fully defined, and before using the type parameter in any way other than to
+// form other types. Once SetConstraint returns the receiver, t is safe for
+// concurrent use.
func (t *TypeParam) SetConstraint(bound Type) {
if bound == nil {
panic("nil constraint")
diff --git a/src/go/types/api.go b/src/go/types/api.go
index 86a03eba31..f2dcd104d8 100644
--- a/src/go/types/api.go
+++ b/src/go/types/api.go
@@ -199,12 +199,12 @@ type Info struct {
// qualified identifiers are collected in the Uses map.
Types map[ast.Expr]TypeAndValue
- // Instances maps identifiers denoting parameterized types or functions to
- // their type arguments and instantiated type.
+ // Instances maps identifiers denoting generic types or functions to their
+ // type arguments and instantiated type.
//
// For example, Instances will map the identifier for 'T' in the type
// instantiation T[int, string] to the type arguments [int, string] and
- // resulting instantiated *Named type. Given a parameterized function
+ // resulting instantiated *Named type. Given a generic function
// func F[A any](A), Instances will map the identifier for 'F' in the call
// expression F(int(1)) to the inferred type arguments [int], and resulting
// instantiated *Signature.
diff --git a/src/go/types/eval.go b/src/go/types/eval.go
index c8bb005eb6..5700cbf79c 100644
--- a/src/go/types/eval.go
+++ b/src/go/types/eval.go
@@ -37,8 +37,8 @@ func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (_ Type
// CheckExpr type checks the expression expr as if it had appeared at position
// pos of package pkg. Type information about the expression is recorded in
-// info. The expression may be an uninstantiated parameterized function or
-// type.
+// info. The expression may be an identifier denoting an uninstantiated generic
+// function or type.
//
// If pkg == nil, the Universe scope is used and the provided
// position pos is ignored. If pkg != nil, and pos is invalid,
diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 4b8e3d4661..a481746657 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -15,10 +15,10 @@ import (
// Instantiate instantiates the type orig with the given type arguments targs.
// orig must be a *Named or a *Signature type. If there is no error, the
-// resulting Type is a new, instantiated (not parameterized) type of the same
-// kind (either a *Named or a *Signature). Methods attached to a *Named type
-// are also instantiated, and associated with a new *Func that has the same
-// position as the original method, but nil function scope.
+// resulting Type is an instantiated type of the same kind (either a *Named or
+// a *Signature). Methods attached to a *Named type are also instantiated, and
+// associated with a new *Func that has the same position as the original
+// method, but nil function scope.
//
// If ctxt is non-nil, it may be used to de-duplicate the instance against
// previous instances with the same identity. As a special case, generic
diff --git a/src/go/types/named.go b/src/go/types/named.go
index 5b84e0653b..876f7e8551 100644
--- a/src/go/types/named.go
+++ b/src/go/types/named.go
@@ -98,12 +98,12 @@ func (t *Named) cleanup() {
}
// Obj returns the type name for the declaration defining the named type t. For
-// instantiated types, this is the type name of the base type.
+// instantiated types, this is same as the type name of the origin type.
func (t *Named) Obj() *TypeName {
return t.orig.obj // for non-instances this is the same as t.obj
}
-// Origin returns the parameterized type from which the named type t is
+// Origin returns the generic type from which the named type t is
// instantiated. If t is not an instantiated type, the result is t.
func (t *Named) Origin() *Named { return t.orig }
@@ -111,7 +111,7 @@ func (t *Named) Origin() *Named { return t.orig }
// between parameterized instantiated and non-instantiated types.
// TypeParams returns the type parameters of the named type t, or nil.
-// The result is non-nil for an (originally) parameterized type even if it is instantiated.
+// The result is non-nil for an (originally) generic type even if it is instantiated.
func (t *Named) TypeParams() *TypeParamList { return t.resolve(nil).tparams }
// SetTypeParams sets the type parameters of the named type t.
@@ -124,7 +124,11 @@ func (t *Named) SetTypeParams(tparams []*TypeParam) {
// TypeArgs returns the type arguments used to instantiate the named type t.
func (t *Named) TypeArgs() *TypeList { return t.targs }
-// NumMethods returns the number of explicit methods whose receiver is named type t.
+// NumMethods returns the number of explicit methods defined for t.
+//
+// For an ordinary or instantiated type t, the receiver base type of these
+// methods will be the named type t. For an uninstantiated generic type t, each
+// method receiver will be instantiated with its receiver type parameters.
func (t *Named) NumMethods() int { return t.resolve(nil).methods.Len() }
// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go
index 778c687d43..40d96ac947 100644
--- a/src/go/types/typeparam.go
+++ b/src/go/types/typeparam.go
@@ -30,7 +30,8 @@ type TypeParam struct {
// or Signature type by calling SetTypeParams. Setting a type parameter on more
// than one type will result in a panic.
//
-// The constraint argument can be nil, and set later via SetConstraint.
+// The constraint argument can be nil, and set later via SetConstraint. If the
+// constraint is non-nil, it must be fully defined.
func NewTypeParam(obj *TypeName, constraint Type) *TypeParam {
return (*Checker)(nil).newTypeParam(obj, constraint)
}
@@ -73,8 +74,10 @@ func (t *TypeParam) Constraint() Type {
// SetConstraint sets the type constraint for t.
//
-// SetConstraint should not be called concurrently, but once SetConstraint
-// returns the receiver t is safe for concurrent use.
+// It must be called by users of NewTypeParam after the bound's underlying is
+// fully defined, and before using the type parameter in any way other than to
+// form other types. Once SetConstraint returns the receiver, t is safe for
+// concurrent use.
func (t *TypeParam) SetConstraint(bound Type) {
if bound == nil {
panic("nil constraint")
From 3a5e3d8173df547d8360a609097fc80f01182db1 Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Wed, 9 Mar 2022 14:27:25 -0800
Subject: [PATCH 059/276] go/types, types2: pointer base types cannot be type
constraints
Pointer types may appear in expressions *P and we don't know if
we have an indirection (P is a pointer value) or a pointer type
(P is a type) until we type-check P. Don't forget to check that
a type P must be an ordinary (not a constraint) type in this
special case.
Fixes #51578.
Change-Id: If782cc6dd2a602a498574c78c99e40c3b72274a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/391275
Trust: Robert Griesemer
Run-TryBot: Robert Griesemer
Reviewed-by: Robert Findley
TryBot-Result: Gopher Robot
---
src/cmd/compile/internal/types2/expr.go | 1 +
.../types2/testdata/fixedbugs/issue51578.go2 | 17 +++++++++++++++++
src/cmd/compile/internal/types2/typexpr.go | 10 +++++++---
src/go/types/expr.go | 1 +
src/go/types/testdata/fixedbugs/issue51578.go2 | 17 +++++++++++++++++
src/go/types/typexpr.go | 10 +++++++---
6 files changed, 50 insertions(+), 6 deletions(-)
create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51578.go2
create mode 100644 src/go/types/testdata/fixedbugs/issue51578.go2
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 861a83472d..05cf1d0b33 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -1642,6 +1642,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
case invalid:
goto Error
case typexpr:
+ check.validVarType(e.X, x.typ)
x.typ = &Pointer{base: x.typ}
default:
var base Type
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51578.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51578.go2
new file mode 100644
index 0000000000..5c204bae20
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51578.go2
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var _ = (*interface /* ERROR interface contains type constraints */ {int})(nil)
+
+// abbreviated test case from issue
+
+type TypeSet interface{ int | string }
+
+func _() {
+ f((*TypeSet /* ERROR interface contains type constraints */)(nil))
+}
+
+func f(any) {}
\ No newline at end of file
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index a9ce55bd1e..7e30562e97 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -147,10 +147,16 @@ func (check *Checker) typ(e syntax.Expr) Type {
// constraint interface.
func (check *Checker) varType(e syntax.Expr) Type {
typ := check.definedType(e, nil)
+ check.validVarType(e, typ)
+ return typ
+}
+// validVarType reports an error if typ is a constraint interface.
+// The expression e is used for error reporting, if any.
+func (check *Checker) validVarType(e syntax.Expr, typ Type) {
// If we have a type parameter there's nothing to do.
if isTypeParam(typ) {
- return typ
+ return
}
// We don't want to call under() or complete interfaces while we are in
@@ -169,8 +175,6 @@ func (check *Checker) varType(e syntax.Expr) Type {
}
}
})
-
- return typ
}
// definedType is like typ but also accepts a type name def.
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 68b0789d65..e24bd60dc3 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -1588,6 +1588,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case invalid:
goto Error
case typexpr:
+ check.validVarType(e.X, x.typ)
x.typ = &Pointer{base: x.typ}
default:
var base Type
diff --git a/src/go/types/testdata/fixedbugs/issue51578.go2 b/src/go/types/testdata/fixedbugs/issue51578.go2
new file mode 100644
index 0000000000..5c204bae20
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51578.go2
@@ -0,0 +1,17 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var _ = (*interface /* ERROR interface contains type constraints */ {int})(nil)
+
+// abbreviated test case from issue
+
+type TypeSet interface{ int | string }
+
+func _() {
+ f((*TypeSet /* ERROR interface contains type constraints */)(nil))
+}
+
+func f(any) {}
\ No newline at end of file
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 14735c3709..5bb2d8f811 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -144,10 +144,16 @@ func (check *Checker) typ(e ast.Expr) Type {
// constraint interface.
func (check *Checker) varType(e ast.Expr) Type {
typ := check.definedType(e, nil)
+ check.validVarType(e, typ)
+ return typ
+}
+// validVarType reports an error if typ is a constraint interface.
+// The expression e is used for error reporting, if any.
+func (check *Checker) validVarType(e ast.Expr, typ Type) {
// If we have a type parameter there's nothing to do.
if isTypeParam(typ) {
- return typ
+ return
}
// We don't want to call under() or complete interfaces while we are in
@@ -165,8 +171,6 @@ func (check *Checker) varType(e ast.Expr) Type {
}
}
})
-
- return typ
}
// definedType is like typ but also accepts a type name def.
From 9faef5a6540f56af0129610db8a55b443229075f Mon Sep 17 00:00:00 2001
From: Meng Zhuo
Date: Fri, 22 Oct 2021 14:36:06 +0800
Subject: [PATCH 060/276] cmd/compile,bytealg: change context register on
riscv64
The register ABI will use X8-X23 (CL 356519),
this CL changes context register from X20(S4) to X26(S10) to meet the
prerequisite.
Update #40724
Change-Id: I93d51d22fe7b3ea5ceffe96dff93e3af60fbe7f6
Reviewed-on: https://go-review.googlesource.com/c/go/+/357974
Trust: mzh
Run-TryBot: mzh
Reviewed-by: Joel Sing
Reviewed-by: Cherry Mui
TryBot-Result: Gopher Robot
---
src/cmd/compile/internal/riscv64/ssa.go | 2 +-
src/cmd/compile/internal/ssa/gen/RISCV64Ops.go | 4 ++--
src/cmd/compile/internal/ssa/opGen.go | 4 ++--
src/cmd/internal/obj/riscv/cpu.go | 6 +++---
src/internal/bytealg/equal_riscv64.s | 2 +-
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go
index 1359b6a0c3..fc52e9427d 100644
--- a/src/cmd/compile/internal/riscv64/ssa.go
+++ b/src/cmd/compile/internal/riscv64/ssa.go
@@ -648,7 +648,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
}
case ssa.OpRISCV64LoweredGetClosurePtr:
- // Closure pointer is S4 (riscv.REG_CTXT).
+ // Closure pointer is S10 (riscv.REG_CTXT).
ssagen.CheckLoweredGetClosurePtr(v)
case ssa.OpRISCV64LoweredGetCallerSP:
diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
index 076919773b..09a8bb38c9 100644
--- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go
@@ -26,7 +26,7 @@ import (
const (
riscv64REG_G = 27
- riscv64REG_CTXT = 20
+ riscv64REG_CTXT = 26
riscv64REG_LR = 1
riscv64REG_SP = 2
riscv64REG_GP = 3
@@ -115,7 +115,7 @@ func init() {
panic("Too many RISCV64 registers")
}
- regCtxt := regNamed["X20"]
+ regCtxt := regNamed["X26"]
callerSave := gpMask | fpMask | regNamed["g"]
var (
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index 81fe5d4c23..6f0eb45014 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -28898,7 +28898,7 @@ var opcodeTable = [...]opInfo{
call: true,
reg: regInfo{
inputs: []inputInfo{
- {1, 524288}, // X20
+ {1, 33554432}, // X26
{0, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
},
clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
@@ -29189,7 +29189,7 @@ var opcodeTable = [...]opInfo{
argLen: 0,
reg: regInfo{
outputs: []outputInfo{
- {0, 524288}, // X20
+ {0, 33554432}, // X26
},
},
},
diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go
index d9434e7415..8c2daf6e5b 100644
--- a/src/cmd/internal/obj/riscv/cpu.go
+++ b/src/cmd/internal/obj/riscv/cpu.go
@@ -125,13 +125,13 @@ const (
REG_A7 = REG_X17
REG_S2 = REG_X18
REG_S3 = REG_X19
- REG_S4 = REG_X20 // aka REG_CTXT
+ REG_S4 = REG_X20
REG_S5 = REG_X21
REG_S6 = REG_X22
REG_S7 = REG_X23
REG_S8 = REG_X24
REG_S9 = REG_X25
- REG_S10 = REG_X26
+ REG_S10 = REG_X26 // aka REG_CTXT
REG_S11 = REG_X27 // aka REG_G
REG_T3 = REG_X28
REG_T4 = REG_X29
@@ -139,8 +139,8 @@ const (
REG_T6 = REG_X31 // aka REG_TMP
// Go runtime register names.
+ REG_CTXT = REG_S10 // Context for closures.
REG_G = REG_S11 // G pointer.
- REG_CTXT = REG_S4 // Context for closures.
REG_LR = REG_RA // Link register.
REG_TMP = REG_T6 // Reserved for assembler use.
diff --git a/src/internal/bytealg/equal_riscv64.s b/src/internal/bytealg/equal_riscv64.s
index 959a996f81..5dd13beb55 100644
--- a/src/internal/bytealg/equal_riscv64.s
+++ b/src/internal/bytealg/equal_riscv64.s
@@ -5,7 +5,7 @@
#include "go_asm.h"
#include "textflag.h"
-#define CTXT S4
+#define CTXT S10
// func memequal(a, b unsafe.Pointer, size uintptr) bool
TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25
From 604140d93111f89911e17cb147dcf6a02d2700d0 Mon Sep 17 00:00:00 2001
From: Carl Johnson
Date: Fri, 4 Mar 2022 14:49:52 +0000
Subject: [PATCH 061/276] net/url: add JoinPath, URL.JoinPath
Builds on CL 332209.
Fixes #47005
Change-Id: I82708dede05d79a196ca63f5a4e7cb5ac9a041ea
GitHub-Last-Rev: 51b735066eef74f5e67c3e8899c58f44c0383c61
GitHub-Pull-Request: golang/go#50383
Reviewed-on: https://go-review.googlesource.com/c/go/+/374654
Reviewed-by: Russ Cox
Auto-Submit: Russ Cox
Trust: Ian Lance Taylor
Reviewed-by: Damien Neil
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gopher Robot
---
api/next.txt | 2 ++
src/net/url/url.go | 23 +++++++++++++++++
src/net/url/url_test.go | 56 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+)
diff --git a/api/next.txt b/api/next.txt
index 23fd98a9ba..148cbffbfe 100644
--- a/api/next.txt
+++ b/api/next.txt
@@ -3,3 +3,5 @@ pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint1
pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8
pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8
pkg encoding/binary, type AppendByteOrder interface, String() string
+pkg net/url, func JoinPath(string, ...string) (string, error)
+pkg net/url, method (*URL) JoinPath(...string) *URL
diff --git a/src/net/url/url.go b/src/net/url/url.go
index f31aa08b59..1571bf728b 100644
--- a/src/net/url/url.go
+++ b/src/net/url/url.go
@@ -13,6 +13,7 @@ package url
import (
"errors"
"fmt"
+ "path"
"sort"
"strconv"
"strings"
@@ -1176,6 +1177,17 @@ func (u *URL) UnmarshalBinary(text []byte) error {
return nil
}
+// JoinPath returns a new URL with the provided path elements joined to
+// any existing path and the resulting path cleaned of any ./ or ../ elements.
+func (u *URL) JoinPath(elem ...string) *URL {
+ url := *u
+ if len(elem) > 0 {
+ elem = append([]string{u.Path}, elem...)
+ url.setPath(path.Join(elem...))
+ }
+ return &url
+}
+
// validUserinfo reports whether s is a valid userinfo string per RFC 3986
// Section 3.2.1:
// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
@@ -1216,3 +1228,14 @@ func stringContainsCTLByte(s string) bool {
}
return false
}
+
+// JoinPath returns a URL string with the provided path elements joined to
+// the existing path of base and the resulting path cleaned of any ./ or ../ elements.
+func JoinPath(base string, elem ...string) (result string, err error) {
+ url, err := Parse(base)
+ if err != nil {
+ return
+ }
+ result = url.JoinPath(elem...).String()
+ return
+}
diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go
index 664757b832..84dba45c3c 100644
--- a/src/net/url/url_test.go
+++ b/src/net/url/url_test.go
@@ -2062,3 +2062,59 @@ func BenchmarkPathUnescape(b *testing.B) {
})
}
}
+
+func TestJoinPath(t *testing.T) {
+ tests := []struct {
+ base string
+ elem []string
+ out string
+ }{
+ {
+ base: "https://go.googlesource.com",
+ elem: []string{"go"},
+ out: "https://go.googlesource.com/go",
+ },
+ {
+ base: "https://go.googlesource.com/a/b/c",
+ elem: []string{"../../../go"},
+ out: "https://go.googlesource.com/go",
+ },
+ {
+ base: "https://go.googlesource.com/",
+ elem: []string{"./go"},
+ out: "https://go.googlesource.com/go",
+ },
+ {
+ base: "https://go.googlesource.com//",
+ elem: []string{"/go"},
+ out: "https://go.googlesource.com/go",
+ },
+ {
+ base: "https://go.googlesource.com//",
+ elem: []string{"/go", "a", "b", "c"},
+ out: "https://go.googlesource.com/go/a/b/c",
+ },
+ {
+ base: "http://[fe80::1%en0]:8080/",
+ elem: []string{"/go"},
+ },
+ }
+ for _, tt := range tests {
+ wantErr := "nil"
+ if tt.out == "" {
+ wantErr = "non-nil error"
+ }
+ if out, err := JoinPath(tt.base, tt.elem...); out != tt.out || (err == nil) != (tt.out != "") {
+ t.Errorf("JoinPath(%q, %q) = %q, %v, want %q, %v", tt.base, tt.elem, out, err, tt.out, wantErr)
+ }
+ var out string
+ u, err := Parse(tt.base)
+ if err == nil {
+ u = u.JoinPath(tt.elem...)
+ out = u.String()
+ }
+ if out != tt.out || (err == nil) != (tt.out != "") {
+ t.Errorf("Parse(%q).JoinPath(%q) = %q, %v, want %q, %v", tt.base, tt.elem, out, err, tt.out, wantErr)
+ }
+ }
+}
From 46f352de2dc80657664431ebb04f89a2fad579c5 Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Mon, 7 Mar 2022 21:49:26 -0800
Subject: [PATCH 062/276] spec: remove notion of specific types
Specific types were introduced to explain rules for operands of
type parameter type. Specific types are really an implementation
mechanism to represent (possibly infinite) type sets in the machine;
they are not needed in the specification.
A specific type is either standing for a single named or unnamed
type, or it is the underlying (unnamed) type of an infinite set of
types. Each rule that applies to a type T of the set of specific
types must also apply to all types T' in the type set for which T
is a representative of. Thus, in the spec we can simply refer to
the type set directly, infinite or not.
Rather then excluding operands with empty type sets in each instance,
leave unspecified what happens when such an operand is used. Instead
give an implementation some leeway with an implementation restriction.
(The implementation restriction also needs to be formulated for types,
such as in conversions, which technically are not "operands". Left for
another CL.)
Minor: Remove the two uses of the word "concrete" to refer to non-
interface types; instead just say "non-interface type" for clarity.
Change-Id: I67ac89a640c995369c9d421a03820a0c0435835a
Reviewed-on: https://go-review.googlesource.com/c/go/+/390694
Trust: Robert Griesemer
Reviewed-by: Ian Lance Taylor
---
doc/go_spec.html | 138 +++++++++++++----------------------------------
1 file changed, 38 insertions(+), 100 deletions(-)
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 6278b8252d..000b0c5e67 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
@@ -761,7 +761,7 @@ type given in its declaration, the type provided in the
new call or composite literal, or the type of
an element of a structured variable.
Variables of interface type also have a distinct dynamic type,
-which is the concrete type of the value assigned to the variable at run time
+which is the (non-interface) type of the value assigned to the variable at run time
(unless the value is the predeclared identifier nil,
which has no type).
The dynamic type may vary during execution but values stored in interface
@@ -1799,70 +1799,6 @@ interface{ chan int | chan<- string } // channels have different element
interface{ <-chan int | chan<- int } // directional channels have different directions
--[The definition of specific types is not quite correct yet.] -
- -
-An interface specification that contains type elements
-defines a (possibly empty) set of specific types.
-Loosely speaking, these are the types T that appear in the
-interface definition in terms of the form T, ~T,
-or in unions of such terms.
-
-More precisely, for a given interface, the set of specific types corresponds to -the set 𝑅 of representative types of the interface, if 𝑅 is non-empty and finite. -Otherwise, if 𝑅 is empty or infinite, the interface has no specific types. -
- --For a given interface, type element or type term, the set 𝑅 of representative types is defined as follows: -
- -T or a term of the form ~T,
- 𝑅 is the set consisting of the type T.
- t1|t2|…|tn,
- 𝑅 is the union of the representative types of the terms.
- -An interface may have specific types even if its type set -is empty. -
- --Examples of interfaces with their specific types: -
- -
-interface{} // no specific types
-interface{ int } // int
-interface{ ~string } // string
-interface{ int|~string } // int, string
-interface{ Celsius|Kelvin } // Celsius, Kelvin
-interface{ float64|any } // no specific types (union is all types)
-interface{ int; m() } // int (but type set is empty because int has no method m)
-interface{ ~int; m() } // int (but type set is infinite because many integer types have a method m)
-interface{ int; any } // int
-interface{ int; string } // no specific types (intersection is empty)
-
-
@@ -2002,25 +1938,24 @@ by a value of type T.
-Additionally, if x's type V or T are type parameters
-with specific types, x
+Additionally, if x's type V or T are type parameters, x
is assignable to a variable of type T if one of the following conditions applies:
x is the predeclared identifier nil, T is
-a type parameter, and x is assignable to each specific type of
-T.
+a type parameter, and x is assignable to each type in
+T's type set.
V is not a named type, T is
-a type parameter, and x is assignable to each specific type of
-T.
+a type parameter, and x is assignable to each type in
+T's type set.
V is a type parameter and T is not a named type,
-and values of each specific type of V are assignable
+and values of each type in V's type set are assignable
to T.
T's component type (float32
-If T is a type parameter with specific types,
+If T is a type parameter,
x is representable by a value of type T if x is representable
-by a value of each specific type of T.
+by a value of each type in T's type set.
@@ -2705,7 +2640,7 @@ other interfaces based on their type sets. But this should get us going for now.
The predeclared
interface type comparable
-denotes the set of all concrete (non-interface) types that are
+denotes the set of all non-interface types that are
comparable. Specifically,
a type T implements comparable if:
@@ -3037,6 +2972,14 @@ The blank identifier may appear as an
operand only on the left-hand side of an assignment.
+
+Implementation restriction: A compiler need not report an error if an operand's
+type is a type parameter with an empty
+type set. Functions with such type parameters
+cannot be instantiated; any attempt will lead
+to an error at the instantiation site.
+
+
Qualified identifiers
@@ -3819,20 +3762,19 @@ For a of map type M:
For a of type parameter type P:
- P must have specific types.
- The index expression
a[x] must be valid for values
- of all specific types of P.
- - The element types of all specific types of
P must be identical.
+ of all types in P's type set.
+ - The element types of all types in
P's type set must be identical.
In this context, the element type of a string type is byte.
- - If there is a map type among the specific types of
P,
- all specific types must be map types, and the respective key types
+ - If there is a map type in the type set of
P,
+ all types in that type set must be map types, and the respective key types
must be all identical.
a[x] is the array, slice, or string element at index x,
or the map element with key x of the type argument
that P is instantiated with, and the type of a[x] is
the type of the (identical) element types.
- a[x] may not be assigned to if the specific types of P
- include string types.
+ a[x] may not be assigned to if P's type set
+ includes string types.
@@ -4728,6 +4670,10 @@ and the other operand is not, the constant is implicitly
to the type of the other operand.
+
+[The rules for shifts need adjustments for type parameters. Issue #51182.]
+
+
The right operand in a shift expression must have integer type
or be an untyped constant representable by a
@@ -4832,9 +4778,8 @@ The bitwise logical and shift operators apply to integers only.
-Excluding shifts, if the operand type is a type parameter,
-it must have specific types, and the operator must
-apply to each specific type.
+If the operand type is a type parameter,
+the operator must apply to each type in that type set.
The operands are represented as values of the type argument that the type parameter
is instantiated with, and the operation is computed
with the precision of that type argument. For example, given the function:
@@ -4857,11 +4802,6 @@ are computed with float32 or float64 precision,
respectively, depending on the type argument for F.
-
-For shifts, the core type of both operands must be
-an integer.
-
-
Integer operators
@@ -5374,23 +5314,23 @@ in any of these cases:
Additionally, if T or x's type V are type
-parameters with specific types, x
+parameters, x
can also be converted to type T if one of the following conditions applies:
-
Both
V and T are type parameters and a value of each
-specific type of V can be converted to each specific type
-of T.
+type in V's type set can be converted to each type in T's
+type set.
-
Only
V is a type parameter and a value of each
-specific type of V can be converted to T.
+type in V's type set can be converted to T.
-
Only
T is a type parameter and x can be converted to each
-specific type of T.
+type in T's type set.
@@ -7085,9 +7025,8 @@ cap(s) [n]T, *[n]T array length (== n)
If the argument type is a type parameter P,
-P must have specific types, and
the call len(e) (or cap(e) respectively) must be valid for
-each specific type of P.
+each type in P's type set.
The result is the length (or capacity, respectively) of the argument whose type
corresponds to the type argument with which P was
instantiated.
@@ -7309,8 +7248,7 @@ delete(m, k) // remove element m[k] from map m
If the type of m is a type parameter,
-it must have specific types, all specific types
-must be maps, and they must all have identical key types.
+all types in that type set must be maps, and they must all have identical key types.
From 6fb07317e5e7997a1e44ccb6984229c77dc186a3 Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Tue, 8 Mar 2022 13:11:04 -0800
Subject: [PATCH 063/276] spec: more adjustments/corrections
- Change section title from "Type parameters lists" to
"Type parameter declarations" as the enclosing section
is about declarations.
- Correct section on parsing ambiguity in type parameter
lists.
- Rephrase paragraphs on type parameters for method receivers
and adjust examples.
- Remove duplicate prose in section on function argument type
inference.
- Clarified "after substitution" column in Instantiations section.
Change-Id: Id76be9804ad96a3f1221e5c4942552dde015dfcb
Reviewed-on: https://go-review.googlesource.com/c/go/+/390994
Trust: Robert Griesemer
Reviewed-by: Ian Lance Taylor
---
doc/go_spec.html | 92 +++++++++++++++++++++++++-----------------------
1 file changed, 47 insertions(+), 45 deletions(-)
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 000b0c5e67..cfbb17e3bb 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -807,7 +807,7 @@ TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType
The language predeclares certain type names.
Others are introduced with type declarations
-or type parameter lists.
+or type parameter lists.
Composite types—array, struct, pointer, function,
interface, slice, map, and channel types—may be constructed using
type literals.
@@ -1459,7 +1459,7 @@ type Float interface {
-In a union, a term cannot be a type parameter, and the type sets of all
+In a union, a term cannot be a type parameter, and the type sets of all
non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty).
Given a type parameter P:
@@ -1769,7 +1769,7 @@ depending on the direction of the directional channels present.
By definition, a core type is never a defined type,
-type parameter, or
+type parameter, or
interface type.
@@ -1965,7 +1965,7 @@ to T.
A constant x is representable
by a value of type T,
-where T is not a type parameter,
+where T is not a type parameter,
if one of the following conditions applies:
@@ -2105,6 +2105,7 @@ Blocks nest and influence scoping.
A declaration binds a non-blank identifier to a
constant,
type,
+type parameter,
variable,
function,
label, or
@@ -2502,7 +2503,7 @@ func (tz TimeZone) String() string {
-If the type definition specifies type parameters,
+If the type definition specifies type parameters,
the type name denotes a generic type.
Generic types must be instantiated when they
are used.
@@ -2538,7 +2539,7 @@ present in the generic type definition.
func (l *List[T]) Len() int { … }
-
Type parameter lists
+Type parameter declarations
A type parameter list declares the type parameters of a generic function or type declaration.
@@ -2577,22 +2578,22 @@ has a corresponding (meta-)type which is called its
A parsing ambiguity arises when the type parameter list for a generic type
-declares a single type parameter with a type constraint of the form *C
-or (C) where C is not a (possibly parenthesized)
-type literal:
+declares a single type parameter P with a constraint C
+such that the text P C forms a valid expression:
type T[P *C] …
type T[P (C)] …
+type T[P *C|Q] …
+…
-In these rare cases, the type parameter declaration is indistinguishable from
-the expressions P*C or P(C) and the type declaration
-is parsed as an array type declaration.
-To resolve the ambiguity, embed the constraint in an interface or use a trailing
-comma:
+In these rare cases, the type parameter list is indistinguishable from an
+expression and the type declaration is parsed as an array type declaration.
+To resolve the ambiguity, embed the constraint in an
+interface or use a trailing comma:
@@ -2606,6 +2607,11 @@ of a method declaration associated
with a generic type.
+
+
Type constraints
@@ -2625,10 +2631,10 @@ the enclosing interface{ … } may be omitted for convenience:
-[T *P] // = [T interface{*P}]
-[T ~int] // = [T interface{~int}]
-[T int|string] // = [T interface{int|string}]
-type Constraint ~int // illegal: ~int is not inside a type parameter list
+[T []P] // = [T interface{[]P}]
+[T ~int] // = [T interface{~int}]
+[T int|string] // = [T interface{int|string}]
+type Constraint ~int // illegal: ~int is not inside a type parameter list
-Earlier version
-
-
-For the pre-Go1.18 specification without generics support see
-The Go Programming Language Specification.
-
-
Introduction
-This is a reference manual for the Go programming language. For
-more information and other documents, see golang.org.
+This is the reference manual for the Go programming language.
+The pre-Go1.18 version, without generics, can be found
+here.
+For more information and other documents, see golang.org.
@@ -4668,10 +4663,6 @@ and the other operand is not, the constant is implicitly
to the type of the other operand.
-
-[The rules for shifts need adjustments for type parameters. Issue #51182.]
-
-
The right operand in a shift expression must have integer type
or be an untyped constant representable by a
@@ -7257,10 +7248,6 @@ does not exist, delete is a no-op.
Manipulating complex numbers
-
-[We don't support generic arguments for these built-ins for Go 1.18.]
-
-
Three functions assemble and disassemble complex numbers.
The built-in function complex constructs a complex
@@ -7323,6 +7310,10 @@ const c = imag(b) // untyped constant -1.4
_ = imag(3 << s) // illegal: 3 assumes complex type, cannot shift
+
+Arguments of type parameter type are not permitted.
+
+
Handling panics
Two built-in functions, panic and recover,
From fe75fe3c7ae99713ed4e452ea8a4fcb589517dd9 Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Thu, 10 Mar 2022 17:40:01 -0800
Subject: [PATCH 079/276] spec: various minor clarifications
- Allow for a type parameter as length/capacity to make.
- Be slightly more precise in prose for append.
- Add a couple of links.
Change-Id: Ib97e528bab1ab55d271beeeb53d9bb7a07047b9b
Reviewed-on: https://go-review.googlesource.com/c/go/+/391754
Trust: Robert Griesemer
Reviewed-by: Ian Lance Taylor
---
doc/go_spec.html | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 9b37e0ded0..ad12fcfaa9 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -7116,8 +7116,9 @@ make(T, n) channel buffered channel of type T, buffer size n
-Each of the size arguments n and m must be of integer type
-or an untyped constant.
+Each of the size arguments n and m must be of integer type,
+have a type set containing only integer types,
+or be an untyped constant.
A constant size argument must be non-negative and representable
by a value of type int; if it is an untyped constant it is given type int.
If both n and m are provided and are constant, then
@@ -7154,9 +7155,9 @@ by the arguments overlaps.
The variadic function append
appends zero or more values x to a slice s
-and returns the resulting slice.
+and returns the resulting slice of the same type as s.
The core type of s must be a slice
-of the form []E.
+of type []E.
The values x are passed to a parameter of type ...E
and the respective parameter
passing rules apply.
@@ -7166,7 +7167,7 @@ followed by .... This form appends the bytes of the string.
-append(s S, x ...E) S // E is the element type of the core type of S
+append(s S, x ...E) S // core type of S is []E
@@ -7922,11 +7923,17 @@ func Add(ptr Pointer, len IntegerType) Pointer
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
+
+
A Pointer is a pointer type but a Pointer
value may not be dereferenced.
-Any pointer or value of underlying type uintptr can be converted to
-a type of underlying type Pointer and vice versa.
+Any pointer or value of underlying type uintptr can be
+converted to a type of underlying type Pointer and vice versa.
The effect of converting between Pointer and uintptr is implementation-defined.
@@ -7973,7 +7980,8 @@ uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0
A (variable of) type T has variable size if T
-is a type parameter, or if it is an array or struct type containing elements
+is a type parameter, or if it is an
+array or struct type containing elements
or fields of variable size. Otherwise the size is constant.
Calls to Alignof, Offsetof, and Sizeof
are compile-time constant expressions of
From c1f22134f22158ebeebf450357f711eb22fab202 Mon Sep 17 00:00:00 2001
From: Tobias Klauser
Date: Thu, 10 Mar 2022 09:28:09 +0100
Subject: [PATCH 080/276] runtime/pprof, syscall: report MaxRSS on all unix
platforms
All unix platforms currently supported by Go provide the getrusage
syscall. On aix and solaris the Getrusage syscall wrapper is not
available yet, so add and use it to report MaxRSS in memory profiles.
Change-Id: Ie880a3058171031fd2e12ccf9adfb85ce18858b1
Reviewed-on: https://go-review.googlesource.com/c/go/+/391434
Trust: Tobias Klauser
Run-TryBot: Tobias Klauser
TryBot-Result: Gopher Robot
Reviewed-by: Michael Pratt
Trust: Michael Pratt
Reviewed-by: Ian Lance Taylor
---
src/runtime/pprof/pprof_norusage.go | 2 +-
src/runtime/pprof/pprof_rusage.go | 6 ++++--
src/runtime/pprof/rusage_test.go | 2 +-
src/syscall/syscall_aix.go | 1 +
src/syscall/syscall_solaris.go | 1 +
src/syscall/zsyscall_aix_ppc64.go | 13 +++++++++++++
src/syscall/zsyscall_solaris_amd64.go | 13 +++++++++++++
7 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/src/runtime/pprof/pprof_norusage.go b/src/runtime/pprof/pprof_norusage.go
index cbc5176cfa..3d6052519c 100644
--- a/src/runtime/pprof/pprof_norusage.go
+++ b/src/runtime/pprof/pprof_norusage.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.
-//go:build !darwin && !linux
+//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris
package pprof
diff --git a/src/runtime/pprof/pprof_rusage.go b/src/runtime/pprof/pprof_rusage.go
index 46263fedd9..7df81eca23 100644
--- a/src/runtime/pprof/pprof_rusage.go
+++ b/src/runtime/pprof/pprof_rusage.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.
-//go:build darwin || linux
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
package pprof
@@ -17,10 +17,12 @@ import (
func addMaxRSS(w io.Writer) {
var rssToBytes uintptr
switch runtime.GOOS {
- case "linux", "android":
+ case "aix", "android", "dragonfly", "freebsd", "linux", "netbsd", "openbsd":
rssToBytes = 1024
case "darwin", "ios":
rssToBytes = 1
+ case "illumos", "solaris":
+ rssToBytes = uintptr(syscall.Getpagesize())
default:
panic("unsupported OS")
}
diff --git a/src/runtime/pprof/rusage_test.go b/src/runtime/pprof/rusage_test.go
index b0d651e0eb..f274d0caa3 100644
--- a/src/runtime/pprof/rusage_test.go
+++ b/src/runtime/pprof/rusage_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build darwin || freebsd || linux || netbsd || openbsd
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
package pprof
diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go
index 739c55f179..acc19b4db3 100644
--- a/src/syscall/syscall_aix.go
+++ b/src/syscall/syscall_aix.go
@@ -594,6 +594,7 @@ func PtraceDetach(pid int) (err error) { return ptrace64(PT_DETACH, int64(pid),
//sys Getppid() (ppid int)
//sys Getpriority(which int, who int) (n int, err error)
//sysnb Getrlimit(which int, lim *Rlimit) (err error)
+//sysnb Getrusage(who int, rusage *Rusage) (err error)
//sysnb Getuid() (uid int)
//sys Kill(pid int, signum Signal) (err error)
//sys Lchown(path string, uid int, gid int) (err error)
diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go
index d01070b2ec..38c82a11e8 100644
--- a/src/syscall/syscall_solaris.go
+++ b/src/syscall/syscall_solaris.go
@@ -421,6 +421,7 @@ func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags i
//sys Getppid() (ppid int)
//sys Getpriority(which int, who int) (n int, err error)
//sysnb Getrlimit(which int, lim *Rlimit) (err error)
+//sysnb Getrusage(who int, rusage *Rusage) (err error)
//sysnb Gettimeofday(tv *Timeval) (err error)
//sysnb Getuid() (uid int)
//sys Kill(pid int, signum Signal) (err error)
diff --git a/src/syscall/zsyscall_aix_ppc64.go b/src/syscall/zsyscall_aix_ppc64.go
index 94f1b4371c..2a3411374f 100644
--- a/src/syscall/zsyscall_aix_ppc64.go
+++ b/src/syscall/zsyscall_aix_ppc64.go
@@ -62,6 +62,7 @@ import "unsafe"
//go:cgo_import_dynamic libc_Getppid getppid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Getpriority getpriority "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Getrlimit getrlimit "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_Getrusage getrusage "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Getuid getuid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Kill kill "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Lchown lchown "libc.a/shr_64.o"
@@ -154,6 +155,7 @@ import "unsafe"
//go:linkname libc_Getppid libc_Getppid
//go:linkname libc_Getpriority libc_Getpriority
//go:linkname libc_Getrlimit libc_Getrlimit
+//go:linkname libc_Getrusage libc_Getrusage
//go:linkname libc_Getuid libc_Getuid
//go:linkname libc_Kill libc_Kill
//go:linkname libc_Lchown libc_Lchown
@@ -249,6 +251,7 @@ var (
libc_Getppid,
libc_Getpriority,
libc_Getrlimit,
+ libc_Getrusage,
libc_Getuid,
libc_Kill,
libc_Lchown,
@@ -925,6 +928,16 @@ func Getrlimit(which int, lim *Rlimit) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func Getrusage(who int, rusage *Rusage) (err error) {
+ _, _, e1 := rawSyscall6(uintptr(unsafe.Pointer(&libc_Getrusage)), 2, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0, 0, 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func Getuid() (uid int) {
r0, _, _ := rawSyscall6(uintptr(unsafe.Pointer(&libc_Getuid)), 0, 0, 0, 0, 0, 0, 0)
uid = int(r0)
diff --git a/src/syscall/zsyscall_solaris_amd64.go b/src/syscall/zsyscall_solaris_amd64.go
index dad0580027..7b012bf9bb 100644
--- a/src/syscall/zsyscall_solaris_amd64.go
+++ b/src/syscall/zsyscall_solaris_amd64.go
@@ -35,6 +35,7 @@ import "unsafe"
//go:cgo_import_dynamic libc_Getppid getppid "libc.so"
//go:cgo_import_dynamic libc_Getpriority getpriority "libc.so"
//go:cgo_import_dynamic libc_Getrlimit getrlimit "libc.so"
+//go:cgo_import_dynamic libc_Getrusage getrusage "libc.so"
//go:cgo_import_dynamic libc_Gettimeofday gettimeofday "libc.so"
//go:cgo_import_dynamic libc_Getuid getuid "libc.so"
//go:cgo_import_dynamic libc_Kill kill "libc.so"
@@ -120,6 +121,7 @@ import "unsafe"
//go:linkname libc_Getppid libc_Getppid
//go:linkname libc_Getpriority libc_Getpriority
//go:linkname libc_Getrlimit libc_Getrlimit
+//go:linkname libc_Getrusage libc_Getrusage
//go:linkname libc_Gettimeofday libc_Gettimeofday
//go:linkname libc_Getuid libc_Getuid
//go:linkname libc_Kill libc_Kill
@@ -208,6 +210,7 @@ var (
libc_Getppid,
libc_Getpriority,
libc_Getrlimit,
+ libc_Getrusage,
libc_Gettimeofday,
libc_Getuid,
libc_Kill,
@@ -580,6 +583,16 @@ func Getrlimit(which int, lim *Rlimit) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func Getrusage(who int, rusage *Rusage) (err error) {
+ _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&libc_Getrusage)), 2, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0, 0, 0, 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func Gettimeofday(tv *Timeval) (err error) {
_, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&libc_Gettimeofday)), 1, uintptr(unsafe.Pointer(tv)), 0, 0, 0, 0, 0)
if e1 != 0 {
From 7b1ba972dc5687f6746b2299b047f44e38bc6686 Mon Sep 17 00:00:00 2001
From: "Paul E. Murphy"
Date: Mon, 25 Oct 2021 16:51:55 -0500
Subject: [PATCH 081/276] cmd/asm: add support for bdnz/bdz extended mnemonics
on PPC64
Support BDNZ and BDZ mnemonics, they are commonly used
POWER instructions. The raw BC mnemonic is not easy
to read.
Likewise, cleanup code surrounding these changes.
Change-Id: I72f1dad5013f7856bd0dd320bfb17b5a9f3c69ee
Reviewed-on: https://go-review.googlesource.com/c/go/+/390696
Reviewed-by: Lynn Boger
Trust: Paul Murphy
Run-TryBot: Paul Murphy
TryBot-Result: Gopher Robot
---
src/cmd/asm/internal/arch/ppc64.go | 2 +-
src/cmd/asm/internal/asm/testdata/ppc64.s | 28 ++++++++++++++---------
src/cmd/internal/obj/ppc64/a.out.go | 11 +++++----
src/cmd/internal/obj/ppc64/anames.go | 2 ++
src/cmd/internal/obj/ppc64/asm9.go | 24 ++++++++++++-------
5 files changed, 43 insertions(+), 24 deletions(-)
diff --git a/src/cmd/asm/internal/arch/ppc64.go b/src/cmd/asm/internal/arch/ppc64.go
index 3139665ba5..616e189b1a 100644
--- a/src/cmd/asm/internal/arch/ppc64.go
+++ b/src/cmd/asm/internal/arch/ppc64.go
@@ -15,7 +15,7 @@ import (
func jumpPPC64(word string) bool {
switch word {
- case "BC", "BCL", "BEQ", "BGE", "BGT", "BL", "BLE", "BLT", "BNE", "BR", "BVC", "BVS", "CALL", "JMP":
+ case "BC", "BCL", "BEQ", "BGE", "BGT", "BL", "BLE", "BLT", "BNE", "BR", "BVC", "BVS", "BDNZ", "BDZ", "CALL", "JMP":
return true
}
return false
diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s
index c140fd025a..5452668791 100644
--- a/src/cmd/asm/internal/asm/testdata/ppc64.s
+++ b/src/cmd/asm/internal/asm/testdata/ppc64.s
@@ -751,17 +751,23 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVD XER, R3 // 7c6102a6
MOVFL CR3, CR1 // 4c8c0000
- MOVW CR0, R1 // 7c380026
- MOVW CR7, R1 // 7c301026
- MOVW CR, R1 // 7c200026
+ MOVW CR0, R1 // 7c380026
+ MOVW CR7, R1 // 7c301026
+ MOVW CR, R1 // 7c200026
- MOVW R1, CR // 7c2ff120
- MOVFL R1, CR // 7c2ff120
- MOVW R1, CR2 // 7c320120
- MOVFL R1, CR2 // 7c320120
- MOVFL R1, $255 // 7c2ff120
- MOVFL R1, $1 // 7c301120
- MOVFL R1, $128 // 7c380120
- MOVFL R1, $3 // 7c203120
+ MOVW R1, CR // 7c2ff120
+ MOVFL R1, CR // 7c2ff120
+ MOVW R1, CR2 // 7c320120
+ MOVFL R1, CR2 // 7c320120
+ MOVFL R1, $255 // 7c2ff120
+ MOVFL R1, $1 // 7c301120
+ MOVFL R1, $128 // 7c380120
+ MOVFL R1, $3 // 7c203120
+
+ // Verify supported bdnz/bdz encodings.
+ BC 16,0,0(PC) // BC $16,R0,0(PC) // 42000000
+ BDNZ 0(PC) // 42000000
+ BDZ 0(PC) // 42400000
+ BC 18,0,0(PC) // BC $18,R0,0(PC) // 42400000
RET
diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go
index 1e74e64a29..25081efcee 100644
--- a/src/cmd/internal/obj/ppc64/a.out.go
+++ b/src/cmd/internal/obj/ppc64/a.out.go
@@ -362,13 +362,14 @@ const (
BI_LT = 0
BI_GT = 1
BI_EQ = 2
- BI_OVF = 3
+ BI_FU = 3
)
// Common values for the BO field.
const (
BO_BCTR = 16 // decrement ctr, branch on ctr != 0
+ BO_NOTBCTR = 18 // decrement ctr, branch on ctr == 0
BO_BCR = 12 // branch on cr value
BO_BCRBCTR = 8 // decrement ctr, branch on ctr != 0 and cr value
BO_NOTBCR = 4 // branch on not cr value
@@ -480,9 +481,11 @@ const (
ABGT
ABLE // not GT = L/E/U
ABLT
- ABNE // not EQ = L/G/U
- ABVC // Unordered-clear
- ABVS // Unordered-set
+ ABNE // not EQ = L/G/U
+ ABVC // Branch if float not unordered (also branch on not summary overflow)
+ ABVS // Branch if float unordered (also branch on summary overflow)
+ ABDNZ // Decrement CTR, and branch if CTR != 0
+ ABDZ // Decrement CTR, and branch if CTR == 0
ACMP
ACMPU
ACMPEQB
diff --git a/src/cmd/internal/obj/ppc64/anames.go b/src/cmd/internal/obj/ppc64/anames.go
index 0da73ca91e..7521a92ab4 100644
--- a/src/cmd/internal/obj/ppc64/anames.go
+++ b/src/cmd/internal/obj/ppc64/anames.go
@@ -42,6 +42,8 @@ var Anames = []string{
"BNE",
"BVC",
"BVS",
+ "BDNZ",
+ "BDZ",
"CMP",
"CMPU",
"CMPEQB",
diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go
index 70ce9050b6..50c9b37f02 100644
--- a/src/cmd/internal/obj/ppc64/asm9.go
+++ b/src/cmd/internal/obj/ppc64/asm9.go
@@ -305,6 +305,7 @@ var optab = []Optab{
{as: ABC, a1: C_SCON, a2: C_REG, a6: C_LR, type_: 18, size: 4},
{as: ABC, a1: C_SCON, a2: C_REG, a6: C_CTR, type_: 18, size: 4},
{as: ABC, a6: C_ZOREG, type_: 15, size: 8},
+ {as: ABDNZ, a6: C_SBRA, type_: 16, size: 4},
{as: ASYNC, type_: 46, size: 4},
{as: AWORD, a1: C_LCON, type_: 40, size: 4},
{as: ADWORD, a1: C_64CON, type_: 31, size: 8},
@@ -1778,6 +1779,9 @@ func buildop(ctxt *obj.Link) {
case ABC:
opset(ABCL, r0)
+ case ABDNZ:
+ opset(ABDZ, r0)
+
case AEXTSB: /* op Rs, Ra */
opset(AEXTSBCC, r0)
@@ -4875,21 +4879,25 @@ func (c *ctxt9) opirr(a obj.As) uint32 {
return OPVCC(16, 0, 0, 0) | 1
case ABEQ:
- return AOP_RRR(16<<26, 12, 2, 0)
+ return AOP_RRR(16<<26, BO_BCR, BI_EQ, 0)
case ABGE:
- return AOP_RRR(16<<26, 4, 0, 0)
+ return AOP_RRR(16<<26, BO_NOTBCR, BI_LT, 0)
case ABGT:
- return AOP_RRR(16<<26, 12, 1, 0)
+ return AOP_RRR(16<<26, BO_BCR, BI_GT, 0)
case ABLE:
- return AOP_RRR(16<<26, 4, 1, 0)
+ return AOP_RRR(16<<26, BO_NOTBCR, BI_GT, 0)
case ABLT:
- return AOP_RRR(16<<26, 12, 0, 0)
+ return AOP_RRR(16<<26, BO_BCR, BI_LT, 0)
case ABNE:
- return AOP_RRR(16<<26, 4, 2, 0)
+ return AOP_RRR(16<<26, BO_NOTBCR, BI_EQ, 0)
case ABVC:
- return AOP_RRR(16<<26, 4, 3, 0) // apparently unordered-clear
+ return AOP_RRR(16<<26, BO_NOTBCR, BI_FU, 0)
case ABVS:
- return AOP_RRR(16<<26, 12, 3, 0) // apparently unordered-set
+ return AOP_RRR(16<<26, BO_BCR, BI_FU, 0)
+ case ABDZ:
+ return AOP_RRR(16<<26, BO_NOTBCTR, 0, 0)
+ case ABDNZ:
+ return AOP_RRR(16<<26, BO_BCTR, 0, 0)
case ACMP:
return OPVCC(11, 0, 0, 0) | 1<<21 /* L=1 */
From baf61e4a67789e20f019507287a324cca06bed42 Mon Sep 17 00:00:00 2001
From: eh-steve
Date: Fri, 11 Mar 2022 21:14:27 +0000
Subject: [PATCH 082/276] encoding/hex: implement Decode with a lookup table
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Implement hex decode using a 256 byte lookup table instead of branching logic.
In happy flow, uses 3x 64 byte (or 5x 32 byte) cache lines.
name old time/op new time/op delta
Decode/256-64 223ns ± 3% 135ns ± 2% -39.64% (p=0.000 n=8+8)
Decode/1024-64 872ns ± 2% 512ns ± 2% -41.25% (p=0.000 n=8+8)
Decode/4096-64 3.43µs ± 1% 2.01µs ± 2% -41.31% (p=0.001 n=7+7)
Decode/16384-64 13.9µs ± 1% 8.0µs ± 1% -42.69% (p=0.000 n=8+7)
name old speed new speed delta
Decode/256-64 1.15GB/s ± 3% 1.90GB/s ± 2% +65.66% (p=0.000 n=8+8)
Decode/1024-64 1.17GB/s ± 2% 2.00GB/s ± 2% +70.22% (p=0.000 n=8+8)
Decode/4096-64 1.20GB/s ± 1% 2.04GB/s ± 2% +70.39% (p=0.001 n=7+7)
Decode/16384-64 1.18GB/s ± 1% 2.06GB/s ± 1% +74.49% (p=0.000 n=8+7)
Also reduces amd64 object size by 766 bytes, despite the extra RODATA due to removal of `fromHexChar()` and duplicated inlined versions of it and simplification of `Decode()`.
Change-Id: I0988c7a30562ec154eff11db6e27954e0ce2b611
GitHub-Last-Rev: 64818018afc83ab07ec128a46aaea6a16f11400e
GitHub-Pull-Request: golang/go#51432
Reviewed-on: https://go-review.googlesource.com/c/go/+/390037
Reviewed-by: Ian Lance Taylor
Reviewed-by: Daniel Martí
Trust: Daniel Martí
Run-TryBot: Daniel Martí
TryBot-Result: Gopher Robot
---
src/encoding/hex/hex.go | 55 ++++++++++++++++++++++++-----------------
1 file changed, 32 insertions(+), 23 deletions(-)
diff --git a/src/encoding/hex/hex.go b/src/encoding/hex/hex.go
index fbba78ffd2..375f583170 100644
--- a/src/encoding/hex/hex.go
+++ b/src/encoding/hex/hex.go
@@ -12,7 +12,26 @@ import (
"strings"
)
-const hextable = "0123456789abcdef"
+const (
+ hextable = "0123456789abcdef"
+ reverseHexTable = "" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff" +
+ "\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+)
// EncodedLen returns the length of an encoding of n source bytes.
// Specifically, it returns n * 2.
@@ -58,13 +77,16 @@ func DecodedLen(x int) int { return x / 2 }
func Decode(dst, src []byte) (int, error) {
i, j := 0, 1
for ; j < len(src); j += 2 {
- a, ok := fromHexChar(src[j-1])
- if !ok {
- return i, InvalidByteError(src[j-1])
+ p := src[j-1]
+ q := src[j]
+
+ a := reverseHexTable[p]
+ b := reverseHexTable[q]
+ if a > 0x0f {
+ return i, InvalidByteError(p)
}
- b, ok := fromHexChar(src[j])
- if !ok {
- return i, InvalidByteError(src[j])
+ if b > 0x0f {
+ return i, InvalidByteError(q)
}
dst[i] = (a << 4) | b
i++
@@ -72,7 +94,7 @@ func Decode(dst, src []byte) (int, error) {
if len(src)%2 == 1 {
// Check for invalid char before reporting bad length,
// since the invalid char (if present) is an earlier problem.
- if _, ok := fromHexChar(src[j-1]); !ok {
+ if reverseHexTable[src[j-1]] > 0x0f {
return i, InvalidByteError(src[j-1])
}
return i, ErrLength
@@ -80,20 +102,6 @@ func Decode(dst, src []byte) (int, error) {
return i, nil
}
-// fromHexChar converts a hex character into its value and a success flag.
-func fromHexChar(c byte) (byte, bool) {
- switch {
- case '0' <= c && c <= '9':
- return c - '0', true
- case 'a' <= c && c <= 'f':
- return c - 'a' + 10, true
- case 'A' <= c && c <= 'F':
- return c - 'A' + 10, true
- }
-
- return 0, false
-}
-
// EncodeToString returns the hexadecimal encoding of src.
func EncodeToString(src []byte) string {
dst := make([]byte, EncodedLen(len(src)))
@@ -185,7 +193,8 @@ func (d *decoder) Read(p []byte) (n int, err error) {
numRead, d.err = d.r.Read(d.arr[numCopy:])
d.in = d.arr[:numCopy+numRead]
if d.err == io.EOF && len(d.in)%2 != 0 {
- if _, ok := fromHexChar(d.in[len(d.in)-1]); !ok {
+
+ if a := reverseHexTable[d.in[len(d.in)-1]]; a > 0x0f {
d.err = InvalidByteError(d.in[len(d.in)-1])
} else {
d.err = io.ErrUnexpectedEOF
From 842d37ee5f86f12aa096b750adbd2debd9129fcb Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Fri, 11 Mar 2022 18:29:37 -0800
Subject: [PATCH 083/276] syscall: add race annotations to Pread and Pwrite
Fixes #51618
Change-Id: Ife894d8c313dce8c4929f40fa0ac90a069f77a89
Reviewed-on: https://go-review.googlesource.com/c/go/+/391954
Trust: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gopher Robot
Reviewed-by: Keith Randall
---
src/runtime/race/testdata/mop_test.go | 14 +++++++++-
src/syscall/syscall_aix.go | 4 +--
src/syscall/syscall_darwin.go | 4 +--
src/syscall/syscall_dragonfly.go | 4 +--
src/syscall/syscall_freebsd.go | 4 +--
src/syscall/syscall_linux_386.go | 4 +--
src/syscall/syscall_linux_amd64.go | 4 +--
src/syscall/syscall_linux_arm.go | 4 +--
src/syscall/syscall_linux_arm64.go | 4 +--
src/syscall/syscall_linux_mips64x.go | 4 +--
src/syscall/syscall_linux_mipsx.go | 4 +--
src/syscall/syscall_linux_ppc64x.go | 4 +--
src/syscall/syscall_linux_riscv64.go | 4 +--
src/syscall/syscall_linux_s390x.go | 4 +--
src/syscall/syscall_netbsd.go | 4 +--
src/syscall/syscall_openbsd.go | 4 +--
src/syscall/syscall_solaris.go | 4 +--
src/syscall/syscall_unix.go | 36 ++++++++++++++++++++++++++
src/syscall/zsyscall_aix_ppc64.go | 20 +++++++-------
src/syscall/zsyscall_darwin_amd64.go | 4 +--
src/syscall/zsyscall_darwin_arm64.go | 4 +--
src/syscall/zsyscall_freebsd_386.go | 4 +--
src/syscall/zsyscall_freebsd_amd64.go | 4 +--
src/syscall/zsyscall_freebsd_arm.go | 4 +--
src/syscall/zsyscall_freebsd_arm64.go | 4 +--
src/syscall/zsyscall_linux_386.go | 4 +--
src/syscall/zsyscall_linux_amd64.go | 4 +--
src/syscall/zsyscall_linux_arm.go | 4 +--
src/syscall/zsyscall_linux_arm64.go | 4 +--
src/syscall/zsyscall_linux_mips.go | 4 +--
src/syscall/zsyscall_linux_mips64.go | 4 +--
src/syscall/zsyscall_linux_mips64le.go | 4 +--
src/syscall/zsyscall_linux_mipsle.go | 4 +--
src/syscall/zsyscall_linux_ppc64.go | 4 +--
src/syscall/zsyscall_linux_ppc64le.go | 4 +--
src/syscall/zsyscall_linux_riscv64.go | 4 +--
src/syscall/zsyscall_linux_s390x.go | 4 +--
src/syscall/zsyscall_netbsd_386.go | 4 +--
src/syscall/zsyscall_netbsd_amd64.go | 4 +--
src/syscall/zsyscall_netbsd_arm.go | 4 +--
src/syscall/zsyscall_netbsd_arm64.go | 4 +--
src/syscall/zsyscall_openbsd_386.go | 4 +--
src/syscall/zsyscall_openbsd_amd64.go | 4 +--
src/syscall/zsyscall_openbsd_arm.go | 4 +--
src/syscall/zsyscall_openbsd_arm64.go | 4 +--
src/syscall/zsyscall_openbsd_mips64.go | 4 +--
src/syscall/zsyscall_solaris_amd64.go | 20 +++++++-------
47 files changed, 155 insertions(+), 107 deletions(-)
diff --git a/src/runtime/race/testdata/mop_test.go b/src/runtime/race/testdata/mop_test.go
index 2d093739df..d05a443f62 100644
--- a/src/runtime/race/testdata/mop_test.go
+++ b/src/runtime/race/testdata/mop_test.go
@@ -1896,6 +1896,14 @@ func TestRaceNestedStruct(t *testing.T) {
}
func TestRaceIssue5567(t *testing.T) {
+ testRaceRead(t, false)
+}
+
+func TestRaceIssue51618(t *testing.T) {
+ testRaceRead(t, true)
+}
+
+func testRaceRead(t *testing.T, pread bool) {
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
in := make(chan []byte)
res := make(chan error)
@@ -1914,7 +1922,11 @@ func TestRaceIssue5567(t *testing.T) {
var n, total int
b := make([]byte, 17) // the race is on b buffer
for err == nil {
- n, err = f.Read(b)
+ if pread {
+ n, err = f.ReadAt(b, int64(total))
+ } else {
+ n, err = f.Read(b)
+ }
total += n
if n > 0 {
in <- b[:n]
diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go
index acc19b4db3..a2f8c78438 100644
--- a/src/syscall/syscall_aix.go
+++ b/src/syscall/syscall_aix.go
@@ -604,8 +604,8 @@ func PtraceDetach(pid int) (err error) { return ptrace64(PT_DETACH, int64(pid),
//sys Mkdirat(dirfd int, path string, mode uint32) (err error)
//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error)
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys pread(fd int, p []byte, offset int64) (n int, err error)
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys read(fd int, p []byte) (n int, err error)
//sys Reboot(how int) (err error)
//sys Rename(from string, to string) (err error)
diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go
index 87fb5c2f62..2e5387a6d9 100644
--- a/src/syscall/syscall_darwin.go
+++ b/src/syscall/syscall_darwin.go
@@ -170,8 +170,8 @@ func Kill(pid int, signum Signal) (err error) { return kill(pid, int(signum), 1)
//sys Munlockall() (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error)
//sys Pathconf(path string, name int) (val int, err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error)
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys pread(fd int, p []byte, offset int64) (n int, err error)
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys read(fd int, p []byte) (n int, err error)
//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
//sys Readlink(path string, buf []byte) (n int, err error)
diff --git a/src/syscall/syscall_dragonfly.go b/src/syscall/syscall_dragonfly.go
index f3c0f54521..d8edca9961 100644
--- a/src/syscall/syscall_dragonfly.go
+++ b/src/syscall/syscall_dragonfly.go
@@ -122,12 +122,12 @@ func Pipe2(p []int, flags int) (err error) {
}
//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) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
return extpread(fd, p, 0, offset)
}
//sys extpwrite(fd int, p []byte, flags int, offset int64) (n int, err error)
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
return extpwrite(fd, p, 0, offset)
}
diff --git a/src/syscall/syscall_freebsd.go b/src/syscall/syscall_freebsd.go
index ecb9ec825a..8494b21e5b 100644
--- a/src/syscall/syscall_freebsd.go
+++ b/src/syscall/syscall_freebsd.go
@@ -469,8 +469,8 @@ func convertFromDirents11(buf []byte, old []byte) int {
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error)
//sys Pathconf(path string, name int) (val int, err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error)
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys pread(fd int, p []byte, offset int64) (n int, err error)
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []byte) (n int, err error)
//sys Rename(from string, to string) (err error)
diff --git a/src/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go
index ef0f53468a..fc7df8496e 100644
--- a/src/syscall/syscall_linux_386.go
+++ b/src/syscall/syscall_linux_386.go
@@ -32,8 +32,8 @@ func setTimeval(sec, usec int64) Timeval {
//sys Ioperm(from int, num int, on int) (err error)
//sys Iopl(level int) (err error)
//sys Pause() (err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32
diff --git a/src/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go
index ea5229e8a0..0bcc664d32 100644
--- a/src/syscall/syscall_linux_amd64.go
+++ b/src/syscall/syscall_linux_amd64.go
@@ -22,8 +22,8 @@ const _SYS_setgroups = SYS_SETGROUPS
//sys Iopl(level int) (err error)
//sys Listen(s int, n int) (err error)
//sys Pause() (err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go
index f00149a1d4..9db702729f 100644
--- a/src/syscall/syscall_linux_arm.go
+++ b/src/syscall/syscall_linux_arm.go
@@ -72,8 +72,8 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
//sys Utime(path string, buf *Utimbuf) (err error)
//sys utimes(path string, times *[2]Timeval) (err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64
//sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go
index 9ed20f43ed..ef935f3a63 100644
--- a/src/syscall/syscall_linux_arm64.go
+++ b/src/syscall/syscall_linux_arm64.go
@@ -28,8 +28,8 @@ func EpollCreate(size int) (fd int, err error) {
//sysnb getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Getuid() (uid int)
//sys Listen(s int, n int) (err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go
index b56b8f06b6..258eb97b7e 100644
--- a/src/syscall/syscall_linux_mips64x.go
+++ b/src/syscall/syscall_linux_mips64x.go
@@ -23,8 +23,8 @@ const _SYS_setgroups = SYS_SETGROUPS
//sys Lchown(path string, uid int, gid int) (err error)
//sys Listen(s int, n int) (err error)
//sys Pause() (err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
diff --git a/src/syscall/syscall_linux_mipsx.go b/src/syscall/syscall_linux_mipsx.go
index c9c9f94e42..5390277926 100644
--- a/src/syscall/syscall_linux_mipsx.go
+++ b/src/syscall/syscall_linux_mipsx.go
@@ -24,8 +24,8 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
//sys Lchown(path string, uid int, gid int) (err error)
//sys Listen(s int, n int) (err error)
//sys Pause() (err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
diff --git a/src/syscall/syscall_linux_ppc64x.go b/src/syscall/syscall_linux_ppc64x.go
index 4180a17f3b..88ad8e4cd4 100644
--- a/src/syscall/syscall_linux_ppc64x.go
+++ b/src/syscall/syscall_linux_ppc64x.go
@@ -28,8 +28,8 @@ const _SYS_setgroups = SYS_SETGROUPS
//sys Listen(s int, n int) (err error)
//sys Lstat(path string, stat *Stat_t) (err error)
//sys Pause() (err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
diff --git a/src/syscall/syscall_linux_riscv64.go b/src/syscall/syscall_linux_riscv64.go
index a5fb18aa85..0ac4c5496e 100644
--- a/src/syscall/syscall_linux_riscv64.go
+++ b/src/syscall/syscall_linux_riscv64.go
@@ -28,8 +28,8 @@ func EpollCreate(size int) (fd int, err error) {
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Getuid() (uid int)
//sys Listen(s int, n int) (err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error)
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
diff --git a/src/syscall/syscall_linux_s390x.go b/src/syscall/syscall_linux_s390x.go
index 5d6f4d2526..46b252dc95 100644
--- a/src/syscall/syscall_linux_s390x.go
+++ b/src/syscall/syscall_linux_s390x.go
@@ -25,8 +25,8 @@ const _SYS_setgroups = SYS_SETGROUPS
//sys Lchown(path string, uid int, gid int) (err error)
//sys Lstat(path string, stat *Stat_t) (err error)
//sys Pause() (err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
diff --git a/src/syscall/syscall_netbsd.go b/src/syscall/syscall_netbsd.go
index 0d562cc78e..9ccb66c083 100644
--- a/src/syscall/syscall_netbsd.go
+++ b/src/syscall/syscall_netbsd.go
@@ -198,8 +198,8 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error)
//sys Pathconf(path string, name int) (val int, err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error)
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys pread(fd int, p []byte, offset int64) (n int, err error)
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []byte) (n int, err error)
//sys Rename(from string, to string) (err error)
diff --git a/src/syscall/syscall_openbsd.go b/src/syscall/syscall_openbsd.go
index 30a95316e8..1d82351084 100644
--- a/src/syscall/syscall_openbsd.go
+++ b/src/syscall/syscall_openbsd.go
@@ -173,8 +173,8 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error)
//sys Pathconf(path string, name int) (val int, err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error)
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys pread(fd int, p []byte, offset int64) (n int, err error)
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []byte) (n int, err error)
//sys Rename(from string, to string) (err error)
diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go
index 38c82a11e8..37ce5c9e3c 100644
--- a/src/syscall/syscall_solaris.go
+++ b/src/syscall/syscall_solaris.go
@@ -434,8 +434,8 @@ func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags i
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error)
//sys Pathconf(path string, name int) (val int, err error)
-//sys Pread(fd int, p []byte, offset int64) (n int, err error)
-//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys pread(fd int, p []byte, offset int64) (n int, err error)
+//sys pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []byte) (n int, err error)
//sys Rename(from string, to string) (err error)
diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go
index 5ee938115d..c35df430aa 100644
--- a/src/syscall/syscall_unix.go
+++ b/src/syscall/syscall_unix.go
@@ -227,6 +227,42 @@ func Write(fd int, p []byte) (n int, err error) {
return
}
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+ n, err = pread(fd, p, offset)
+ if race.Enabled {
+ if n > 0 {
+ race.WriteRange(unsafe.Pointer(&p[0]), n)
+ }
+ if err == nil {
+ race.Acquire(unsafe.Pointer(&ioSync))
+ }
+ }
+ if msanenabled && n > 0 {
+ msanWrite(unsafe.Pointer(&p[0]), n)
+ }
+ if asanenabled && n > 0 {
+ asanWrite(unsafe.Pointer(&p[0]), n)
+ }
+ return
+}
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+ if race.Enabled {
+ race.ReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ n, err = pwrite(fd, p, offset)
+ if race.Enabled && n > 0 {
+ race.ReadRange(unsafe.Pointer(&p[0]), n)
+ }
+ if msanenabled && n > 0 {
+ msanRead(unsafe.Pointer(&p[0]), n)
+ }
+ if asanenabled && n > 0 {
+ asanRead(unsafe.Pointer(&p[0]), n)
+ }
+ return
+}
+
// For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT.
var SocketDisableIPv6 bool
diff --git a/src/syscall/zsyscall_aix_ppc64.go b/src/syscall/zsyscall_aix_ppc64.go
index 2a3411374f..39838a42e6 100644
--- a/src/syscall/zsyscall_aix_ppc64.go
+++ b/src/syscall/zsyscall_aix_ppc64.go
@@ -72,8 +72,8 @@ import "unsafe"
//go:cgo_import_dynamic libc_Mkdirat mkdirat "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Mknodat mknodat "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Open open "libc.a/shr_64.o"
-//go:cgo_import_dynamic libc_Pread pread "libc.a/shr_64.o"
-//go:cgo_import_dynamic libc_Pwrite pwrite "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_pread pread "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_pwrite pwrite "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_read read "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Reboot reboot "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_Rename rename "libc.a/shr_64.o"
@@ -165,8 +165,8 @@ import "unsafe"
//go:linkname libc_Mkdirat libc_Mkdirat
//go:linkname libc_Mknodat libc_Mknodat
//go:linkname libc_Open libc_Open
-//go:linkname libc_Pread libc_Pread
-//go:linkname libc_Pwrite libc_Pwrite
+//go:linkname libc_pread libc_pread
+//go:linkname libc_pwrite libc_pwrite
//go:linkname libc_read libc_read
//go:linkname libc_Reboot libc_Reboot
//go:linkname libc_Rename libc_Rename
@@ -261,8 +261,8 @@ var (
libc_Mkdirat,
libc_Mknodat,
libc_Open,
- libc_Pread,
- libc_Pwrite,
+ libc_pread,
+ libc_pwrite,
libc_read,
libc_Reboot,
libc_Rename,
@@ -1067,12 +1067,12 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 *byte
if len(p) > 0 {
_p0 = &p[0]
}
- r0, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_Pread)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
+ r0, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_pread)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
@@ -1082,12 +1082,12 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 *byte
if len(p) > 0 {
_p0 = &p[0]
}
- r0, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_Pwrite)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
+ r0, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_pwrite)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go
index 0ccdaf2d0e..ee78a572fc 100644
--- a/src/syscall/zsyscall_darwin_amd64.go
+++ b/src/syscall/zsyscall_darwin_amd64.go
@@ -1137,7 +1137,7 @@ func libc_pathconf_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1158,7 +1158,7 @@ func libc_pread_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_darwin_arm64.go b/src/syscall/zsyscall_darwin_arm64.go
index 09bf34bb3c..ac1eccf755 100644
--- a/src/syscall/zsyscall_darwin_arm64.go
+++ b/src/syscall/zsyscall_darwin_arm64.go
@@ -1137,7 +1137,7 @@ func libc_pathconf_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1158,7 +1158,7 @@ func libc_pread_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_freebsd_386.go b/src/syscall/zsyscall_freebsd_386.go
index ed0eb9fa15..04bad4acc9 100644
--- a/src/syscall/zsyscall_freebsd_386.go
+++ b/src/syscall/zsyscall_freebsd_386.go
@@ -905,7 +905,7 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -922,7 +922,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_freebsd_amd64.go b/src/syscall/zsyscall_freebsd_amd64.go
index e291a56756..eeb9c0cb9b 100644
--- a/src/syscall/zsyscall_freebsd_amd64.go
+++ b/src/syscall/zsyscall_freebsd_amd64.go
@@ -905,7 +905,7 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -922,7 +922,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_freebsd_arm.go b/src/syscall/zsyscall_freebsd_arm.go
index 7dd856fd97..8ea4282ba4 100644
--- a/src/syscall/zsyscall_freebsd_arm.go
+++ b/src/syscall/zsyscall_freebsd_arm.go
@@ -905,7 +905,7 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -922,7 +922,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_freebsd_arm64.go b/src/syscall/zsyscall_freebsd_arm64.go
index 229a9a2238..73bf50559d 100644
--- a/src/syscall/zsyscall_freebsd_arm64.go
+++ b/src/syscall/zsyscall_freebsd_arm64.go
@@ -905,7 +905,7 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -922,7 +922,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_386.go b/src/syscall/zsyscall_linux_386.go
index c385dd3ca1..36a3d7ed39 100644
--- a/src/syscall/zsyscall_linux_386.go
+++ b/src/syscall/zsyscall_linux_386.go
@@ -1196,7 +1196,7 @@ func Pause() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1213,7 +1213,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_amd64.go b/src/syscall/zsyscall_linux_amd64.go
index 3e22e20907..07f328e1e2 100644
--- a/src/syscall/zsyscall_linux_amd64.go
+++ b/src/syscall/zsyscall_linux_amd64.go
@@ -1211,7 +1211,7 @@ func Pause() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1228,7 +1228,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_arm.go b/src/syscall/zsyscall_linux_arm.go
index 38907a0b35..df79dbd0e1 100644
--- a/src/syscall/zsyscall_linux_arm.go
+++ b/src/syscall/zsyscall_linux_arm.go
@@ -1493,7 +1493,7 @@ func utimes(path string, times *[2]Timeval) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1510,7 +1510,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_arm64.go b/src/syscall/zsyscall_linux_arm64.go
index f335c062d5..73321bd897 100644
--- a/src/syscall/zsyscall_linux_arm64.go
+++ b/src/syscall/zsyscall_linux_arm64.go
@@ -1196,7 +1196,7 @@ func Listen(s int, n int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1213,7 +1213,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_mips.go b/src/syscall/zsyscall_linux_mips.go
index f5f73895cc..1ef8eebe4f 100644
--- a/src/syscall/zsyscall_linux_mips.go
+++ b/src/syscall/zsyscall_linux_mips.go
@@ -1180,7 +1180,7 @@ func Pause() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1197,7 +1197,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_mips64.go b/src/syscall/zsyscall_linux_mips64.go
index 32f3c32b9b..1ed877ce7e 100644
--- a/src/syscall/zsyscall_linux_mips64.go
+++ b/src/syscall/zsyscall_linux_mips64.go
@@ -1211,7 +1211,7 @@ func Pause() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1228,7 +1228,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_mips64le.go b/src/syscall/zsyscall_linux_mips64le.go
index 62dcff45a1..3d7cc9e373 100644
--- a/src/syscall/zsyscall_linux_mips64le.go
+++ b/src/syscall/zsyscall_linux_mips64le.go
@@ -1211,7 +1211,7 @@ func Pause() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1228,7 +1228,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_mipsle.go b/src/syscall/zsyscall_linux_mipsle.go
index 4761246536..59b49ddf74 100644
--- a/src/syscall/zsyscall_linux_mipsle.go
+++ b/src/syscall/zsyscall_linux_mipsle.go
@@ -1180,7 +1180,7 @@ func Pause() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1197,7 +1197,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_ppc64.go b/src/syscall/zsyscall_linux_ppc64.go
index c9b1365e74..93632bd1cb 100644
--- a/src/syscall/zsyscall_linux_ppc64.go
+++ b/src/syscall/zsyscall_linux_ppc64.go
@@ -1273,7 +1273,7 @@ func Pause() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1290,7 +1290,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_ppc64le.go b/src/syscall/zsyscall_linux_ppc64le.go
index 0807390894..fc8f6b7bcf 100644
--- a/src/syscall/zsyscall_linux_ppc64le.go
+++ b/src/syscall/zsyscall_linux_ppc64le.go
@@ -1273,7 +1273,7 @@ func Pause() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1290,7 +1290,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_riscv64.go b/src/syscall/zsyscall_linux_riscv64.go
index 1661d04221..0efa70715d 100644
--- a/src/syscall/zsyscall_linux_riscv64.go
+++ b/src/syscall/zsyscall_linux_riscv64.go
@@ -1196,7 +1196,7 @@ func Listen(s int, n int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1213,7 +1213,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_linux_s390x.go b/src/syscall/zsyscall_linux_s390x.go
index 2ab78c71bf..568bb430a6 100644
--- a/src/syscall/zsyscall_linux_s390x.go
+++ b/src/syscall/zsyscall_linux_s390x.go
@@ -1243,7 +1243,7 @@ func Pause() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1260,7 +1260,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_netbsd_386.go b/src/syscall/zsyscall_netbsd_386.go
index 408318181a..9b92859206 100644
--- a/src/syscall/zsyscall_netbsd_386.go
+++ b/src/syscall/zsyscall_netbsd_386.go
@@ -816,7 +816,7 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -833,7 +833,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_netbsd_amd64.go b/src/syscall/zsyscall_netbsd_amd64.go
index 2039cf6d0e..ac34c00b5a 100644
--- a/src/syscall/zsyscall_netbsd_amd64.go
+++ b/src/syscall/zsyscall_netbsd_amd64.go
@@ -816,7 +816,7 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -833,7 +833,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_netbsd_arm.go b/src/syscall/zsyscall_netbsd_arm.go
index 3c287ea223..2be5e7baa4 100644
--- a/src/syscall/zsyscall_netbsd_arm.go
+++ b/src/syscall/zsyscall_netbsd_arm.go
@@ -816,7 +816,7 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -833,7 +833,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_netbsd_arm64.go b/src/syscall/zsyscall_netbsd_arm64.go
index 1d40db9e6b..02a652bbbb 100644
--- a/src/syscall/zsyscall_netbsd_arm64.go
+++ b/src/syscall/zsyscall_netbsd_arm64.go
@@ -816,7 +816,7 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -833,7 +833,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_openbsd_386.go b/src/syscall/zsyscall_openbsd_386.go
index 2dcc4b2739..f7986d5ea5 100644
--- a/src/syscall/zsyscall_openbsd_386.go
+++ b/src/syscall/zsyscall_openbsd_386.go
@@ -1105,7 +1105,7 @@ func libc_pathconf_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1126,7 +1126,7 @@ func libc_pread_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_openbsd_amd64.go b/src/syscall/zsyscall_openbsd_amd64.go
index 8d4cb9c1e1..605443d890 100644
--- a/src/syscall/zsyscall_openbsd_amd64.go
+++ b/src/syscall/zsyscall_openbsd_amd64.go
@@ -1105,7 +1105,7 @@ func libc_pathconf_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1126,7 +1126,7 @@ func libc_pread_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_openbsd_arm.go b/src/syscall/zsyscall_openbsd_arm.go
index d45bc02fbd..0f2312fbc4 100644
--- a/src/syscall/zsyscall_openbsd_arm.go
+++ b/src/syscall/zsyscall_openbsd_arm.go
@@ -1105,7 +1105,7 @@ func libc_pathconf_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1126,7 +1126,7 @@ func libc_pread_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_openbsd_arm64.go b/src/syscall/zsyscall_openbsd_arm64.go
index e060b092fe..1367e2aba9 100644
--- a/src/syscall/zsyscall_openbsd_arm64.go
+++ b/src/syscall/zsyscall_openbsd_arm64.go
@@ -1105,7 +1105,7 @@ func libc_pathconf_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -1126,7 +1126,7 @@ func libc_pread_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_openbsd_mips64.go b/src/syscall/zsyscall_openbsd_mips64.go
index 51904b5e29..2cf8465319 100644
--- a/src/syscall/zsyscall_openbsd_mips64.go
+++ b/src/syscall/zsyscall_openbsd_mips64.go
@@ -810,7 +810,7 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
@@ -827,7 +827,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
diff --git a/src/syscall/zsyscall_solaris_amd64.go b/src/syscall/zsyscall_solaris_amd64.go
index 7b012bf9bb..5bb50caaae 100644
--- a/src/syscall/zsyscall_solaris_amd64.go
+++ b/src/syscall/zsyscall_solaris_amd64.go
@@ -48,8 +48,8 @@ import "unsafe"
//go:cgo_import_dynamic libc_Nanosleep nanosleep "libc.so"
//go:cgo_import_dynamic libc_Open open "libc.so"
//go:cgo_import_dynamic libc_Pathconf pathconf "libc.so"
-//go:cgo_import_dynamic libc_Pread pread "libc.so"
-//go:cgo_import_dynamic libc_Pwrite pwrite "libc.so"
+//go:cgo_import_dynamic libc_pread pread "libc.so"
+//go:cgo_import_dynamic libc_pwrite pwrite "libc.so"
//go:cgo_import_dynamic libc_read read "libc.so"
//go:cgo_import_dynamic libc_Readlink readlink "libc.so"
//go:cgo_import_dynamic libc_Rename rename "libc.so"
@@ -134,8 +134,8 @@ import "unsafe"
//go:linkname libc_Nanosleep libc_Nanosleep
//go:linkname libc_Open libc_Open
//go:linkname libc_Pathconf libc_Pathconf
-//go:linkname libc_Pread libc_Pread
-//go:linkname libc_Pwrite libc_Pwrite
+//go:linkname libc_pread libc_pread
+//go:linkname libc_pwrite libc_pwrite
//go:linkname libc_read libc_read
//go:linkname libc_Readlink libc_Readlink
//go:linkname libc_Rename libc_Rename
@@ -223,8 +223,8 @@ var (
libc_Nanosleep,
libc_Open,
libc_Pathconf,
- libc_Pread,
- libc_Pwrite,
+ libc_pread,
+ libc_pwrite,
libc_read,
libc_Readlink,
libc_Rename,
@@ -753,12 +753,12 @@ func Pathconf(path string, name int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
+func pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 *byte
if len(p) > 0 {
_p0 = &p[0]
}
- r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_Pread)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
+ r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_pread)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
@@ -768,12 +768,12 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 *byte
if len(p) > 0 {
_p0 = &p[0]
}
- r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_Pwrite)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
+ r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_pwrite)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
From 3c2e73c8c3323887e6b95f72adb6242b8727ba8b Mon Sep 17 00:00:00 2001
From: Tobias Klauser
Date: Fri, 11 Mar 2022 08:20:55 +0100
Subject: [PATCH 084/276] runtime/pprof: use syscall.RUSAGE_SELF
Change-Id: Idc37429de5a48e708eda868ca7fa26b28620bac0
Reviewed-on: https://go-review.googlesource.com/c/go/+/391854
Trust: Tobias Klauser
Run-TryBot: Tobias Klauser
TryBot-Result: Gopher Robot
Reviewed-by: Ian Lance Taylor
---
src/runtime/pprof/pprof_rusage.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/runtime/pprof/pprof_rusage.go b/src/runtime/pprof/pprof_rusage.go
index 7df81eca23..984a32e79d 100644
--- a/src/runtime/pprof/pprof_rusage.go
+++ b/src/runtime/pprof/pprof_rusage.go
@@ -28,6 +28,6 @@ func addMaxRSS(w io.Writer) {
}
var rusage syscall.Rusage
- syscall.Getrusage(0, &rusage)
+ syscall.Getrusage(syscall.RUSAGE_SELF, &rusage)
fmt.Fprintf(w, "# MaxRSS = %d\n", uintptr(rusage.Maxrss)*rssToBytes)
}
From ab0f7611d739fe10d0265dbc6bdc17684423bfc8 Mon Sep 17 00:00:00 2001
From: Uzondu Enudeme
Date: Thu, 10 Mar 2022 00:08:52 +0100
Subject: [PATCH 085/276] net/url: add OmitHost bool to url.URL
Previously, myscheme:/path and myscheme:///path were treated as the same URL
although materially different. The distinction made clear by RFC 3986 sec. 5.3 where
a different recomposition behavior is expected when a URI reference has an undefined
host(authority) as in myscheme:/path vs. one with an empty host(authority)
as in myscheme:///path.
This change fixes the Parse/String roundtrip limitation for URLs with an undefined
host and a single slash.
Fixes #46059
Change-Id: I1b8d6042135513616374ff8c8dfb1cdb640f8efe
Reviewed-on: https://go-review.googlesource.com/c/go/+/391294
Reviewed-by: Ian Lance Taylor
Reviewed-by: Emmanuel Odeke
Run-TryBot: Emmanuel Odeke
TryBot-Result: Gopher Robot
---
src/net/url/url.go | 28 +++++++++++++++++++---------
src/net/url/url_test.go | 13 +++++++------
2 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/src/net/url/url.go b/src/net/url/url.go
index 1571bf728b..ecfd1d9e94 100644
--- a/src/net/url/url.go
+++ b/src/net/url/url.go
@@ -363,6 +363,7 @@ type URL struct {
Host string // host or host:port
Path string // path (relative paths may omit leading slash)
RawPath string // encoded path hint (see EscapedPath method)
+ OmitHost bool // do not emit empty host (authority)
ForceQuery bool // append a query ('?') even if RawQuery is empty
RawQuery string // encoded query values, without '?'
Fragment string // fragment for references, without '#'
@@ -556,7 +557,12 @@ func parse(rawURL string, viaRequest bool) (*URL, error) {
if err != nil {
return nil, err
}
+ } else if url.Scheme != "" && strings.HasPrefix(rest, "/") {
+ // OmitHost is set to true when rawURL has an empty host (authority).
+ // See golang.org/issue/46059.
+ url.OmitHost = true
}
+
// Set Path and, optionally, RawPath.
// RawPath is a hint of the encoding of Path. We don't want to set it if
// the default escaping of Path is equivalent, to help make sure that people
@@ -806,15 +812,19 @@ func (u *URL) String() string {
buf.WriteString(u.Opaque)
} else {
if u.Scheme != "" || u.Host != "" || u.User != nil {
- if u.Host != "" || u.Path != "" || u.User != nil {
- buf.WriteString("//")
- }
- if ui := u.User; ui != nil {
- buf.WriteString(ui.String())
- buf.WriteByte('@')
- }
- if h := u.Host; h != "" {
- buf.WriteString(escape(h, encodeHost))
+ if u.OmitHost && u.Host == "" && u.User == nil {
+ // omit empty host
+ } else {
+ if u.Host != "" || u.Path != "" || u.User != nil {
+ buf.WriteString("//")
+ }
+ if ui := u.User; ui != nil {
+ buf.WriteString(ui.String())
+ buf.WriteByte('@')
+ }
+ if h := u.Host; h != "" {
+ buf.WriteString(escape(h, encodeHost))
+ }
}
}
path := u.EscapedPath()
diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go
index 84dba45c3c..18aa5f8a1c 100644
--- a/src/net/url/url_test.go
+++ b/src/net/url/url_test.go
@@ -163,14 +163,15 @@ var urltests = []URLTest{
},
"http:%2f%2fwww.google.com/?q=go+language",
},
- // non-authority with path
+ // non-authority with path; see golang.org/issue/46059
{
"mailto:/webmaster@golang.org",
&URL{
- Scheme: "mailto",
- Path: "/webmaster@golang.org",
+ Scheme: "mailto",
+ Path: "/webmaster@golang.org",
+ OmitHost: true,
},
- "mailto:///webmaster@golang.org", // unfortunate compromise
+ "",
},
// non-authority
{
@@ -625,8 +626,8 @@ func ufmt(u *URL) string {
pass = p
}
}
- return fmt.Sprintf("opaque=%q, scheme=%q, user=%#v, pass=%#v, host=%q, path=%q, rawpath=%q, rawq=%q, frag=%q, rawfrag=%q, forcequery=%v",
- u.Opaque, u.Scheme, user, pass, u.Host, u.Path, u.RawPath, u.RawQuery, u.Fragment, u.RawFragment, u.ForceQuery)
+ return fmt.Sprintf("opaque=%q, scheme=%q, user=%#v, pass=%#v, host=%q, path=%q, rawpath=%q, rawq=%q, frag=%q, rawfrag=%q, forcequery=%v, omithost=%t",
+ u.Opaque, u.Scheme, user, pass, u.Host, u.Path, u.RawPath, u.RawQuery, u.Fragment, u.RawFragment, u.ForceQuery, u.OmitHost)
}
func BenchmarkString(b *testing.B) {
From 7900576bac4630bbeec7f4f1aa4b1cb0d51bd8a1 Mon Sep 17 00:00:00 2001
From: Cuong Manh Le
Date: Sun, 13 Mar 2022 22:38:15 +0700
Subject: [PATCH 086/276] cmd/compile: remove unified IR stmtTypeDeclHack
After CL 385998, unified IR quirks mode was gone, it's time to remove
stmtTypeDeclHack, too.
Change-Id: Id73dd1d6c11b91c0c6c6cbe85f1b06977a9876d2
Reviewed-on: https://go-review.googlesource.com/c/go/+/392214
Trust: Cuong Manh Le
Run-TryBot: Cuong Manh Le
TryBot-Result: Gopher Robot
Reviewed-by: Matthew Dempsky
---
src/cmd/compile/internal/noder/codes.go | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/cmd/compile/internal/noder/codes.go b/src/cmd/compile/internal/noder/codes.go
index bc0831dd78..8f54a07ca4 100644
--- a/src/cmd/compile/internal/noder/codes.go
+++ b/src/cmd/compile/internal/noder/codes.go
@@ -29,9 +29,6 @@ const (
stmtFor
stmtSwitch
stmtSelect
-
- // TODO(mdempsky): Remove after we don't care about toolstash -cmp.
- stmtTypeDeclHack
)
type codeExpr int
From 471d319fb2497aa7239943eb1a6d5cfbad503a2a Mon Sep 17 00:00:00 2001
From: "Bryan C. Mills"
Date: Thu, 10 Mar 2022 15:28:10 -0500
Subject: [PATCH 087/276] debug/buildinfo: use testenv.GoToolPath in tests
instead of resolving "go" from $PATH
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Updates #37475.
Change-Id: I8c3237438da3e9521ce3be26a0b5d5ca36944b17
Reviewed-on: https://go-review.googlesource.com/c/go/+/391803
Trust: Bryan Mills
Run-TryBot: Bryan Mills
TryBot-Result: Gopher Robot
Reviewed-by: Daniel Martí
Trust: Daniel Martí
---
src/debug/buildinfo/buildinfo_test.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/debug/buildinfo/buildinfo_test.go b/src/debug/buildinfo/buildinfo_test.go
index ac71626fda..0affc832e7 100644
--- a/src/debug/buildinfo/buildinfo_test.go
+++ b/src/debug/buildinfo/buildinfo_test.go
@@ -66,7 +66,7 @@ func TestReadFile(t *testing.T) {
t.Fatal(err)
}
outPath := filepath.Join(dir, path.Base(t.Name()))
- cmd := exec.Command("go", "build", "-o="+outPath)
+ cmd := exec.Command(testenv.GoToolPath(t), "build", "-o="+outPath)
cmd.Dir = dir
cmd.Env = append(os.Environ(), "GO111MODULE=on", "GOOS="+goos, "GOARCH="+goarch)
stderr := &bytes.Buffer{}
@@ -89,7 +89,7 @@ func TestReadFile(t *testing.T) {
t.Fatal(err)
}
outPath := filepath.Join(gopathDir, path.Base(t.Name()))
- cmd := exec.Command("go", "build", "-o="+outPath)
+ cmd := exec.Command(testenv.GoToolPath(t), "build", "-o="+outPath)
cmd.Dir = pkgDir
cmd.Env = append(os.Environ(), "GO111MODULE=off", "GOPATH="+gopathDir, "GOOS="+goos, "GOARCH="+goarch)
stderr := &bytes.Buffer{}
From d99ff0382116bb472b9f92ddf23cb22bf145bbcd Mon Sep 17 00:00:00 2001
From: "Bryan C. Mills"
Date: Wed, 9 Mar 2022 17:17:40 -0500
Subject: [PATCH 088/276] go/build: set PWD for go subcommands
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Since these commands already include an explicit Env field,
they will not be fixed automatically by proposal #50599.
Change-Id: Ia8157a71cf0cfe208bdc0da9aef54be3d26c795f
Reviewed-on: https://go-review.googlesource.com/c/go/+/391804
Trust: Bryan Mills
Run-TryBot: Bryan Mills
TryBot-Result: Gopher Robot
Reviewed-by: Daniel Martí
Trust: Daniel Martí
---
src/go/build/build.go | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/go/build/build.go b/src/go/build/build.go
index baf76e6b7f..c1d044e55a 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -1186,6 +1186,13 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode)
"GOPATH="+ctxt.GOPATH,
"CGO_ENABLED="+cgo,
)
+ if cmd.Dir != "" {
+ // If possible, set PWD: if an error occurs and PWD includes a symlink, we
+ // want the error to refer to Dir, not some other name for it.
+ if abs, err := filepath.Abs(cmd.Dir); err == nil {
+ cmd.Env = append(cmd.Env, "PWD="+abs)
+ }
+ }
if err := cmd.Run(); err != nil {
return fmt.Errorf("go/build: go list %s: %v\n%s\n", path, err, stderr.String())
From 676858f3d4786054e1b27b999b5e73190f25288c Mon Sep 17 00:00:00 2001
From: "Bryan C. Mills"
Date: Thu, 10 Mar 2022 15:09:17 -0500
Subject: [PATCH 089/276] cmd/go: use testGOROOT in
TestListTemplateContextFunction
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This test uses testgo to run 'go list', so it should use the correct
GOROOT for testgo. (This may be particularly relevant when the test
binary itself is build with -trimpath, in which case runtime.GOROOT()
is not valid.)
Updates #51483
Change-Id: I79b310f88e3a200122d6289073df1385e3e97cca
Reviewed-on: https://go-review.googlesource.com/c/go/+/391801
Trust: Bryan Mills
Run-TryBot: Bryan Mills
TryBot-Result: Gopher Robot
Reviewed-by: Daniel Martí
Trust: Daniel Martí
---
src/cmd/go/go_test.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 01356f9dd0..fa0d44dae6 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -1631,7 +1631,7 @@ func TestListTemplateContextFunction(t *testing.T) {
}{
{"GOARCH", runtime.GOARCH},
{"GOOS", runtime.GOOS},
- {"GOROOT", filepath.Clean(runtime.GOROOT())},
+ {"GOROOT", testGOROOT},
{"GOPATH", os.Getenv("GOPATH")},
{"CgoEnabled", ""},
{"UseAllFiles", ""},
From 8419ec295cd86a3d26cd360ef5f919a51fe33ebb Mon Sep 17 00:00:00 2001
From: Cuong Manh Le
Date: Sun, 13 Mar 2022 00:04:46 +0700
Subject: [PATCH 090/276] cmd/compile: fix wrong dict param when getting dict
type
CL 338129 added getDictionaryType to get the dictionary type from the
specified dict param, but still using the one in info.dictParam, which
is wrong.
Fixes #51413
Change-Id: Ie13460c1e5751c4c5fc44479a44f6eed8b3b06e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/391994
Trust: Cuong Manh Le
Run-TryBot: Cuong Manh Le
TryBot-Result: Gopher Robot
Reviewed-by: Matthew Dempsky
Trust: Matthew Dempsky
Reviewed-by: Keith Randall
---
src/cmd/compile/internal/noder/stencil.go | 2 +-
test/typeparam/mdempsky/13.go | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index cd586cab78..c78a169d31 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -898,7 +898,7 @@ func getDictionaryType(info *instInfo, dictParam *ir.Name, pos src.XPos, i int)
base.Fatalf(fmt.Sprintf("bad dict index %d", i))
}
- r := getDictionaryEntry(pos, info.dictParam, i, info.dictInfo.startSubDict)
+ r := getDictionaryEntry(pos, dictParam, i, info.dictInfo.startSubDict)
// change type of retrieved dictionary entry to *byte, which is the
// standard typing of a *runtime._type in the compiler
typed(types.Types[types.TUINT8].PtrTo(), r)
diff --git a/test/typeparam/mdempsky/13.go b/test/typeparam/mdempsky/13.go
index bf37a64177..8e11352b51 100644
--- a/test/typeparam/mdempsky/13.go
+++ b/test/typeparam/mdempsky/13.go
@@ -1,4 +1,4 @@
-// run -gcflags=""
+// run
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
From 41fe746857104d8775a23dc8f69494240d683e54 Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Mon, 14 Mar 2022 10:45:16 -0700
Subject: [PATCH 091/276] go/types, types2: use correct underlying type in
union set computation
Fixes #51658.
Change-Id: Ibf415d7e12849b8f50b58d74713613d4e65bc347
Reviewed-on: https://go-review.googlesource.com/c/go/+/392575
Trust: Robert Griesemer
Run-TryBot: Robert Griesemer
Reviewed-by: Robert Findley
---
.../types2/testdata/fixedbugs/issue51658.go2 | 39 +++++++++++++++++++
src/cmd/compile/internal/types2/typeset.go | 2 +-
.../types/testdata/fixedbugs/issue51658.go2 | 39 +++++++++++++++++++
src/go/types/typeset.go | 2 +-
4 files changed, 80 insertions(+), 2 deletions(-)
create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51658.go2
create mode 100644 src/go/types/testdata/fixedbugs/issue51658.go2
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51658.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51658.go2
new file mode 100644
index 0000000000..c437c92d29
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51658.go2
@@ -0,0 +1,39 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type F { // ERROR syntax error
+ float64
+} // ERROR syntax error
+
+func _[T F | int](x T) {
+ _ = x == 0 // don't crash when recording type of 0
+}
+
+// test case from issue
+
+type FloatType { // ERROR syntax error
+ float32 | float64
+} // ERROR syntax error
+
+type IntegerType interface {
+ int8 | int16 | int32 | int64 | int |
+ uint8 | uint16 | uint32 | uint64 | uint
+}
+
+type ComplexType interface {
+ complex64 | complex128
+}
+
+type Number interface {
+ FloatType | IntegerType | ComplexType
+}
+
+func GetDefaultNumber[T Number](value, defaultValue T) T {
+ if value == 0 {
+ return defaultValue
+ }
+ return value
+}
diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go
index 8df8949435..646b436685 100644
--- a/src/cmd/compile/internal/types2/typeset.go
+++ b/src/cmd/compile/internal/types2/typeset.go
@@ -406,7 +406,7 @@ func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos syn
// For now we don't permit type parameters as constraints.
assert(!isTypeParam(t.typ))
terms = computeInterfaceTypeSet(check, pos, ui).terms
- } else if t.typ == Typ[Invalid] {
+ } else if u == Typ[Invalid] {
continue
} else {
if t.tilde && !Identical(t.typ, u) {
diff --git a/src/go/types/testdata/fixedbugs/issue51658.go2 b/src/go/types/testdata/fixedbugs/issue51658.go2
new file mode 100644
index 0000000000..04ce6a9760
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51658.go2
@@ -0,0 +1,39 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type F { // ERROR expected type
+ float64
+} // ERROR expected declaration
+
+func _[T F | int](x T) {
+ _ = x == 0 // don't crash when recording type of 0
+}
+
+// test case from issue
+
+type FloatType { // ERROR expected type
+ float32 | float64
+} // ERROR expected declaration
+
+type IntegerType interface {
+ int8 | int16 | int32 | int64 | int |
+ uint8 | uint16 | uint32 | uint64 | uint
+}
+
+type ComplexType interface {
+ complex64 | complex128
+}
+
+type Number interface {
+ FloatType | IntegerType | ComplexType
+}
+
+func GetDefaultNumber[T Number](value, defaultValue T) T {
+ if value == 0 {
+ return defaultValue
+ }
+ return value
+}
diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go
index 6603383ea3..b33141ec32 100644
--- a/src/go/types/typeset.go
+++ b/src/go/types/typeset.go
@@ -406,7 +406,7 @@ func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos tok
// For now we don't permit type parameters as constraints.
assert(!isTypeParam(t.typ))
terms = computeInterfaceTypeSet(check, pos, ui).terms
- } else if t.typ == Typ[Invalid] {
+ } else if u == Typ[Invalid] {
continue
} else {
if t.tilde && !Identical(t.typ, u) {
From 5ccd8e5133a43e574be8d66aae3a230c39b4b67a Mon Sep 17 00:00:00 2001
From: Keith Randall
Date: Thu, 10 Mar 2022 15:26:22 -0800
Subject: [PATCH 092/276] internal/cpu: disallow disabling options that are
required for microarch
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
e.g., if GOAMD64=v3, don't allow GODEBUG=cpu.XXX=off for XXX which
are required for v3.
Change-Id: Ib58a4c8b13c5464ba476448ba44bbb261218787c
Reviewed-on: https://go-review.googlesource.com/c/go/+/391694
Trust: Keith Randall
Run-TryBot: Keith Randall
TryBot-Result: Gopher Robot
Reviewed-by: Martin Möhrmann
---
src/internal/cpu/cpu_x86.go | 34 ++++++++++++++++++++++++----------
src/internal/cpu/cpu_x86.s | 17 +++++++++++++++++
2 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go
index 81d5ceed61..6fd979a747 100644
--- a/src/internal/cpu/cpu_x86.go
+++ b/src/internal/cpu/cpu_x86.go
@@ -14,6 +14,9 @@ func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
// xgetbv with ecx = 0 is implemented in cpu_x86.s.
func xgetbv() (eax, edx uint32)
+// getGOAMD64level is implemented in cpu_x86.s. Returns number in [1,4].
+func getGOAMD64level() int32
+
const (
// edx bits
cpuid_SSE2 = 1 << 26
@@ -47,19 +50,30 @@ func doinit() {
options = []option{
{Name: "adx", Feature: &X86.HasADX},
{Name: "aes", Feature: &X86.HasAES},
- {Name: "avx", Feature: &X86.HasAVX},
- {Name: "avx2", Feature: &X86.HasAVX2},
- {Name: "bmi1", Feature: &X86.HasBMI1},
- {Name: "bmi2", Feature: &X86.HasBMI2},
{Name: "erms", Feature: &X86.HasERMS},
- {Name: "fma", Feature: &X86.HasFMA},
{Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ},
- {Name: "popcnt", Feature: &X86.HasPOPCNT},
{Name: "rdtscp", Feature: &X86.HasRDTSCP},
- {Name: "sse3", Feature: &X86.HasSSE3},
- {Name: "sse41", Feature: &X86.HasSSE41},
- {Name: "sse42", Feature: &X86.HasSSE42},
- {Name: "ssse3", Feature: &X86.HasSSSE3},
+ }
+ level := getGOAMD64level()
+ if level < 2 {
+ // These options are required at level 2. At lower levels
+ // they can be turned off.
+ options = append(options,
+ option{Name: "popcnt", Feature: &X86.HasPOPCNT},
+ option{Name: "sse3", Feature: &X86.HasSSE3},
+ option{Name: "sse41", Feature: &X86.HasSSE41},
+ option{Name: "sse42", Feature: &X86.HasSSE42},
+ option{Name: "ssse3", Feature: &X86.HasSSSE3})
+ }
+ if level < 3 {
+ // These options are required at level 3. At lower levels
+ // they can be turned off.
+ options = append(options,
+ option{Name: "avx", Feature: &X86.HasAVX},
+ option{Name: "avx2", Feature: &X86.HasAVX2},
+ option{Name: "bmi1", Feature: &X86.HasBMI1},
+ option{Name: "bmi2", Feature: &X86.HasBMI2},
+ option{Name: "fma", Feature: &X86.HasFMA})
}
maxID, _, _, _ := cpuid(0, 0)
diff --git a/src/internal/cpu/cpu_x86.s b/src/internal/cpu/cpu_x86.s
index edef21905c..2ee8eca248 100644
--- a/src/internal/cpu/cpu_x86.s
+++ b/src/internal/cpu/cpu_x86.s
@@ -24,3 +24,20 @@ TEXT ·xgetbv(SB),NOSPLIT,$0-8
MOVL AX, eax+0(FP)
MOVL DX, edx+4(FP)
RET
+
+// func getGOAMD64level() int32
+TEXT ·getGOAMD64level(SB),NOSPLIT,$0-4
+#ifdef GOAMD64_v4
+ MOVL $4, ret+0(FP)
+#else
+#ifdef GOAMD64_v3
+ MOVL $3, ret+0(FP)
+#else
+#ifdef GOAMD64_v2
+ MOVL $2, ret+0(FP)
+#else
+ MOVL $1, ret+0(FP)
+#endif
+#endif
+#endif
+ RET
From b7041c7ad1c9d42078cfc376320e5b307e617a80 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Mon, 14 Mar 2022 11:03:23 -0400
Subject: [PATCH 093/276] cmd/api: require proposal # for new API features
Having the proposal numbers recorded in the API files
should help significantly when it comes time to audit
the new API additions at the end of each release cycle.
Change-Id: Id18e8cbdf892228a10ac17e4e21c7e17de5d4ff7
Reviewed-on: https://go-review.googlesource.com/c/go/+/392414
Trust: Russ Cox
Run-TryBot: Russ Cox
Reviewed-by: Dmitri Shuralyov
TryBot-Result: Gopher Robot
---
api/README | 16 +++++++++--
api/next.txt | 9 ------
api/next/45754.txt | 2 ++
api/next/46059.txt | 2 ++
api/next/47005.txt | 2 ++
api/next/50601.txt | 5 ++++
src/cmd/api/goapi.go | 58 ++++++++++++++++++++++++++-----------
src/cmd/api/run.go | 68 +++++++++++++++++++++++++++-----------------
8 files changed, 108 insertions(+), 54 deletions(-)
delete mode 100644 api/next.txt
create mode 100644 api/next/45754.txt
create mode 100644 api/next/46059.txt
create mode 100644 api/next/47005.txt
create mode 100644 api/next/50601.txt
diff --git a/api/README b/api/README
index ce24efcd31..1e52f7a843 100644
--- a/api/README
+++ b/api/README
@@ -8,6 +8,16 @@ shipped. Each file adds new lines but does not remove any.
except.txt lists features that may disappear without breaking true
compatibility.
-next.txt is the only file intended to be mutated. It's a list of
-features that may be added to the next version. It only affects
-warning output from the go api tool.
+Starting with go1.19.txt, each API feature line must end in "#nnnnn"
+giving the GitHub issue number of the proposal issue that accepted
+the new API. This helps with our end-of-cycle audit of new APIs.
+The same requirement applies to next/* (described below), which will
+become a go1.XX.txt for XX >= 19.
+
+The next/ directory contains the only files intended to be mutated.
+Each file in that directory contains a list of features that may be added
+to the next release of Go. The files in this directory only affect the
+warning output from the go api tool. Each file should be named
+nnnnn.txt, after the issue number for the accepted proposal.
+(The #nnnnn suffix must also appear at the end of each line in the file;
+that will be preserved when next/*.txt is concatenated into go1.XX.txt.)
diff --git a/api/next.txt b/api/next.txt
deleted file mode 100644
index a0f2bed8d1..0000000000
--- a/api/next.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg encoding/binary, type AppendByteOrder interface { AppendUint16, AppendUint32, AppendUint64, String }
-pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint16) []uint8
-pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8
-pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8
-pkg encoding/binary, type AppendByteOrder interface, String() string
-pkg flag, func TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string)
-pkg flag, method (*FlagSet) TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string)
-pkg net/url, func JoinPath(string, ...string) (string, error)
-pkg net/url, method (*URL) JoinPath(...string) *URL
diff --git a/api/next/45754.txt b/api/next/45754.txt
new file mode 100644
index 0000000000..e980342c04
--- /dev/null
+++ b/api/next/45754.txt
@@ -0,0 +1,2 @@
+pkg flag, func TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string) #45754
+pkg flag, method (*FlagSet) TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string) #45754
diff --git a/api/next/46059.txt b/api/next/46059.txt
new file mode 100644
index 0000000000..3cc44966a2
--- /dev/null
+++ b/api/next/46059.txt
@@ -0,0 +1,2 @@
+pkg net/url, type URL struct, OmitHost bool #46059
+
diff --git a/api/next/47005.txt b/api/next/47005.txt
new file mode 100644
index 0000000000..0d7695e45c
--- /dev/null
+++ b/api/next/47005.txt
@@ -0,0 +1,2 @@
+pkg net/url, func JoinPath(string, ...string) (string, error) #47005
+pkg net/url, method (*URL) JoinPath(...string) *URL #47005
diff --git a/api/next/50601.txt b/api/next/50601.txt
new file mode 100644
index 0000000000..261dce375d
--- /dev/null
+++ b/api/next/50601.txt
@@ -0,0 +1,5 @@
+pkg encoding/binary, type AppendByteOrder interface { AppendUint16, AppendUint32, AppendUint64, String } #50601
+pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint16) []uint8 #50601
+pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8 #50601
+pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8 #50601
+pkg encoding/binary, type AppendByteOrder interface, String() string #50601
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 5ae059e4ce..2a0e109575 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.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.
-// Binary api computes the exported API of a set of Go packages.
+// Api computes the exported API of a set of Go packages.
package main
import (
@@ -24,6 +24,7 @@ import (
"regexp"
"runtime"
"sort"
+ "strconv"
"strings"
"sync"
)
@@ -42,12 +43,13 @@ func goCmd() string {
// Flags
var (
- checkFile = flag.String("c", "", "optional comma-separated filename(s) to check API against")
- allowNew = flag.Bool("allow_new", true, "allow API additions")
- exceptFile = flag.String("except", "", "optional filename of packages that are allowed to change without triggering a failure in the tool")
- nextFile = flag.String("next", "", "optional filename of tentative upcoming API features for the next release. This file can be lazily maintained. It only affects the delta warnings from the -c file printed on success.")
- verbose = flag.Bool("v", false, "verbose debugging")
- forceCtx = flag.String("contexts", "", "optional comma-separated list of -[-cgo] to override default contexts.")
+ checkFiles = flag.String("c", "", "optional comma-separated filename(s) to check API against")
+ requireApproval = flag.String("approval", "", "require approvals in comma-separated list of `files`")
+ allowNew = flag.Bool("allow_new", true, "allow API additions")
+ exceptFile = flag.String("except", "", "optional filename of packages that are allowed to change without triggering a failure in the tool")
+ nextFiles = flag.String("next", "", "comma-separated list of `files` for upcoming API features for the next release. These files can be lazily maintained. They only affects the delta warnings from the -c file printed on success.")
+ verbose = flag.Bool("v", false, "verbose debugging")
+ forceCtx = flag.String("contexts", "", "optional comma-separated list of -[-cgo] to override default contexts.")
)
// contexts are the default contexts which are scanned, unless
@@ -126,9 +128,9 @@ func main() {
flag.Parse()
if !strings.Contains(runtime.Version(), "weekly") && !strings.Contains(runtime.Version(), "devel") {
- if *nextFile != "" {
- fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFile)
- *nextFile = ""
+ if *nextFiles != "" {
+ fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFiles)
+ *nextFiles = ""
}
}
@@ -201,7 +203,7 @@ func main() {
bw := bufio.NewWriter(os.Stdout)
defer bw.Flush()
- if *checkFile == "" {
+ if *checkFiles == "" {
sort.Strings(features)
for _, f := range features {
fmt.Fprintln(bw, f)
@@ -210,10 +212,15 @@ func main() {
}
var required []string
- for _, file := range strings.Split(*checkFile, ",") {
+ for _, file := range strings.Split(*checkFiles, ",") {
required = append(required, fileFeatures(file)...)
}
- optional := fileFeatures(*nextFile)
+ var optional []string
+ if *nextFiles != "" {
+ for _, file := range strings.Split(*nextFiles, ",") {
+ optional = append(optional, fileFeatures(file)...)
+ }
+ }
exception := fileFeatures(*exceptFile)
fail = !compareAPI(bw, features, required, optional, exception, *allowNew)
}
@@ -340,6 +347,13 @@ func fileFeatures(filename string) []string {
if filename == "" {
return nil
}
+ needApproval := false
+ for _, name := range strings.Split(*requireApproval, ",") {
+ if filename == name {
+ needApproval = true
+ break
+ }
+ }
bs, err := os.ReadFile(filename)
if err != nil {
log.Fatalf("Error reading file %s: %v", filename, err)
@@ -348,11 +362,23 @@ func fileFeatures(filename string) []string {
s = aliasReplacer.Replace(s)
lines := strings.Split(s, "\n")
var nonblank []string
- for _, line := range lines {
+ for i, line := range lines {
line = strings.TrimSpace(line)
- if line != "" && !strings.HasPrefix(line, "#") {
- nonblank = append(nonblank, line)
+ if line == "" || strings.HasPrefix(line, "#") {
+ continue
}
+ if needApproval {
+ feature, approval, ok := strings.Cut(line, "#")
+ if !ok {
+ log.Fatalf("%s:%d: missing proposal approval\n", filename, i+1)
+ }
+ _, err := strconv.Atoi(approval)
+ if err != nil {
+ log.Fatalf("%s:%d: malformed proposal approval #%s\n", filename, i+1, approval)
+ }
+ line = strings.TrimSpace(feature)
+ }
+ nonblank = append(nonblank, line)
}
return nonblank
}
diff --git a/src/cmd/api/run.go b/src/cmd/api/run.go
index 1b94a1b883..130166e7b9 100644
--- a/src/cmd/api/run.go
+++ b/src/cmd/api/run.go
@@ -18,6 +18,7 @@ import (
"os"
"path/filepath"
"runtime"
+ "strconv"
"strings"
)
@@ -41,51 +42,66 @@ func main() {
if goroot == "" {
log.Fatal("No $GOROOT set.")
}
+ if err := os.Chdir(filepath.Join(goroot, "api")); err != nil {
+ log.Fatal(err)
+ }
- apiDir := filepath.Join(goroot, "api")
- out, err := exec.Command(goCmd(), "tool", "api",
- "-c", findAPIDirFiles(apiDir),
- allowNew(apiDir),
- "-next", filepath.Join(apiDir, "next.txt"),
- "-except", filepath.Join(apiDir, "except.txt")).CombinedOutput()
+ files, err := filepath.Glob("go1*.txt")
+ if err != nil {
+ log.Fatal(err)
+ }
+ next, err := filepath.Glob(filepath.Join("next", "*.txt"))
+ if err != nil {
+ log.Fatal(err)
+ }
+ cmd := exec.Command(goCmd(), "tool", "api",
+ "-c", strings.Join(files, ","),
+ "-approval", strings.Join(append(approvalNeeded(files), next...), ","),
+ allowNew(),
+ "-next", strings.Join(next, ","),
+ "-except", "except.txt",
+ )
+ fmt.Println(cmd.Args)
+ out, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("Error running API checker: %v\n%s", err, out)
}
fmt.Print(string(out))
}
-// findAPIDirFiles returns a comma-separated list of Go API files
-// (go1.txt, go1.1.txt, etc.) located in apiDir.
-func findAPIDirFiles(apiDir string) string {
- dir, err := os.Open(apiDir)
- if err != nil {
- log.Fatal(err)
- }
- defer dir.Close()
- fs, err := dir.Readdirnames(-1)
- if err != nil {
- log.Fatal(err)
- }
- var apiFiles []string
- for _, fn := range fs {
- if strings.HasPrefix(fn, "go1") {
- apiFiles = append(apiFiles, filepath.Join(apiDir, fn))
+func approvalNeeded(files []string) []string {
+ var out []string
+ for _, f := range files {
+ name := filepath.Base(f)
+ if name == "go1.txt" {
+ continue
+ }
+ minor := strings.TrimSuffix(strings.TrimPrefix(name, "go1."), ".txt")
+ n, err := strconv.Atoi(minor)
+ if err != nil {
+ log.Fatalf("unexpected api file: %v", f)
+ }
+ if n >= 19 { // approvals started being tracked in Go 1.19
+ out = append(out, f)
}
}
- return strings.Join(apiFiles, ",")
+ return out
}
// allowNew returns the -allow_new flag to use for the 'go tool api' invocation.
-func allowNew(apiDir string) string {
+func allowNew() string {
+ // Experiment for Go 1.19: always require api file updates.
+ return "-allow_new=false"
+
// Verify that the api/go1.n.txt for previous Go version exists.
// It definitely should, otherwise it's a signal that the logic below may be outdated.
- if _, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version-1))); err != nil {
+ if _, err := os.Stat(fmt.Sprintf("go1.%d.txt", goversion.Version-1)); err != nil {
log.Fatalln("Problem with api file for previous release:", err)
}
// See whether the api/go1.n.txt for this Go version has been created.
// (As of April 2021, it gets created during the release of the first Beta.)
- _, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version)))
+ _, err := os.Stat(fmt.Sprintf("go1.%d.txt", goversion.Version))
if errors.Is(err, fs.ErrNotExist) {
// It doesn't exist, so we're in development or before Beta 1.
// At this stage, unmentioned API additions are deemed okay.
From 15728ce950eea43d6f1b9fb29819d006071e843a Mon Sep 17 00:00:00 2001
From: Keith Randall
Date: Mon, 14 Mar 2022 15:17:43 -0700
Subject: [PATCH 094/276] cmd/compile: disable rewrite loop detector for
deadcode-only changes
We're guaranteed we won't infinite loop on deadcode-only changes,
because each change converts valid -> invalid, and there are only a
finite number of valid values.
The loops this test is looking for are those generated by rule
applications, so it isn't useful to check for loops when rules aren't
involved.
Fixes #51639
Change-Id: Idf1abeab9d47baafddc3a1197d5064faaf07ef78
Reviewed-on: https://go-review.googlesource.com/c/go/+/392760
Trust: Keith Randall
Run-TryBot: Keith Randall
TryBot-Result: Gopher Robot
Reviewed-by: Josh Bleecher Snyder
Trust: Josh Bleecher Snyder
---
src/cmd/compile/internal/ssa/rewrite.go | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go
index 9136c59e65..eb8fa0c02a 100644
--- a/src/cmd/compile/internal/ssa/rewrite.go
+++ b/src/cmd/compile/internal/ssa/rewrite.go
@@ -40,6 +40,7 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu
var states map[string]bool
for {
change := false
+ deadChange := false
for _, b := range f.Blocks {
var b0 *Block
if debug > 1 {
@@ -73,7 +74,7 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu
// Not quite a deadcode pass, because it does not handle cycles.
// But it should help Uses==1 rules to fire.
v.reset(OpInvalid)
- change = true
+ deadChange = true
}
// No point rewriting values which aren't used.
continue
@@ -145,15 +146,16 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu
}
}
}
- if !change {
+ if !change && !deadChange {
break
}
iters++
- if iters > 1000 || debug >= 2 {
+ if (iters > 1000 || debug >= 2) && change {
// We've done a suspiciously large number of rewrites (or we're in debug mode).
// As of Sep 2021, 90% of rewrites complete in 4 iterations or fewer
// and the maximum value encountered during make.bash is 12.
// Start checking for cycles. (This is too expensive to do routinely.)
+ // Note: we avoid this path for deadChange-only iterations, to fix #51639.
if states == nil {
states = make(map[string]bool)
}
From 41a82aa9c36bffab2593d50aa55a462fef4e5bd4 Mon Sep 17 00:00:00 2001
From: Rob Pike
Date: Tue, 15 Mar 2022 10:21:08 +1100
Subject: [PATCH 095/276] text/template/parse: allow space after continue or
break
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Trivial fix: We must skip space after either of these keywords
before we expect a closing delimiter.
Also delete the stutter-generating extra 'in' in the error message.
(See what I did there?)
Fixes #51670
Change-Id: If5415632c36eaac6699bdc0aa6ce18be956c9b53
Reviewed-on: https://go-review.googlesource.com/c/go/+/392615
Reviewed-by: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
Reviewed-by: Daniel Martí
Trust: Daniel Martí
TryBot-Result: Gopher Robot
---
src/text/template/parse/parse.go | 8 ++++----
src/text/template/parse/parse_test.go | 4 ++++
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go
index b0cbe9dfc8..ce548b0886 100644
--- a/src/text/template/parse/parse.go
+++ b/src/text/template/parse/parse.go
@@ -415,8 +415,8 @@ func (t *Tree) action() (n Node) {
// {{break}}
// Break keyword is past.
func (t *Tree) breakControl(pos Pos, line int) Node {
- if token := t.next(); token.typ != itemRightDelim {
- t.unexpected(token, "in {{break}}")
+ if token := t.nextNonSpace(); token.typ != itemRightDelim {
+ t.unexpected(token, "{{break}}")
}
if t.rangeDepth == 0 {
t.errorf("{{break}} outside {{range}}")
@@ -428,8 +428,8 @@ func (t *Tree) breakControl(pos Pos, line int) Node {
// {{continue}}
// Continue keyword is past.
func (t *Tree) continueControl(pos Pos, line int) Node {
- if token := t.next(); token.typ != itemRightDelim {
- t.unexpected(token, "in {{continue}}")
+ if token := t.nextNonSpace(); token.typ != itemRightDelim {
+ t.unexpected(token, "{{continue}}")
}
if t.rangeDepth == 0 {
t.errorf("{{continue}} outside {{range}}")
diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go
index 0c4778c7b3..fdb25d78f5 100644
--- a/src/text/template/parse/parse_test.go
+++ b/src/text/template/parse/parse_test.go
@@ -260,6 +260,10 @@ var parseTests = []parseTest{
{"newline in pipeline", "{{\n\"x\"\n|\nprintf\n}}", noError, `{{"x" | printf}}`},
{"newline in comment", "{{/*\nhello\n*/}}", noError, ""},
{"newline in comment", "{{-\n/*\nhello\n*/\n-}}", noError, ""},
+ {"spaces around continue", "{{range .SI}}{{.}}{{ continue }}{{end}}", noError,
+ `{{range .SI}}{{.}}{{continue}}{{end}}`},
+ {"spaces around break", "{{range .SI}}{{.}}{{ break }}{{end}}", noError,
+ `{{range .SI}}{{.}}{{break}}{{end}}`},
// Errors.
{"unclosed action", "hello{{range", hasError, ""},
From 44a0da4ff11a5447dcfe2b62ac46bca134736d81 Mon Sep 17 00:00:00 2001
From: eric fang
Date: Tue, 20 Apr 2021 02:46:33 +0000
Subject: [PATCH 096/276] cmd/internal/obj/arm64: refactor the handling of
shifted RSP
Some arithmetic operation instructions such as ADD and SUB support two
formats of left shift (<<) operation, namely shifted register format and
extended register format. And the encoding, supported registers and shifted
amount are both different.
The assembly parser doesn't distinguish them and parses them into TYPE_SHIFT
type, because the parser can't tell them apart and in most cases extended
left-shift can be replaced by shifted left-shift. The only exception is
when the second source register or the destination register is RSP.
This CL converts this case into the extended format in the preprocess stage,
which helps to simplify some of the logic of the new assembler implementation
and also makes this situation look more reasonable.
Change-Id: I2cd7d2d663b38a7ba77a9fef1092708b8cb9bc3d
Reviewed-on: https://go-review.googlesource.com/c/go/+/311709
Trust: Eric Fang
Run-TryBot: Eric Fang
TryBot-Result: Gopher Robot
Reviewed-by: Cherry Mui
---
.../asm/internal/asm/testdata/arm64error.s | 4 +-
src/cmd/internal/obj/arm64/asm7.go | 61 +++++--------------
src/cmd/internal/obj/arm64/obj7.go | 18 ++++++
3 files changed, 35 insertions(+), 48 deletions(-)
diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s
index 3d3de1d9b1..033c4cda6c 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64error.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64error.s
@@ -417,8 +417,8 @@ TEXT errors(SB),$0
CASPD (R2, R4), (R2), (R8, R9) // ERROR "source register pair must be contiguous"
CASPD (R2, R3), (R2), (R8, R10) // ERROR "destination register pair must be contiguous"
ADD R1>>2, RSP, R3 // ERROR "illegal combination"
- ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference"
- CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4"
+ ADDS R2<<3, R3, RSP // ERROR "illegal destination register"
+ CMP R1<<5, RSP // ERROR "shift amount out of range 0 to 4"
MOVD.P y+8(FP), R1 // ERROR "illegal combination"
MOVD.W x-8(SP), R1 // ERROR "illegal combination"
LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination"
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index f4111f4f5c..5435b2248f 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -321,11 +321,8 @@ var optab = []Optab{
{ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0},
{AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
{AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
- {AADD, C_SHIFT, C_RSP, C_NONE, C_RSP, 26, 4, 0, 0, 0},
- {AADD, C_SHIFT, C_NONE, C_NONE, C_RSP, 26, 4, 0, 0, 0},
{AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
{ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
- {ACMP, C_SHIFT, C_RSP, C_NONE, C_NONE, 26, 4, 0, 0, 0},
{ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
{AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
{AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
@@ -1687,7 +1684,8 @@ func rclass(r int16) int {
return C_ARNG
case r >= REG_ELEM && r < REG_ELEM_END:
return C_ELEM
- case r >= REG_UXTB && r < REG_SPECIAL:
+ case r >= REG_UXTB && r < REG_SPECIAL,
+ r >= REG_LSL && r < REG_ARNG:
return C_EXTREG
case r >= REG_SPECIAL:
return C_SPR
@@ -3666,52 +3664,18 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
rt := int(p.To.Reg)
o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
- case 26: // op R<> 10) & 63
- shift := (p.From.Offset >> 22) & 3
- if shift != 0 {
- c.ctxt.Diag("illegal combination: %v", p)
- break
- }
-
- if amount > 4 {
- c.ctxt.Diag("the left shift amount out of range 0 to 4: %v", p)
- break
- }
- rf := (p.From.Offset >> 16) & 31
- rt := int(p.To.Reg)
- r := int(p.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- if r == 0 {
- r = rt
- }
-
- o1 = c.opxrrr(p, p.As, false)
- o1 |= uint32(rf)<<16 | uint32(amount&7)<<10 | (uint32(r&31) << 5) | uint32(rt&31)
-
case 27: /* op Rm<= REG_LSL && p.From.Reg < REG_ARNG) {
amount := (p.From.Reg >> 5) & 7
if amount > 4 {
c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
}
o1 = c.opxrrr(p, p.As, true)
- o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */
+ o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Reg) /* includes reg, op, etc */
} else {
o1 = c.opxrrr(p, p.As, false)
o1 |= uint32(p.From.Reg&31) << 16
@@ -5344,7 +5308,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
c.checkShiftAmount(p, &p.From)
o1 = c.opldrr(p, p.As, true)
- o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */
+ o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Index) /* includes reg, op, etc */
} else {
// (Rn)(Rm), no extension or shift.
o1 = c.opldrr(p, p.As, false)
@@ -5360,7 +5324,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
c.checkShiftAmount(p, &p.To)
o1 = c.opstrr(p, p.As, true)
- o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */
+ o1 |= c.encRegShiftOrExt(p, &p.To, p.To.Index) /* includes reg, op, etc */
} else {
// (Rn)(Rm), no extension or shift.
o1 = c.opstrr(p, p.As, false)
@@ -7427,7 +7391,7 @@ func roff(rm int16, o uint32, amount int16) uint32 {
}
// encRegShiftOrExt returns the encoding of shifted/extended register, Rx<> 5) & 7
rm = r & 31
@@ -7472,8 +7436,13 @@ func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 {
} else {
return roff(rm, 7, num)
}
- case REG_LSL <= r && r < (REG_LSL+1<<8):
- return roff(rm, 3, 6)
+ case REG_LSL <= r && r < REG_ARNG:
+ if a.Type == obj.TYPE_MEM { // (R1)(R2<<1)
+ return roff(rm, 3, 6)
+ } else if isADDWop(p.As) {
+ return roff(rm, 2, num)
+ }
+ return roff(rm, 3, num)
default:
c.ctxt.Diag("unsupported register extension type.")
}
diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go
index 43f7b16d6e..ee5a6fa273 100644
--- a/src/cmd/internal/obj/arm64/obj7.go
+++ b/src/cmd/internal/obj/arm64/obj7.go
@@ -1089,6 +1089,24 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
}
}
}
+ if p.From.Type == obj.TYPE_SHIFT && (p.To.Reg == REG_RSP || p.Reg == REG_RSP) {
+ offset := p.From.Offset
+ op := offset & (3 << 22)
+ if op != SHIFT_LL {
+ ctxt.Diag("illegal combination: %v", p)
+ }
+ r := (offset >> 16) & 31
+ shift := (offset >> 10) & 63
+ if shift > 4 {
+ // the shift amount is out of range, in order to avoid repeated error
+ // reportings, don't call ctxt.Diag, because asmout case 27 has the
+ // same check.
+ shift = 7
+ }
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = int16(REG_LSL + r + (shift&7)<<5)
+ p.From.Offset = 0
+ }
}
}
From 49f16625c82483ab26929a2761031c93dd5d2c83 Mon Sep 17 00:00:00 2001
From: fanzha02
Date: Mon, 14 Mar 2022 02:40:25 +0000
Subject: [PATCH 097/276] cmd/internal/obj/arm64: add TRN1 and TRN2
instructions support
Add test cases.
Fixes #51628
Change-Id: I433367d87e6bb5da5579c4be540079b92701c1fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/392294
Trust: Josh Bleecher Snyder
Reviewed-by: Josh Bleecher Snyder
Reviewed-by: Cherry Mui
Trust: Fannie Zhang
---
src/cmd/asm/internal/asm/testdata/arm64.s | 4 ++++
src/cmd/internal/obj/arm64/a.out.go | 2 ++
src/cmd/internal/obj/arm64/anames.go | 2 ++
src/cmd/internal/obj/arm64/asm7.go | 8 ++++++++
4 files changed, 16 insertions(+)
diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s
index a4b56b0696..8a7dd299aa 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64.s
@@ -241,6 +241,10 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
FADDS F2, F3, F4 // 6428221e
FADDD F1, F2 // 4228611e
VDUP V19.S[0], V17.S4 // 7106044e
+ VTRN1 V3.D2, V2.D2, V20.D2 // 5428c34e
+ VTRN2 V3.D2, V2.D2, V21.D2 // 5568c34e
+ VTRN1 V5.D2, V4.D2, V22.D2 // 9628c54e
+ VTRN2 V5.D2, V4.D2, V23.D2 // 9768c54e
// special
diff --git a/src/cmd/internal/obj/arm64/a.out.go b/src/cmd/internal/obj/arm64/a.out.go
index aa7c54df9a..f3480e0f5e 100644
--- a/src/cmd/internal/obj/arm64/a.out.go
+++ b/src/cmd/internal/obj/arm64/a.out.go
@@ -1053,6 +1053,8 @@ const (
AVUADDW2
AVUADDW
AVUSRA
+ AVTRN1
+ AVTRN2
ALAST
AB = obj.AJMP
ABL = obj.ACALL
diff --git a/src/cmd/internal/obj/arm64/anames.go b/src/cmd/internal/obj/arm64/anames.go
index 9cc5871648..ab97a1a130 100644
--- a/src/cmd/internal/obj/arm64/anames.go
+++ b/src/cmd/internal/obj/arm64/anames.go
@@ -537,5 +537,7 @@ var Anames = []string{
"VUADDW2",
"VUADDW",
"VUSRA",
+ "VTRN1",
+ "VTRN2",
"LAST",
}
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index 5435b2248f..244430eb8f 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -2985,6 +2985,8 @@ func buildop(ctxt *obj.Link) {
case AVZIP1:
oprangeset(AVZIP2, t)
+ oprangeset(AVTRN1, t)
+ oprangeset(AVTRN2, t)
case AVUXTL:
oprangeset(AVUXTL2, t)
@@ -6179,6 +6181,12 @@ func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
case AVUADDW, AVUADDW2:
return 0x17<<25 | 1<<21 | 1<<12
+
+ case AVTRN1:
+ return 7<<25 | 5<<11
+
+ case AVTRN2:
+ return 7<<25 | 1<<14 | 5<<11
}
c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
From e475cf2e705d4eda8647426e060898ab3f643610 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Mon, 14 Mar 2022 17:39:35 -0700
Subject: [PATCH 098/276] syscall: add race annotations to Windows ReadFile and
WriteFile
For #51618
Fixes #51673
Change-Id: Ie63408d62303293d80afed8d5cf1cb164a8abecc
Reviewed-on: https://go-review.googlesource.com/c/go/+/392774
Trust: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
Reviewed-by: Keith Randall
TryBot-Result: Gopher Robot
---
src/syscall/syscall_windows.go | 62 +++++++++++++++++++--------------
src/syscall/zsyscall_windows.go | 4 +--
2 files changed, 38 insertions(+), 28 deletions(-)
diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go
index 78e46a656d..aba6c3f5fb 100644
--- a/src/syscall/syscall_windows.go
+++ b/src/syscall/syscall_windows.go
@@ -202,8 +202,8 @@ func NewCallbackCDecl(fn any) uintptr {
//sys formatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
//sys ExitProcess(exitcode uint32)
//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (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)
+//sys readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = ReadFile
+//sys writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = WriteFile
//sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff]
//sys CloseHandle(handle Handle) (err error)
//sys GetStdHandle(stdhandle int) (handle Handle, err error) [failretval==InvalidHandle]
@@ -385,42 +385,52 @@ func Read(fd Handle, p []byte) (n int, err error) {
}
return 0, e
}
- if race.Enabled {
- if done > 0 {
- race.WriteRange(unsafe.Pointer(&p[0]), int(done))
- }
- race.Acquire(unsafe.Pointer(&ioSync))
- }
- if msanenabled && done > 0 {
- msanWrite(unsafe.Pointer(&p[0]), int(done))
- }
- if asanenabled && done > 0 {
- asanWrite(unsafe.Pointer(&p[0]), int(done))
- }
return int(done), nil
}
func Write(fd Handle, p []byte) (n int, err error) {
- if race.Enabled {
- race.ReleaseMerge(unsafe.Pointer(&ioSync))
- }
var done uint32
e := WriteFile(fd, p, &done, nil)
if e != nil {
return 0, e
}
- if race.Enabled && done > 0 {
- race.ReadRange(unsafe.Pointer(&p[0]), int(done))
- }
- if msanenabled && done > 0 {
- msanRead(unsafe.Pointer(&p[0]), int(done))
- }
- if asanenabled && done > 0 {
- asanRead(unsafe.Pointer(&p[0]), int(done))
- }
return int(done), nil
}
+func ReadFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error {
+ err := readFile(fd, p, done, overlapped)
+ if race.Enabled {
+ if *done > 0 {
+ race.WriteRange(unsafe.Pointer(&p[0]), int(*done))
+ }
+ race.Acquire(unsafe.Pointer(&ioSync))
+ }
+ if msanenabled && *done > 0 {
+ msanWrite(unsafe.Pointer(&p[0]), int(*done))
+ }
+ if asanenabled && *done > 0 {
+ asanWrite(unsafe.Pointer(&p[0]), int(*done))
+ }
+ return err
+}
+
+func WriteFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error {
+ if race.Enabled {
+ race.ReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ err := writeFile(fd, p, done, overlapped)
+ if race.Enabled && *done > 0 {
+ race.ReadRange(unsafe.Pointer(&p[0]), int(*done))
+ }
+ if msanenabled && *done > 0 {
+ msanRead(unsafe.Pointer(&p[0]), int(*done))
+ }
+ if asanenabled && *done > 0 {
+ asanRead(unsafe.Pointer(&p[0]), int(*done))
+ }
+ return err
+}
+
var ioSync int64
var procSetFilePointerEx = modkernel32.NewProc("SetFilePointerEx")
diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go
index 2d6f34e059..61d89f1460 100644
--- a/src/syscall/zsyscall_windows.go
+++ b/src/syscall/zsyscall_windows.go
@@ -1016,7 +1016,7 @@ func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree
return
}
-func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
+func readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
var _p0 *byte
if len(buf) > 0 {
_p0 = &buf[0]
@@ -1158,7 +1158,7 @@ func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32,
return
}
-func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
+func writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
var _p0 *byte
if len(buf) > 0 {
_p0 = &buf[0]
From 7b15e297a26842f1f3408ee9d7942f8cfab2e5ea Mon Sep 17 00:00:00 2001
From: Archana R
Date: Mon, 7 Mar 2022 01:54:14 -0600
Subject: [PATCH 099/276] cmd/compile: fix PrefetchStreamed builtin
implementation on PPC64
This CL fixes encoding of PrefetchStreamed on PPC64 to be consistent
with what is implemented on AMD64 and ARM64 platforms which is
prefetchNTA (prefetch non-temporal access). Looking at the definition
of prefetchNTA, the closest corresponding Touch hint (TH) value to be
used on PPC64 is 16 that states that the address is accessed in a
transient manner. Current usage of TH=8 may cause degraded
performance.
Change-Id: I393bf5a9b971a22f632b3cbfb4fa659062af9a27
Reviewed-on: https://go-review.googlesource.com/c/go/+/390316
Reviewed-by: Paul Murphy
Reviewed-by: Cherry Mui
Run-TryBot: Cherry Mui
TryBot-Result: Gopher Robot
---
src/cmd/compile/internal/ssa/gen/PPC64.rules | 8 ++++++--
src/cmd/compile/internal/ssa/rewritePPC64.go | 4 ++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules
index c3f07a4e22..eb9fe3cf72 100644
--- a/src/cmd/compile/internal/ssa/gen/PPC64.rules
+++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules
@@ -1479,7 +1479,11 @@
&& clobber(call)
=> (Move [sz] dst src mem)
-// Prefetch instructions (aux is option: 0 - DCBT ; 8 - DCBT stream)
+// Prefetch instructions (TH specified using aux field)
+// For DCBT Ra,Rb,TH, A value of TH indicates:
+// 0, hint this cache line will be used soon. (PrefetchCache)
+// 16, hint this cache line will not be used for long. (PrefetchCacheStreamed)
+// See ISA 3.0 Book II 4.3.2 for more detail. https://openpower.foundation/specifications/isa/
(PrefetchCache ptr mem) => (DCBT ptr mem [0])
-(PrefetchCacheStreamed ptr mem) => (DCBT ptr mem [8])
+(PrefetchCacheStreamed ptr mem) => (DCBT ptr mem [16])
diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go
index 7592b4f505..5da6d9641c 100644
--- a/src/cmd/compile/internal/ssa/rewritePPC64.go
+++ b/src/cmd/compile/internal/ssa/rewritePPC64.go
@@ -14140,12 +14140,12 @@ func rewriteValuePPC64_OpPrefetchCacheStreamed(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (PrefetchCacheStreamed ptr mem)
- // result: (DCBT ptr mem [8])
+ // result: (DCBT ptr mem [16])
for {
ptr := v_0
mem := v_1
v.reset(OpPPC64DCBT)
- v.AuxInt = int64ToAuxInt(8)
+ v.AuxInt = int64ToAuxInt(16)
v.AddArg2(ptr, mem)
return true
}
From b054c7dc1738c810e74756ae0ac4797ce5d31cf6 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Mon, 14 Mar 2022 11:27:46 -0400
Subject: [PATCH 100/276] os: raise open file rlimit at startup
Some systems set an artificially low soft limit on open file count,
for compatibility with code that uses select and its hard-coded
maximum file descriptor (limited by the size of fd_set).
Go does not use select, so it should not be subject to these limits.
On some systems the limit is 256, which is very easy to run into, even
in simple programs like gofmt when they parallelize walking a file tree.
After a long discussion on go.dev/issue/46279, we decided the best
approach was for Go to raise the limit unconditionally for itself, and
then leave old software to set the limit back as needed. Code that
really wants Go to leave the limit alone can set the hard limit, which
Go of course has no choice but to respect.
Fixes #46279.
Change-Id: Id6107503437d47a870a41be25e822fc79cea08b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/392415
Trust: Russ Cox
Run-TryBot: Russ Cox
TryBot-Result: Gopher Robot
Reviewed-by: Ian Lance Taylor
---
src/os/rlimit.go | 31 +++++++++++++++++++++++++++++++
src/os/rlimit_test.go | 32 ++++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+)
create mode 100644 src/os/rlimit.go
create mode 100644 src/os/rlimit_test.go
diff --git a/src/os/rlimit.go b/src/os/rlimit.go
new file mode 100644
index 0000000000..3e29db9562
--- /dev/null
+++ b/src/os/rlimit.go
@@ -0,0 +1,31 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
+
+package os
+
+import "syscall"
+
+// Some systems set an artificially low soft limit on open file count, for compatibility
+// with code that uses select and its hard-coded maximum file descriptor
+// (limited by the size of fd_set).
+//
+// Go does not use select, so it should not be subject to these limits.
+// On some systems the limit is 256, which is very easy to run into,
+// even in simple programs like gofmt when they parallelize walking
+// a file tree.
+//
+// After a long discussion on go.dev/issue/46279, we decided the
+// best approach was for Go to raise the limit unconditionally for itself,
+// and then leave old software to set the limit back as needed.
+// Code that really wants Go to leave the limit alone can set the hard limit,
+// which Go of course has no choice but to respect.
+func init() {
+ var lim syscall.Rlimit
+ if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err == nil && lim.Cur != lim.Max {
+ lim.Cur = lim.Max
+ syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim)
+ }
+}
diff --git a/src/os/rlimit_test.go b/src/os/rlimit_test.go
new file mode 100644
index 0000000000..9bb6858a86
--- /dev/null
+++ b/src/os/rlimit_test.go
@@ -0,0 +1,32 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os_test
+
+import (
+ . "os"
+ "testing"
+)
+
+func TestOpenFileLimit(t *testing.T) {
+ // For open file count,
+ // macOS sets the default soft limit to 256 and no hard limit.
+ // CentOS and Fedora set the default soft limit to 1024,
+ // with hard limits of 4096 and 524288, respectively.
+ // Check that we can open 1200 files, which proves
+ // that the rlimit is being raised appropriately on those systems.
+ var files []*File
+ for i := 0; i < 1200; i++ {
+ f, err := Open("rlimit.go")
+ if err != nil {
+ t.Error(err)
+ break
+ }
+ files = append(files, f)
+ }
+
+ for _, f := range files {
+ f.Close()
+ }
+}
From 9b112cec8363c0c574750d92cffe8682e80aacbe Mon Sep 17 00:00:00 2001
From: Keith Randall
Date: Tue, 15 Mar 2022 08:56:07 -0700
Subject: [PATCH 101/276] internal/cpu: don't run SSE3 disable test if
GOAMD64>1
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
That feature can't be disabled if the microarchitectural version
requires it.
Change-Id: Iad8aaa8089d2f023e9ae5044c6da33224499f09b
Reviewed-on: https://go-review.googlesource.com/c/go/+/392994
Run-TryBot: Keith Randall
Trust: Keith Randall
Reviewed-by: Tobias Klauser
Reviewed-by: Martin Möhrmann
TryBot-Result: Gopher Robot
---
src/internal/cpu/cpu_x86_test.go | 3 +++
src/internal/cpu/export_x86_test.go | 11 +++++++++++
2 files changed, 14 insertions(+)
create mode 100644 src/internal/cpu/export_x86_test.go
diff --git a/src/internal/cpu/cpu_x86_test.go b/src/internal/cpu/cpu_x86_test.go
index c8be210055..43d6b211ea 100644
--- a/src/internal/cpu/cpu_x86_test.go
+++ b/src/internal/cpu/cpu_x86_test.go
@@ -19,6 +19,9 @@ func TestX86ifAVX2hasAVX(t *testing.T) {
}
func TestDisableSSE3(t *testing.T) {
+ if GetGOAMD64level() > 1 {
+ t.Skip("skipping test: can't run on GOAMD64>v1 machines")
+ }
runDebugOptionsTest(t, "TestSSE3DebugOption", "cpu.sse3=off")
}
diff --git a/src/internal/cpu/export_x86_test.go b/src/internal/cpu/export_x86_test.go
new file mode 100644
index 0000000000..a12b6f2723
--- /dev/null
+++ b/src/internal/cpu/export_x86_test.go
@@ -0,0 +1,11 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build 386 || amd64
+
+package cpu
+
+var (
+ GetGOAMD64level = getGOAMD64level
+)
From 1178255f8596ea503daf30c84c7c1039f755e7f0 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Thu, 3 Feb 2022 11:50:45 -0500
Subject: [PATCH 102/276] all: untab /* */ doc comments
A long time ago, gofmt insisted on inserting tabs in /* */ comments
at the top level of the file, like this:
/*
Package doc comment.
*/
package p
Gofmt still insists on the tab for comments not at top level,
but it has relaxed the rules about top-level comments.
A few very old doc comments are indented, left over from the old rule.
We are considering formatting doc comments, and so to make
everything consistent, standardize on unindented doc comments
by removing tabs in the few doc comments that are still indented this way.
Also update some cmd/gofmt testdata to match.
Change-Id: I293742e39b52f8a48ec41f72ca4acdafa7ce43bc
Reviewed-on: https://go-review.googlesource.com/c/go/+/384261
Trust: Russ Cox
Run-TryBot: Russ Cox
TryBot-Result: Gopher Robot
Reviewed-by: Ian Lance Taylor
---
src/builtin/builtin.go | 8 +-
src/cmd/gofmt/testdata/crlf.golden | 8 +-
src/cmd/gofmt/testdata/crlf.input | 8 +-
src/cmd/gofmt/testdata/typeswitch.golden | 22 +-
src/cmd/gofmt/testdata/typeswitch.input | 22 +-
src/flag/flag.go | 98 ++--
src/fmt/doc.go | 570 +++++++++++------------
src/go/doc/headscan.go | 10 +-
src/net/rpc/server.go | 190 ++++----
src/runtime/debug/stack_test.go | 30 +-
src/unsafe/unsafe.go | 6 +-
11 files changed, 486 insertions(+), 486 deletions(-)
diff --git a/src/builtin/builtin.go b/src/builtin/builtin.go
index 5657be4564..8997902f8f 100644
--- a/src/builtin/builtin.go
+++ b/src/builtin/builtin.go
@@ -3,10 +3,10 @@
// license that can be found in the LICENSE file.
/*
- Package builtin provides documentation for Go's predeclared identifiers.
- The items documented here are not actually in package builtin
- but their descriptions here allow godoc to present documentation
- for the language's special identifiers.
+Package builtin provides documentation for Go's predeclared identifiers.
+The items documented here are not actually in package builtin
+but their descriptions here allow godoc to present documentation
+for the language's special identifiers.
*/
package builtin
diff --git a/src/cmd/gofmt/testdata/crlf.golden b/src/cmd/gofmt/testdata/crlf.golden
index 193dbacc72..65de9cf199 100644
--- a/src/cmd/gofmt/testdata/crlf.golden
+++ b/src/cmd/gofmt/testdata/crlf.golden
@@ -1,8 +1,8 @@
/*
- Source containing CR/LF line endings.
- The gofmt'ed output must only have LF
- line endings.
- Test case for issue 3961.
+Source containing CR/LF line endings.
+The gofmt'ed output must only have LF
+line endings.
+Test case for issue 3961.
*/
package main
diff --git a/src/cmd/gofmt/testdata/crlf.input b/src/cmd/gofmt/testdata/crlf.input
index ae7e14dbf1..3cd4934caf 100644
--- a/src/cmd/gofmt/testdata/crlf.input
+++ b/src/cmd/gofmt/testdata/crlf.input
@@ -1,8 +1,8 @@
/*
- Source containing CR/LF line endings.
- The gofmt'ed output must only have LF
- line endings.
- Test case for issue 3961.
+Source containing CR/LF line endings.
+The gofmt'ed output must only have LF
+line endings.
+Test case for issue 3961.
*/
package main
diff --git a/src/cmd/gofmt/testdata/typeswitch.golden b/src/cmd/gofmt/testdata/typeswitch.golden
index 2b1905edd3..3cf4dca7d4 100644
--- a/src/cmd/gofmt/testdata/typeswitch.golden
+++ b/src/cmd/gofmt/testdata/typeswitch.golden
@@ -1,17 +1,17 @@
/*
- Parenthesized type switch expressions originally
- accepted by gofmt must continue to be rewritten
- into the correct unparenthesized form.
+Parenthesized type switch expressions originally
+accepted by gofmt must continue to be rewritten
+into the correct unparenthesized form.
- Only type-switches that didn't declare a variable
- in the type switch type assertion and which
- contained only "expression-like" (named) types in their
- cases were permitted to have their type assertion parenthesized
- by go/parser (due to a weak predicate in the parser). All others
- were rejected always, either with a syntax error in the
- type switch header or in the case.
+Only type-switches that didn't declare a variable
+in the type switch type assertion and which
+contained only "expression-like" (named) types in their
+cases were permitted to have their type assertion parenthesized
+by go/parser (due to a weak predicate in the parser). All others
+were rejected always, either with a syntax error in the
+type switch header or in the case.
- See also issue 4470.
+See also issue 4470.
*/
package p
diff --git a/src/cmd/gofmt/testdata/typeswitch.input b/src/cmd/gofmt/testdata/typeswitch.input
index 8f8cba9b85..992a772d52 100644
--- a/src/cmd/gofmt/testdata/typeswitch.input
+++ b/src/cmd/gofmt/testdata/typeswitch.input
@@ -1,17 +1,17 @@
/*
- Parenthesized type switch expressions originally
- accepted by gofmt must continue to be rewritten
- into the correct unparenthesized form.
+Parenthesized type switch expressions originally
+accepted by gofmt must continue to be rewritten
+into the correct unparenthesized form.
- Only type-switches that didn't declare a variable
- in the type switch type assertion and which
- contained only "expression-like" (named) types in their
- cases were permitted to have their type assertion parenthesized
- by go/parser (due to a weak predicate in the parser). All others
- were rejected always, either with a syntax error in the
- type switch header or in the case.
+Only type-switches that didn't declare a variable
+in the type switch type assertion and which
+contained only "expression-like" (named) types in their
+cases were permitted to have their type assertion parenthesized
+by go/parser (due to a weak predicate in the parser). All others
+were rejected always, either with a syntax error in the
+type switch header or in the case.
- See also issue 4470.
+See also issue 4470.
*/
package p
diff --git a/src/flag/flag.go b/src/flag/flag.go
index c27a144434..cdea949a2f 100644
--- a/src/flag/flag.go
+++ b/src/flag/flag.go
@@ -3,67 +3,67 @@
// license that can be found in the LICENSE file.
/*
- Package flag implements command-line flag parsing.
+Package flag implements command-line flag parsing.
- Usage
+Usage
- Define flags using flag.String(), Bool(), Int(), etc.
+Define flags using flag.String(), Bool(), Int(), etc.
- This declares an integer flag, -n, stored in the pointer nFlag, with type *int:
- import "flag"
- var nFlag = flag.Int("n", 1234, "help message for flag n")
- If you like, you can bind the flag to a variable using the Var() functions.
- var flagvar int
- func init() {
- flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
- }
- Or you can create custom flags that satisfy the Value interface (with
- pointer receivers) and couple them to flag parsing by
- flag.Var(&flagVal, "name", "help message for flagname")
- For such flags, the default value is just the initial value of the variable.
+This declares an integer flag, -n, stored in the pointer nFlag, with type *int:
+ import "flag"
+ var nFlag = flag.Int("n", 1234, "help message for flag n")
+If you like, you can bind the flag to a variable using the Var() functions.
+ var flagvar int
+ func init() {
+ flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
+ }
+Or you can create custom flags that satisfy the Value interface (with
+pointer receivers) and couple them to flag parsing by
+ flag.Var(&flagVal, "name", "help message for flagname")
+For such flags, the default value is just the initial value of the variable.
- After all flags are defined, call
- flag.Parse()
- to parse the command line into the defined flags.
+After all flags are defined, call
+ flag.Parse()
+to parse the command line into the defined flags.
- Flags may then be used directly. If you're using the flags themselves,
- they are all pointers; if you bind to variables, they're values.
- fmt.Println("ip has value ", *ip)
- fmt.Println("flagvar has value ", flagvar)
+Flags may then be used directly. If you're using the flags themselves,
+they are all pointers; if you bind to variables, they're values.
+ fmt.Println("ip has value ", *ip)
+ fmt.Println("flagvar has value ", flagvar)
- After parsing, the arguments following the flags are available as the
- slice flag.Args() or individually as flag.Arg(i).
- The arguments are indexed from 0 through flag.NArg()-1.
+After parsing, the arguments following the flags are available as the
+slice flag.Args() or individually as flag.Arg(i).
+The arguments are indexed from 0 through flag.NArg()-1.
- Command line flag syntax
+Command line flag syntax
- The following forms are permitted:
+The following forms are permitted:
- -flag
- -flag=x
- -flag x // non-boolean flags only
- One or two minus signs may be used; they are equivalent.
- The last form is not permitted for boolean flags because the
- meaning of the command
- cmd -x *
- where * is a Unix shell wildcard, will change if there is a file
- called 0, false, etc. You must use the -flag=false form to turn
- off a boolean flag.
+ -flag
+ -flag=x
+ -flag x // non-boolean flags only
+One or two minus signs may be used; they are equivalent.
+The last form is not permitted for boolean flags because the
+meaning of the command
+ cmd -x *
+where * is a Unix shell wildcard, will change if there is a file
+called 0, false, etc. You must use the -flag=false form to turn
+off a boolean flag.
- Flag parsing stops just before the first non-flag argument
- ("-" is a non-flag argument) or after the terminator "--".
+Flag parsing stops just before the first non-flag argument
+("-" is a non-flag argument) or after the terminator "--".
- Integer flags accept 1234, 0664, 0x1234 and may be negative.
- Boolean flags may be:
- 1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False
- Duration flags accept any input valid for time.ParseDuration.
+Integer flags accept 1234, 0664, 0x1234 and may be negative.
+Boolean flags may be:
+ 1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False
+Duration flags accept any input valid for time.ParseDuration.
- The default set of command-line flags is controlled by
- top-level functions. The FlagSet type allows one to define
- independent sets of flags, such as to implement subcommands
- in a command-line interface. The methods of FlagSet are
- analogous to the top-level functions for the command-line
- flag set.
+The default set of command-line flags is controlled by
+top-level functions. The FlagSet type allows one to define
+independent sets of flags, such as to implement subcommands
+in a command-line interface. The methods of FlagSet are
+analogous to the top-level functions for the command-line
+flag set.
*/
package flag
diff --git a/src/fmt/doc.go b/src/fmt/doc.go
index a7bd02b627..f14a7a73e3 100644
--- a/src/fmt/doc.go
+++ b/src/fmt/doc.go
@@ -3,342 +3,342 @@
// license that can be found in the LICENSE file.
/*
- Package fmt implements formatted I/O with functions analogous
- to C's printf and scanf. The format 'verbs' are derived from C's but
- are simpler.
+Package fmt implements formatted I/O with functions analogous
+to C's printf and scanf. The format 'verbs' are derived from C's but
+are simpler.
- Printing
+Printing
- The verbs:
+The verbs:
- General:
- %v the value in a default format
- when printing structs, the plus flag (%+v) adds field names
- %#v a Go-syntax representation of the value
- %T a Go-syntax representation of the type of the value
- %% a literal percent sign; consumes no value
+General:
+ %v the value in a default format
+ when printing structs, the plus flag (%+v) adds field names
+ %#v a Go-syntax representation of the value
+ %T a Go-syntax representation of the type of the value
+ %% a literal percent sign; consumes no value
- Boolean:
- %t the word true or false
- Integer:
- %b base 2
- %c the character represented by the corresponding Unicode code point
- %d base 10
- %o base 8
- %O base 8 with 0o prefix
- %q a single-quoted character literal safely escaped with Go syntax.
- %x base 16, with lower-case letters for a-f
- %X base 16, with upper-case letters for A-F
- %U Unicode format: U+1234; same as "U+%04X"
- Floating-point and complex constituents:
- %b decimalless scientific notation with exponent a power of two,
- in the manner of strconv.FormatFloat with the 'b' format,
- e.g. -123456p-78
- %e scientific notation, e.g. -1.234456e+78
- %E scientific notation, e.g. -1.234456E+78
- %f decimal point but no exponent, e.g. 123.456
- %F synonym for %f
- %g %e for large exponents, %f otherwise. Precision is discussed below.
- %G %E for large exponents, %F otherwise
- %x hexadecimal notation (with decimal power of two exponent), e.g. -0x1.23abcp+20
- %X upper-case hexadecimal notation, e.g. -0X1.23ABCP+20
- String and slice of bytes (treated equivalently with these verbs):
- %s the uninterpreted bytes of the string or slice
- %q a double-quoted string safely escaped with Go syntax
- %x base 16, lower-case, two characters per byte
- %X base 16, upper-case, two characters per byte
- Slice:
- %p address of 0th element in base 16 notation, with leading 0x
- Pointer:
- %p base 16 notation, with leading 0x
- The %b, %d, %o, %x and %X verbs also work with pointers,
- formatting the value exactly as if it were an integer.
+Boolean:
+ %t the word true or false
+Integer:
+ %b base 2
+ %c the character represented by the corresponding Unicode code point
+ %d base 10
+ %o base 8
+ %O base 8 with 0o prefix
+ %q a single-quoted character literal safely escaped with Go syntax.
+ %x base 16, with lower-case letters for a-f
+ %X base 16, with upper-case letters for A-F
+ %U Unicode format: U+1234; same as "U+%04X"
+Floating-point and complex constituents:
+ %b decimalless scientific notation with exponent a power of two,
+ in the manner of strconv.FormatFloat with the 'b' format,
+ e.g. -123456p-78
+ %e scientific notation, e.g. -1.234456e+78
+ %E scientific notation, e.g. -1.234456E+78
+ %f decimal point but no exponent, e.g. 123.456
+ %F synonym for %f
+ %g %e for large exponents, %f otherwise. Precision is discussed below.
+ %G %E for large exponents, %F otherwise
+ %x hexadecimal notation (with decimal power of two exponent), e.g. -0x1.23abcp+20
+ %X upper-case hexadecimal notation, e.g. -0X1.23ABCP+20
+String and slice of bytes (treated equivalently with these verbs):
+ %s the uninterpreted bytes of the string or slice
+ %q a double-quoted string safely escaped with Go syntax
+ %x base 16, lower-case, two characters per byte
+ %X base 16, upper-case, two characters per byte
+Slice:
+ %p address of 0th element in base 16 notation, with leading 0x
+Pointer:
+ %p base 16 notation, with leading 0x
+ The %b, %d, %o, %x and %X verbs also work with pointers,
+ formatting the value exactly as if it were an integer.
- The default format for %v is:
- bool: %t
- int, int8 etc.: %d
- uint, uint8 etc.: %d, %#x if printed with %#v
- float32, complex64, etc: %g
- string: %s
- chan: %p
- pointer: %p
- For compound objects, the elements are printed using these rules, recursively,
- laid out like this:
- struct: {field0 field1 ...}
- array, slice: [elem0 elem1 ...]
- maps: map[key1:value1 key2:value2 ...]
- pointer to above: &{}, &[], &map[]
+The default format for %v is:
+ bool: %t
+ int, int8 etc.: %d
+ uint, uint8 etc.: %d, %#x if printed with %#v
+ float32, complex64, etc: %g
+ string: %s
+ chan: %p
+ pointer: %p
+For compound objects, the elements are printed using these rules, recursively,
+laid out like this:
+ struct: {field0 field1 ...}
+ array, slice: [elem0 elem1 ...]
+ maps: map[key1:value1 key2:value2 ...]
+ pointer to above: &{}, &[], &map[]
- Width is specified by an optional decimal number immediately preceding the verb.
- If absent, the width is whatever is necessary to represent the value.
- Precision is specified after the (optional) width by a period followed by a
- decimal number. If no period is present, a default precision is used.
- A period with no following number specifies a precision of zero.
- Examples:
- %f default width, default precision
- %9f width 9, default precision
- %.2f default width, precision 2
- %9.2f width 9, precision 2
- %9.f width 9, precision 0
+Width is specified by an optional decimal number immediately preceding the verb.
+If absent, the width is whatever is necessary to represent the value.
+Precision is specified after the (optional) width by a period followed by a
+decimal number. If no period is present, a default precision is used.
+A period with no following number specifies a precision of zero.
+Examples:
+ %f default width, default precision
+ %9f width 9, default precision
+ %.2f default width, precision 2
+ %9.2f width 9, precision 2
+ %9.f width 9, precision 0
- Width and precision are measured in units of Unicode code points,
- that is, runes. (This differs from C's printf where the
- units are always measured in bytes.) Either or both of the flags
- may be replaced with the character '*', causing their values to be
- obtained from the next operand (preceding the one to format),
- which must be of type int.
+Width and precision are measured in units of Unicode code points,
+that is, runes. (This differs from C's printf where the
+units are always measured in bytes.) Either or both of the flags
+may be replaced with the character '*', causing their values to be
+obtained from the next operand (preceding the one to format),
+which must be of type int.
- For most values, width is the minimum number of runes to output,
- padding the formatted form with spaces if necessary.
+For most values, width is the minimum number of runes to output,
+padding the formatted form with spaces if necessary.
- For strings, byte slices and byte arrays, however, precision
- limits the length of the input to be formatted (not the size of
- the output), truncating if necessary. Normally it is measured in
- runes, but for these types when formatted with the %x or %X format
- it is measured in bytes.
+For strings, byte slices and byte arrays, however, precision
+limits the length of the input to be formatted (not the size of
+the output), truncating if necessary. Normally it is measured in
+runes, but for these types when formatted with the %x or %X format
+it is measured in bytes.
- For floating-point values, width sets the minimum width of the field and
- precision sets the number of places after the decimal, if appropriate,
- except that for %g/%G precision sets the maximum number of significant
- digits (trailing zeros are removed). For example, given 12.345 the format
- %6.3f prints 12.345 while %.3g prints 12.3. The default precision for %e, %f
- and %#g is 6; for %g it is the smallest number of digits necessary to identify
- the value uniquely.
+For floating-point values, width sets the minimum width of the field and
+precision sets the number of places after the decimal, if appropriate,
+except that for %g/%G precision sets the maximum number of significant
+digits (trailing zeros are removed). For example, given 12.345 the format
+%6.3f prints 12.345 while %.3g prints 12.3. The default precision for %e, %f
+and %#g is 6; for %g it is the smallest number of digits necessary to identify
+the value uniquely.
- For complex numbers, the width and precision apply to the two
- components independently and the result is parenthesized, so %f applied
- to 1.2+3.4i produces (1.200000+3.400000i).
+For complex numbers, the width and precision apply to the two
+components independently and the result is parenthesized, so %f applied
+to 1.2+3.4i produces (1.200000+3.400000i).
- Other flags:
- + always print a sign for numeric values;
- guarantee ASCII-only output for %q (%+q)
- - pad with spaces on the right rather than the left (left-justify the field)
- # alternate format: add leading 0b for binary (%#b), 0 for octal (%#o),
- 0x or 0X for hex (%#x or %#X); suppress 0x for %p (%#p);
- for %q, print a raw (backquoted) string if strconv.CanBackquote
- returns true;
- always print a decimal point for %e, %E, %f, %F, %g and %G;
- do not remove trailing zeros for %g and %G;
- write e.g. U+0078 'x' if the character is printable for %U (%#U).
- ' ' (space) leave a space for elided sign in numbers (% d);
- put spaces between bytes printing strings or slices in hex (% x, % X)
- 0 pad with leading zeros rather than spaces;
- for numbers, this moves the padding after the sign;
- ignored for strings, byte slices and byte arrays
+Other flags:
+ + always print a sign for numeric values;
+ guarantee ASCII-only output for %q (%+q)
+ - pad with spaces on the right rather than the left (left-justify the field)
+ # alternate format: add leading 0b for binary (%#b), 0 for octal (%#o),
+ 0x or 0X for hex (%#x or %#X); suppress 0x for %p (%#p);
+ for %q, print a raw (backquoted) string if strconv.CanBackquote
+ returns true;
+ always print a decimal point for %e, %E, %f, %F, %g and %G;
+ do not remove trailing zeros for %g and %G;
+ write e.g. U+0078 'x' if the character is printable for %U (%#U).
+ ' ' (space) leave a space for elided sign in numbers (% d);
+ put spaces between bytes printing strings or slices in hex (% x, % X)
+ 0 pad with leading zeros rather than spaces;
+ for numbers, this moves the padding after the sign;
+ ignored for strings, byte slices and byte arrays
- Flags are ignored by verbs that do not expect them.
- For example there is no alternate decimal format, so %#d and %d
- behave identically.
+Flags are ignored by verbs that do not expect them.
+For example there is no alternate decimal format, so %#d and %d
+behave identically.
- For each Printf-like function, there is also a Print function
- that takes no format and is equivalent to saying %v for every
- operand. Another variant Println inserts blanks between
- operands and appends a newline.
+For each Printf-like function, there is also a Print function
+that takes no format and is equivalent to saying %v for every
+operand. Another variant Println inserts blanks between
+operands and appends a newline.
- Regardless of the verb, if an operand is an interface value,
- the internal concrete value is used, not the interface itself.
- Thus:
- var i interface{} = 23
- fmt.Printf("%v\n", i)
- will print 23.
+Regardless of the verb, if an operand is an interface value,
+the internal concrete value is used, not the interface itself.
+Thus:
+ var i interface{} = 23
+ fmt.Printf("%v\n", i)
+will print 23.
- Except when printed using the verbs %T and %p, special
- formatting considerations apply for operands that implement
- certain interfaces. In order of application:
+Except when printed using the verbs %T and %p, special
+formatting considerations apply for operands that implement
+certain interfaces. In order of application:
- 1. If the operand is a reflect.Value, the operand is replaced by the
- concrete value that it holds, and printing continues with the next rule.
+1. If the operand is a reflect.Value, the operand is replaced by the
+concrete value that it holds, and printing continues with the next rule.
- 2. If an operand implements the Formatter interface, it will
- be invoked. In this case the interpretation of verbs and flags is
- controlled by that implementation.
+2. If an operand implements the Formatter interface, it will
+be invoked. In this case the interpretation of verbs and flags is
+controlled by that implementation.
- 3. If the %v verb is used with the # flag (%#v) and the operand
- implements the GoStringer interface, that will be invoked.
+3. If the %v verb is used with the # flag (%#v) and the operand
+implements the GoStringer interface, that will be invoked.
- If the format (which is implicitly %v for Println etc.) is valid
- for a string (%s %q %v %x %X), the following two rules apply:
+If the format (which is implicitly %v for Println etc.) is valid
+for a string (%s %q %v %x %X), the following two rules apply:
- 4. If an operand implements the error interface, the Error method
- will be invoked to convert the object to a string, which will then
- be formatted as required by the verb (if any).
+4. If an operand implements the error interface, the Error method
+will be invoked to convert the object to a string, which will then
+be formatted as required by the verb (if any).
- 5. If an operand implements method String() string, that method
- will be invoked to convert the object to a string, which will then
- be formatted as required by the verb (if any).
+5. If an operand implements method String() string, that method
+will be invoked to convert the object to a string, which will then
+be formatted as required by the verb (if any).
- For compound operands such as slices and structs, the format
- applies to the elements of each operand, recursively, not to the
- operand as a whole. Thus %q will quote each element of a slice
- of strings, and %6.2f will control formatting for each element
- of a floating-point array.
+For compound operands such as slices and structs, the format
+applies to the elements of each operand, recursively, not to the
+operand as a whole. Thus %q will quote each element of a slice
+of strings, and %6.2f will control formatting for each element
+of a floating-point array.
- However, when printing a byte slice with a string-like verb
- (%s %q %x %X), it is treated identically to a string, as a single item.
+However, when printing a byte slice with a string-like verb
+(%s %q %x %X), it is treated identically to a string, as a single item.
- To avoid recursion in cases such as
- type X string
- func (x X) String() string { return Sprintf("<%s>", x) }
- convert the value before recurring:
- func (x X) String() string { return Sprintf("<%s>", string(x)) }
- Infinite recursion can also be triggered by self-referential data
- structures, such as a slice that contains itself as an element, if
- that type has a String method. Such pathologies are rare, however,
- and the package does not protect against them.
+To avoid recursion in cases such as
+ type X string
+ func (x X) String() string { return Sprintf("<%s>", x) }
+convert the value before recurring:
+ func (x X) String() string { return Sprintf("<%s>", string(x)) }
+Infinite recursion can also be triggered by self-referential data
+structures, such as a slice that contains itself as an element, if
+that type has a String method. Such pathologies are rare, however,
+and the package does not protect against them.
- When printing a struct, fmt cannot and therefore does not invoke
- formatting methods such as Error or String on unexported fields.
+When printing a struct, fmt cannot and therefore does not invoke
+formatting methods such as Error or String on unexported fields.
- Explicit argument indexes
+Explicit argument indexes
- In Printf, Sprintf, and Fprintf, the default behavior is for each
- formatting verb to format successive arguments passed in the call.
- However, the notation [n] immediately before the verb indicates that the
- nth one-indexed argument is to be formatted instead. The same notation
- before a '*' for a width or precision selects the argument index holding
- the value. After processing a bracketed expression [n], subsequent verbs
- will use arguments n+1, n+2, etc. unless otherwise directed.
+In Printf, Sprintf, and Fprintf, the default behavior is for each
+formatting verb to format successive arguments passed in the call.
+However, the notation [n] immediately before the verb indicates that the
+nth one-indexed argument is to be formatted instead. The same notation
+before a '*' for a width or precision selects the argument index holding
+the value. After processing a bracketed expression [n], subsequent verbs
+will use arguments n+1, n+2, etc. unless otherwise directed.
- For example,
- fmt.Sprintf("%[2]d %[1]d\n", 11, 22)
- will yield "22 11", while
- fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6)
- equivalent to
- fmt.Sprintf("%6.2f", 12.0)
- will yield " 12.00". Because an explicit index affects subsequent verbs,
- this notation can be used to print the same values multiple times
- by resetting the index for the first argument to be repeated:
- fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)
- will yield "16 17 0x10 0x11".
+For example,
+ fmt.Sprintf("%[2]d %[1]d\n", 11, 22)
+will yield "22 11", while
+ fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6)
+equivalent to
+ fmt.Sprintf("%6.2f", 12.0)
+will yield " 12.00". Because an explicit index affects subsequent verbs,
+this notation can be used to print the same values multiple times
+by resetting the index for the first argument to be repeated:
+ fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)
+will yield "16 17 0x10 0x11".
- Format errors
+Format errors
- If an invalid argument is given for a verb, such as providing
- a string to %d, the generated string will contain a
- description of the problem, as in these examples:
+If an invalid argument is given for a verb, such as providing
+a string to %d, the generated string will contain a
+description of the problem, as in these examples:
- Wrong type or unknown verb: %!verb(type=value)
- Printf("%d", "hi"): %!d(string=hi)
- Too many arguments: %!(EXTRA type=value)
- Printf("hi", "guys"): hi%!(EXTRA string=guys)
- Too few arguments: %!verb(MISSING)
- Printf("hi%d"): hi%!d(MISSING)
- Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
- Printf("%*s", 4.5, "hi"): %!(BADWIDTH)hi
- Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi
- Invalid or invalid use of argument index: %!(BADINDEX)
- Printf("%*[2]d", 7): %!d(BADINDEX)
- Printf("%.[2]d", 7): %!d(BADINDEX)
+ Wrong type or unknown verb: %!verb(type=value)
+ Printf("%d", "hi"): %!d(string=hi)
+ Too many arguments: %!(EXTRA type=value)
+ Printf("hi", "guys"): hi%!(EXTRA string=guys)
+ Too few arguments: %!verb(MISSING)
+ Printf("hi%d"): hi%!d(MISSING)
+ Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
+ Printf("%*s", 4.5, "hi"): %!(BADWIDTH)hi
+ Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi
+ Invalid or invalid use of argument index: %!(BADINDEX)
+ Printf("%*[2]d", 7): %!d(BADINDEX)
+ Printf("%.[2]d", 7): %!d(BADINDEX)
- All errors begin with the string "%!" followed sometimes
- by a single character (the verb) and end with a parenthesized
- description.
+All errors begin with the string "%!" followed sometimes
+by a single character (the verb) and end with a parenthesized
+description.
- If an Error or String method triggers a panic when called by a
- print routine, the fmt package reformats the error message
- from the panic, decorating it with an indication that it came
- through the fmt package. For example, if a String method
- calls panic("bad"), the resulting formatted message will look
- like
- %!s(PANIC=bad)
+If an Error or String method triggers a panic when called by a
+print routine, the fmt package reformats the error message
+from the panic, decorating it with an indication that it came
+through the fmt package. For example, if a String method
+calls panic("bad"), the resulting formatted message will look
+like
+ %!s(PANIC=bad)
- The %!s just shows the print verb in use when the failure
- occurred. If the panic is caused by a nil receiver to an Error
- or String method, however, the output is the undecorated
- string, "".
+The %!s just shows the print verb in use when the failure
+occurred. If the panic is caused by a nil receiver to an Error
+or String method, however, the output is the undecorated
+string, "".
- Scanning
+Scanning
- An analogous set of functions scans formatted text to yield
- values. Scan, Scanf and Scanln read from os.Stdin; Fscan,
- Fscanf and Fscanln read from a specified io.Reader; Sscan,
- Sscanf and Sscanln read from an argument string.
+An analogous set of functions scans formatted text to yield
+values. Scan, Scanf and Scanln read from os.Stdin; Fscan,
+Fscanf and Fscanln read from a specified io.Reader; Sscan,
+Sscanf and Sscanln read from an argument string.
- Scan, Fscan, Sscan treat newlines in the input as spaces.
+Scan, Fscan, Sscan treat newlines in the input as spaces.
- Scanln, Fscanln and Sscanln stop scanning at a newline and
- require that the items be followed by a newline or EOF.
+Scanln, Fscanln and Sscanln stop scanning at a newline and
+require that the items be followed by a newline or EOF.
- Scanf, Fscanf, and Sscanf parse the arguments according to a
- format string, analogous to that of Printf. In the text that
- follows, 'space' means any Unicode whitespace character
- except newline.
+Scanf, Fscanf, and Sscanf parse the arguments according to a
+format string, analogous to that of Printf. In the text that
+follows, 'space' means any Unicode whitespace character
+except newline.
- In the format string, a verb introduced by the % character
- consumes and parses input; these verbs are described in more
- detail below. A character other than %, space, or newline in
- the format consumes exactly that input character, which must
- be present. A newline with zero or more spaces before it in
- the format string consumes zero or more spaces in the input
- followed by a single newline or the end of the input. A space
- following a newline in the format string consumes zero or more
- spaces in the input. Otherwise, any run of one or more spaces
- in the format string consumes as many spaces as possible in
- the input. Unless the run of spaces in the format string
- appears adjacent to a newline, the run must consume at least
- one space from the input or find the end of the input.
+In the format string, a verb introduced by the % character
+consumes and parses input; these verbs are described in more
+detail below. A character other than %, space, or newline in
+the format consumes exactly that input character, which must
+be present. A newline with zero or more spaces before it in
+the format string consumes zero or more spaces in the input
+followed by a single newline or the end of the input. A space
+following a newline in the format string consumes zero or more
+spaces in the input. Otherwise, any run of one or more spaces
+in the format string consumes as many spaces as possible in
+the input. Unless the run of spaces in the format string
+appears adjacent to a newline, the run must consume at least
+one space from the input or find the end of the input.
- The handling of spaces and newlines differs from that of C's
- scanf family: in C, newlines are treated as any other space,
- and it is never an error when a run of spaces in the format
- string finds no spaces to consume in the input.
+The handling of spaces and newlines differs from that of C's
+scanf family: in C, newlines are treated as any other space,
+and it is never an error when a run of spaces in the format
+string finds no spaces to consume in the input.
- The verbs behave analogously to those of Printf.
- For example, %x will scan an integer as a hexadecimal number,
- and %v will scan the default representation format for the value.
- The Printf verbs %p and %T and the flags # and + are not implemented.
- For floating-point and complex values, all valid formatting verbs
- (%b %e %E %f %F %g %G %x %X and %v) are equivalent and accept
- both decimal and hexadecimal notation (for example: "2.3e+7", "0x4.5p-8")
- and digit-separating underscores (for example: "3.14159_26535_89793").
+The verbs behave analogously to those of Printf.
+For example, %x will scan an integer as a hexadecimal number,
+and %v will scan the default representation format for the value.
+The Printf verbs %p and %T and the flags # and + are not implemented.
+For floating-point and complex values, all valid formatting verbs
+(%b %e %E %f %F %g %G %x %X and %v) are equivalent and accept
+both decimal and hexadecimal notation (for example: "2.3e+7", "0x4.5p-8")
+and digit-separating underscores (for example: "3.14159_26535_89793").
- Input processed by verbs is implicitly space-delimited: the
- implementation of every verb except %c starts by discarding
- leading spaces from the remaining input, and the %s verb
- (and %v reading into a string) stops consuming input at the first
- space or newline character.
+Input processed by verbs is implicitly space-delimited: the
+implementation of every verb except %c starts by discarding
+leading spaces from the remaining input, and the %s verb
+(and %v reading into a string) stops consuming input at the first
+space or newline character.
- The familiar base-setting prefixes 0b (binary), 0o and 0 (octal),
- and 0x (hexadecimal) are accepted when scanning integers
- without a format or with the %v verb, as are digit-separating
- underscores.
+The familiar base-setting prefixes 0b (binary), 0o and 0 (octal),
+and 0x (hexadecimal) are accepted when scanning integers
+without a format or with the %v verb, as are digit-separating
+underscores.
- Width is interpreted in the input text but there is no
- syntax for scanning with a precision (no %5.2f, just %5f).
- If width is provided, it applies after leading spaces are
- trimmed and specifies the maximum number of runes to read
- to satisfy the verb. For example,
- Sscanf(" 1234567 ", "%5s%d", &s, &i)
- will set s to "12345" and i to 67 while
- Sscanf(" 12 34 567 ", "%5s%d", &s, &i)
- will set s to "12" and i to 34.
+Width is interpreted in the input text but there is no
+syntax for scanning with a precision (no %5.2f, just %5f).
+If width is provided, it applies after leading spaces are
+trimmed and specifies the maximum number of runes to read
+to satisfy the verb. For example,
+ Sscanf(" 1234567 ", "%5s%d", &s, &i)
+will set s to "12345" and i to 67 while
+ Sscanf(" 12 34 567 ", "%5s%d", &s, &i)
+will set s to "12" and i to 34.
- In all the scanning functions, a carriage return followed
- immediately by a newline is treated as a plain newline
- (\r\n means the same as \n).
+In all the scanning functions, a carriage return followed
+immediately by a newline is treated as a plain newline
+(\r\n means the same as \n).
- In all the scanning functions, if an operand implements method
- Scan (that is, it implements the Scanner interface) that
- method will be used to scan the text for that operand. Also,
- if the number of arguments scanned is less than the number of
- arguments provided, an error is returned.
+In all the scanning functions, if an operand implements method
+Scan (that is, it implements the Scanner interface) that
+method will be used to scan the text for that operand. Also,
+if the number of arguments scanned is less than the number of
+arguments provided, an error is returned.
- All arguments to be scanned must be either pointers to basic
- types or implementations of the Scanner interface.
+All arguments to be scanned must be either pointers to basic
+types or implementations of the Scanner interface.
- Like Scanf and Fscanf, Sscanf need not consume its entire input.
- There is no way to recover how much of the input string Sscanf used.
+Like Scanf and Fscanf, Sscanf need not consume its entire input.
+There is no way to recover how much of the input string Sscanf used.
- Note: Fscan etc. can read one character (rune) past the input
- they return, which means that a loop calling a scan routine
- may skip some of the input. This is usually a problem only
- when there is no space between input values. If the reader
- provided to Fscan implements ReadRune, that method will be used
- to read characters. If the reader also implements UnreadRune,
- that method will be used to save the character and successive
- calls will not lose data. To attach ReadRune and UnreadRune
- methods to a reader without that capability, use
- bufio.NewReader.
+Note: Fscan etc. can read one character (rune) past the input
+they return, which means that a loop calling a scan routine
+may skip some of the input. This is usually a problem only
+when there is no space between input values. If the reader
+provided to Fscan implements ReadRune, that method will be used
+to read characters. If the reader also implements UnreadRune,
+that method will be used to save the character and successive
+calls will not lose data. To attach ReadRune and UnreadRune
+methods to a reader without that capability, use
+bufio.NewReader.
*/
package fmt
diff --git a/src/go/doc/headscan.go b/src/go/doc/headscan.go
index 320895e43a..f55ca754a6 100644
--- a/src/go/doc/headscan.go
+++ b/src/go/doc/headscan.go
@@ -5,13 +5,13 @@
//go:build ignore
/*
- The headscan command extracts comment headings from package files;
- it is used to detect false positives which may require an adjustment
- to the comment formatting heuristics in comment.go.
+The headscan command extracts comment headings from package files;
+it is used to detect false positives which may require an adjustment
+to the comment formatting heuristics in comment.go.
- Usage: headscan [-root root_directory]
+Usage: headscan [-root root_directory]
- By default, the $GOROOT/src directory is scanned.
+By default, the $GOROOT/src directory is scanned.
*/
package main
diff --git a/src/net/rpc/server.go b/src/net/rpc/server.go
index d5207a42cf..f53ea75f9c 100644
--- a/src/net/rpc/server.go
+++ b/src/net/rpc/server.go
@@ -3,126 +3,126 @@
// license that can be found in the LICENSE file.
/*
- Package rpc provides access to the exported methods of an object across a
- network or other I/O connection. A server registers an object, making it visible
- as a service with the name of the type of the object. After registration, exported
- methods of the object will be accessible remotely. A server may register multiple
- objects (services) of different types but it is an error to register multiple
- objects of the same type.
+Package rpc provides access to the exported methods of an object across a
+network or other I/O connection. A server registers an object, making it visible
+as a service with the name of the type of the object. After registration, exported
+methods of the object will be accessible remotely. A server may register multiple
+objects (services) of different types but it is an error to register multiple
+objects of the same type.
- Only methods that satisfy these criteria will be made available for remote access;
- other methods will be ignored:
+Only methods that satisfy these criteria will be made available for remote access;
+other methods will be ignored:
- - the method's type is exported.
- - the method is exported.
- - the method has two arguments, both exported (or builtin) types.
- - the method's second argument is a pointer.
- - the method has return type error.
+ - the method's type is exported.
+ - the method is exported.
+ - the method has two arguments, both exported (or builtin) types.
+ - the method's second argument is a pointer.
+ - the method has return type error.
- In effect, the method must look schematically like
+In effect, the method must look schematically like
- func (t *T) MethodName(argType T1, replyType *T2) error
+ func (t *T) MethodName(argType T1, replyType *T2) error
- where T1 and T2 can be marshaled by encoding/gob.
- These requirements apply even if a different codec is used.
- (In the future, these requirements may soften for custom codecs.)
+where T1 and T2 can be marshaled by encoding/gob.
+These requirements apply even if a different codec is used.
+(In the future, these requirements may soften for custom codecs.)
- The method's first argument represents the arguments provided by the caller; the
- second argument represents the result parameters to be returned to the caller.
- The method's return value, if non-nil, is passed back as a string that the client
- sees as if created by errors.New. If an error is returned, the reply parameter
- will not be sent back to the client.
+The method's first argument represents the arguments provided by the caller; the
+second argument represents the result parameters to be returned to the caller.
+The method's return value, if non-nil, is passed back as a string that the client
+sees as if created by errors.New. If an error is returned, the reply parameter
+will not be sent back to the client.
- The server may handle requests on a single connection by calling ServeConn. More
- typically it will create a network listener and call Accept or, for an HTTP
- listener, HandleHTTP and http.Serve.
+The server may handle requests on a single connection by calling ServeConn. More
+typically it will create a network listener and call Accept or, for an HTTP
+listener, HandleHTTP and http.Serve.
- A client wishing to use the service establishes a connection and then invokes
- NewClient on the connection. The convenience function Dial (DialHTTP) performs
- both steps for a raw network connection (an HTTP connection). The resulting
- Client object has two methods, Call and Go, that specify the service and method to
- call, a pointer containing the arguments, and a pointer to receive the result
- parameters.
+A client wishing to use the service establishes a connection and then invokes
+NewClient on the connection. The convenience function Dial (DialHTTP) performs
+both steps for a raw network connection (an HTTP connection). The resulting
+Client object has two methods, Call and Go, that specify the service and method to
+call, a pointer containing the arguments, and a pointer to receive the result
+parameters.
- The Call method waits for the remote call to complete while the Go method
- launches the call asynchronously and signals completion using the Call
- structure's Done channel.
+The Call method waits for the remote call to complete while the Go method
+launches the call asynchronously and signals completion using the Call
+structure's Done channel.
- Unless an explicit codec is set up, package encoding/gob is used to
- transport the data.
+Unless an explicit codec is set up, package encoding/gob is used to
+transport the data.
- Here is a simple example. A server wishes to export an object of type Arith:
+Here is a simple example. A server wishes to export an object of type Arith:
- package server
+ package server
- import "errors"
+ import "errors"
- type Args struct {
- A, B int
+ type Args struct {
+ A, B int
+ }
+
+ type Quotient struct {
+ Quo, Rem int
+ }
+
+ type Arith int
+
+ func (t *Arith) Multiply(args *Args, reply *int) error {
+ *reply = args.A * args.B
+ return nil
+ }
+
+ func (t *Arith) Divide(args *Args, quo *Quotient) error {
+ if args.B == 0 {
+ return errors.New("divide by zero")
}
+ quo.Quo = args.A / args.B
+ quo.Rem = args.A % args.B
+ return nil
+ }
- type Quotient struct {
- Quo, Rem int
- }
+The server calls (for HTTP service):
- type Arith int
+ arith := new(Arith)
+ rpc.Register(arith)
+ rpc.HandleHTTP()
+ l, e := net.Listen("tcp", ":1234")
+ if e != nil {
+ log.Fatal("listen error:", e)
+ }
+ go http.Serve(l, nil)
- func (t *Arith) Multiply(args *Args, reply *int) error {
- *reply = args.A * args.B
- return nil
- }
+At this point, clients can see a service "Arith" with methods "Arith.Multiply" and
+"Arith.Divide". To invoke one, a client first dials the server:
- func (t *Arith) Divide(args *Args, quo *Quotient) error {
- if args.B == 0 {
- return errors.New("divide by zero")
- }
- quo.Quo = args.A / args.B
- quo.Rem = args.A % args.B
- return nil
- }
+ client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
+ if err != nil {
+ log.Fatal("dialing:", err)
+ }
- The server calls (for HTTP service):
+Then it can make a remote call:
- arith := new(Arith)
- rpc.Register(arith)
- rpc.HandleHTTP()
- l, e := net.Listen("tcp", ":1234")
- if e != nil {
- log.Fatal("listen error:", e)
- }
- go http.Serve(l, nil)
+ // Synchronous call
+ args := &server.Args{7,8}
+ var reply int
+ err = client.Call("Arith.Multiply", args, &reply)
+ if err != nil {
+ log.Fatal("arith error:", err)
+ }
+ fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
- At this point, clients can see a service "Arith" with methods "Arith.Multiply" and
- "Arith.Divide". To invoke one, a client first dials the server:
+or
- client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
- if err != nil {
- log.Fatal("dialing:", err)
- }
+ // Asynchronous call
+ quotient := new(Quotient)
+ divCall := client.Go("Arith.Divide", args, quotient, nil)
+ replyCall := <-divCall.Done // will be equal to divCall
+ // check errors, print, etc.
- Then it can make a remote call:
+A server implementation will often provide a simple, type-safe wrapper for the
+client.
- // Synchronous call
- args := &server.Args{7,8}
- var reply int
- err = client.Call("Arith.Multiply", args, &reply)
- if err != nil {
- log.Fatal("arith error:", err)
- }
- fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
-
- or
-
- // Asynchronous call
- quotient := new(Quotient)
- divCall := client.Go("Arith.Divide", args, quotient, nil)
- replyCall := <-divCall.Done // will be equal to divCall
- // check errors, print, etc.
-
- A server implementation will often provide a simple, type-safe wrapper for the
- client.
-
- The net/rpc package is frozen and is not accepting new features.
+The net/rpc package is frozen and is not accepting new features.
*/
package rpc
diff --git a/src/runtime/debug/stack_test.go b/src/runtime/debug/stack_test.go
index 9376e82b84..4cab8864df 100644
--- a/src/runtime/debug/stack_test.go
+++ b/src/runtime/debug/stack_test.go
@@ -20,22 +20,22 @@ func (t T) method() []byte {
}
/*
- The traceback should look something like this, modulo line numbers and hex constants.
- Don't worry much about the base levels, but check the ones in our own package.
+The traceback should look something like this, modulo line numbers and hex constants.
+Don't worry much about the base levels, but check the ones in our own package.
- goroutine 10 [running]:
- runtime/debug.Stack(0x0, 0x0, 0x0)
- /Users/r/go/src/runtime/debug/stack.go:28 +0x80
- runtime/debug.(*T).ptrmethod(0xc82005ee70, 0x0, 0x0, 0x0)
- /Users/r/go/src/runtime/debug/stack_test.go:15 +0x29
- runtime/debug.T.method(0x0, 0x0, 0x0, 0x0)
- /Users/r/go/src/runtime/debug/stack_test.go:18 +0x32
- runtime/debug.TestStack(0xc8201ce000)
- /Users/r/go/src/runtime/debug/stack_test.go:37 +0x38
- testing.tRunner(0xc8201ce000, 0x664b58)
- /Users/r/go/src/testing/testing.go:456 +0x98
- created by testing.RunTests
- /Users/r/go/src/testing/testing.go:561 +0x86d
+ goroutine 10 [running]:
+ runtime/debug.Stack(0x0, 0x0, 0x0)
+ /Users/r/go/src/runtime/debug/stack.go:28 +0x80
+ runtime/debug.(*T).ptrmethod(0xc82005ee70, 0x0, 0x0, 0x0)
+ /Users/r/go/src/runtime/debug/stack_test.go:15 +0x29
+ runtime/debug.T.method(0x0, 0x0, 0x0, 0x0)
+ /Users/r/go/src/runtime/debug/stack_test.go:18 +0x32
+ runtime/debug.TestStack(0xc8201ce000)
+ /Users/r/go/src/runtime/debug/stack_test.go:37 +0x38
+ testing.tRunner(0xc8201ce000, 0x664b58)
+ /Users/r/go/src/testing/testing.go:456 +0x98
+ created by testing.RunTests
+ /Users/r/go/src/testing/testing.go:561 +0x86d
*/
func TestStack(t *testing.T) {
b := T(0).method()
diff --git a/src/unsafe/unsafe.go b/src/unsafe/unsafe.go
index 16e3890d0b..a6a255658b 100644
--- a/src/unsafe/unsafe.go
+++ b/src/unsafe/unsafe.go
@@ -3,10 +3,10 @@
// license that can be found in the LICENSE file.
/*
- Package unsafe contains operations that step around the type safety of Go programs.
+Package unsafe contains operations that step around the type safety of Go programs.
- Packages that import unsafe may be non-portable and are not protected by the
- Go 1 compatibility guidelines.
+Packages that import unsafe may be non-portable and are not protected by the
+Go 1 compatibility guidelines.
*/
package unsafe
From 4e26ab0ed891530cd07174813b89cea04b0fa559 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Mon, 14 Mar 2022 10:29:51 -0700
Subject: [PATCH 103/276] cmd/go: document that 'go run' strips debug info
Change-Id: Ie7293a33862853ac56ee0a9017b201d8ff0ba1f0
Reviewed-on: https://go-review.googlesource.com/c/go/+/392574
Trust: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gopher Robot
Reviewed-by: Bryan Mills
---
src/cmd/go/alldocs.go | 4 ++++
src/cmd/go/internal/run/run.go | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 825de1e64a..8410731a28 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -1599,6 +1599,10 @@
// cross-compiled programs when a simulator or other execution method is
// available.
//
+// By default, 'go run' compiles the binary without generating the information
+// used by debuggers, to reduce build time. To include debugger information in
+// the binary, use 'go build'.
+//
// The exit status of Run is not the exit status of the compiled binary.
//
// For more about build flags, see 'go help build'.
diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go
index 312b49ef5d..35c5783373 100644
--- a/src/cmd/go/internal/run/run.go
+++ b/src/cmd/go/internal/run/run.go
@@ -52,6 +52,10 @@ for example 'go_js_wasm_exec a.out arguments...'. This allows execution of
cross-compiled programs when a simulator or other execution method is
available.
+By default, 'go run' compiles the binary without generating the information
+used by debuggers, to reduce build time. To include debugger information in
+the binary, use 'go build'.
+
The exit status of Run is not the exit status of the compiled binary.
For more about build flags, see 'go help build'.
From 201a2e9c2f82dd2c57c8e79bbe2c028d7c13b8ea Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Wed, 2 Mar 2022 15:49:27 -0800
Subject: [PATCH 104/276] compress/gzip: add example of compressing reader
For #51092
Change-Id: If0a233651ac75f113569ddfffd056084f6092564
Reviewed-on: https://go-review.googlesource.com/c/go/+/389514
Trust: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
Reviewed-by: Joseph Tsai
TryBot-Result: Gopher Robot
---
src/compress/gzip/example_test.go | 87 +++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
diff --git a/src/compress/gzip/example_test.go b/src/compress/gzip/example_test.go
index ce29e9ba36..27aae152d4 100644
--- a/src/compress/gzip/example_test.go
+++ b/src/compress/gzip/example_test.go
@@ -10,7 +10,10 @@ import (
"fmt"
"io"
"log"
+ "net/http"
+ "net/http/httptest"
"os"
+ "strings"
"time"
)
@@ -126,3 +129,87 @@ func ExampleReader_Multistream() {
//
// Hello Gophers - 2
}
+
+func Example_compressingReader() {
+ // This is an example of writing a compressing reader.
+ // This can be useful for an HTTP client body, as shown.
+
+ const testdata = "the data to be compressed"
+
+ // This HTTP handler is just for testing purposes.
+ handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
+ zr, err := gzip.NewReader(req.Body)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Just output the data for the example.
+ if _, err := io.Copy(os.Stdout, zr); err != nil {
+ log.Fatal(err)
+ }
+ })
+ ts := httptest.NewServer(handler)
+ defer ts.Close()
+
+ // The remainder is the example code.
+
+ // The data we want to compress, as an io.Reader
+ dataReader := strings.NewReader(testdata)
+
+ // bodyReader is the body of the HTTP request, as an io.Reader.
+ // httpWriter is the body of the HTTP request, as an io.Writer.
+ bodyReader, httpWriter := io.Pipe()
+
+ // gzipWriter compresses data to httpWriter.
+ gzipWriter := gzip.NewWriter(httpWriter)
+
+ // errch collects any errors from the writing goroutine.
+ errch := make(chan error, 1)
+
+ go func() {
+ defer close(errch)
+ sentErr := false
+ sendErr := func(err error) {
+ if !sentErr {
+ errch <- err
+ sentErr = true
+ }
+ }
+
+ // Copy our data to gzipWriter, which compresses it to
+ // gzipWriter, which feeds it to bodyReader.
+ if _, err := io.Copy(gzipWriter, dataReader); err != nil && err != io.ErrClosedPipe {
+ sendErr(err)
+ }
+ if err := gzipWriter.Close(); err != nil && err != io.ErrClosedPipe {
+ sendErr(err)
+ }
+ if err := httpWriter.Close(); err != nil && err != io.ErrClosedPipe {
+ sendErr(err)
+ }
+ }()
+
+ // Send an HTTP request to the test server.
+ req, err := http.NewRequest("PUT", ts.URL, bodyReader)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Note that passing req to http.Client.Do promises that it
+ // will close the body, in this case bodyReader.
+ // That ensures that the goroutine will exit.
+ resp, err := ts.Client().Do(req)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Check whether there was an error compressing the data.
+ if err := <-errch; err != nil {
+ log.Fatal(err)
+ }
+
+ // For this example we don't care about the response.
+ resp.Body.Close()
+
+ // Output: the data to be compressed
+}
From b4428325e266d8ffdd1131d71862f0767c616e27 Mon Sep 17 00:00:00 2001
From: Bryan Mills
Date: Tue, 15 Mar 2022 17:49:01 +0000
Subject: [PATCH 105/276] Revert "os: raise open file rlimit at startup"
This reverts CL 392415.
Reason for revert: new test is failing on at least darwin-amd64-10_14, darwin-amd64-10_15, and openbsd-arm64-jsing.
Updates #46279.
Change-Id: I2890b72f8ee74f31000d65f7d47b5bb0ed5d6007
Reviewed-on: https://go-review.googlesource.com/c/go/+/393016
Trust: Bryan Mills
Run-TryBot: Bryan Mills
Reviewed-by: Russ Cox
---
src/os/rlimit.go | 31 -------------------------------
src/os/rlimit_test.go | 32 --------------------------------
2 files changed, 63 deletions(-)
delete mode 100644 src/os/rlimit.go
delete mode 100644 src/os/rlimit_test.go
diff --git a/src/os/rlimit.go b/src/os/rlimit.go
deleted file mode 100644
index 3e29db9562..0000000000
--- a/src/os/rlimit.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
-
-package os
-
-import "syscall"
-
-// Some systems set an artificially low soft limit on open file count, for compatibility
-// with code that uses select and its hard-coded maximum file descriptor
-// (limited by the size of fd_set).
-//
-// Go does not use select, so it should not be subject to these limits.
-// On some systems the limit is 256, which is very easy to run into,
-// even in simple programs like gofmt when they parallelize walking
-// a file tree.
-//
-// After a long discussion on go.dev/issue/46279, we decided the
-// best approach was for Go to raise the limit unconditionally for itself,
-// and then leave old software to set the limit back as needed.
-// Code that really wants Go to leave the limit alone can set the hard limit,
-// which Go of course has no choice but to respect.
-func init() {
- var lim syscall.Rlimit
- if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err == nil && lim.Cur != lim.Max {
- lim.Cur = lim.Max
- syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim)
- }
-}
diff --git a/src/os/rlimit_test.go b/src/os/rlimit_test.go
deleted file mode 100644
index 9bb6858a86..0000000000
--- a/src/os/rlimit_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package os_test
-
-import (
- . "os"
- "testing"
-)
-
-func TestOpenFileLimit(t *testing.T) {
- // For open file count,
- // macOS sets the default soft limit to 256 and no hard limit.
- // CentOS and Fedora set the default soft limit to 1024,
- // with hard limits of 4096 and 524288, respectively.
- // Check that we can open 1200 files, which proves
- // that the rlimit is being raised appropriately on those systems.
- var files []*File
- for i := 0; i < 1200; i++ {
- f, err := Open("rlimit.go")
- if err != nil {
- t.Error(err)
- break
- }
- files = append(files, f)
- }
-
- for _, f := range files {
- f.Close()
- }
-}
From db3045b4be5b91cd42c3387dc550c89bbc2f7fb4 Mon Sep 17 00:00:00 2001
From: Cherry Mui
Date: Thu, 24 Feb 2022 23:44:05 -0500
Subject: [PATCH 106/276] cmd/asm: support -d=pctab flag
To debug PC data generation.
Change-Id: Id7ac8d607cc27ad52db490bd758c3a768c3e1df2
Reviewed-on: https://go-review.googlesource.com/c/go/+/388015
Trust: Cherry Mui
Run-TryBot: Cherry Mui
Reviewed-by: Than McIntosh
TryBot-Result: Gopher Robot
---
src/cmd/asm/internal/flags/flags.go | 1 +
src/cmd/asm/main.go | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go
index 607166e664..273d422370 100644
--- a/src/cmd/asm/internal/flags/flags.go
+++ b/src/cmd/asm/internal/flags/flags.go
@@ -30,6 +30,7 @@ var (
var DebugFlags struct {
MayMoreStack string `help:"call named function before all stack growth checks"`
+ PCTab string `help:"print named pc-value table\nOne of: pctospadj, pctofile, pctoline, pctoinline, pctopcdata"`
}
var (
diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go
index 3683527f5b..6a25fd426b 100644
--- a/src/cmd/asm/main.go
+++ b/src/cmd/asm/main.go
@@ -43,6 +43,7 @@ func main() {
ctxt.Flag_linkshared = *flags.Linkshared
ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
ctxt.Flag_maymorestack = flags.DebugFlags.MayMoreStack
+ ctxt.Debugpcln = flags.DebugFlags.PCTab
ctxt.IsAsm = true
ctxt.Pkgpath = *flags.Importpath
switch *flags.Spectre {
From 0d71234ee4cfcac4a6664d8fef4be575cca1d7c7 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Tue, 15 Mar 2022 13:36:10 -0400
Subject: [PATCH 107/276] reflect: avoid panic in reflect.Kind.String for
negative Kind
Kind(-1).String() used to panic; let's not.
Change-Id: I1dfc0e3298beb37d77713d8327579bbde90dd156
Reviewed-on: https://go-review.googlesource.com/c/go/+/393015
Trust: Russ Cox
Reviewed-by: Ian Lance Taylor
---
src/reflect/all_test.go | 9 +++++++++
src/reflect/type.go | 4 ++--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 5364166eab..06026232ee 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -7807,3 +7807,12 @@ func TestIssue50208(t *testing.T) {
t.Errorf("name of type parameter mismatched, want:%s, got:%s", want2, got)
}
}
+
+func TestNegativeKindString(t *testing.T) {
+ x := -1
+ s := Kind(x).String()
+ want := "kind-1"
+ if s != want {
+ t.Fatalf("Kind(-1).String() = %q, want %q", s, want)
+ }
+}
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 8ba63bcad0..83047062bd 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -632,8 +632,8 @@ const (
// String returns the name of k.
func (k Kind) String() string {
- if int(k) < len(kindNames) {
- return kindNames[k]
+ if uint(k) < uint(len(kindNames)) {
+ return kindNames[uint(k)]
}
return "kind" + strconv.Itoa(int(k))
}
From 1cb34fbb26a406faa64f696242841ddff64517c9 Mon Sep 17 00:00:00 2001
From: Matthew Dempsky
Date: Tue, 1 Feb 2022 17:45:28 -0800
Subject: [PATCH 108/276] go/types, cmd/compile: remove unused Interface.obj
field
Change-Id: I6d0f629f9c7379074a03c8f13b99924d872872a3
Reviewed-on: https://go-review.googlesource.com/c/go/+/385996
Trust: Matthew Dempsky
Run-TryBot: Matthew Dempsky
Reviewed-by: David Chase
TryBot-Result: Gopher Robot
Reviewed-by: Robert Findley
---
src/cmd/compile/internal/types2/interface.go | 1 -
src/cmd/compile/internal/types2/sizeof_test.go | 2 +-
src/cmd/compile/internal/types2/typexpr.go | 3 ---
src/cmd/compile/internal/types2/universe.go | 4 ++--
src/go/types/interface.go | 1 -
src/go/types/sizeof_test.go | 2 +-
src/go/types/typexpr.go | 3 ---
src/go/types/universe.go | 4 ++--
8 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go
index 75597abaf9..b8bf88dc62 100644
--- a/src/cmd/compile/internal/types2/interface.go
+++ b/src/cmd/compile/internal/types2/interface.go
@@ -12,7 +12,6 @@ import "cmd/compile/internal/syntax"
// An Interface represents an interface type.
type Interface struct {
check *Checker // for error reporting; nil once type set is computed
- obj *TypeName // corresponding declared object; or nil (for better error messages)
methods []*Func // ordered list of explicitly declared methods
embeddeds []Type // ordered list of explicitly embedded elements
embedPos *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space
diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go
index 14020050a9..bd31a041b7 100644
--- a/src/cmd/compile/internal/types2/sizeof_test.go
+++ b/src/cmd/compile/internal/types2/sizeof_test.go
@@ -28,7 +28,7 @@ func TestSizeof(t *testing.T) {
{Tuple{}, 12, 24},
{Signature{}, 28, 56},
{Union{}, 12, 24},
- {Interface{}, 44, 88},
+ {Interface{}, 40, 80},
{Map{}, 16, 32},
{Chan{}, 12, 24},
{Named{}, 56, 104},
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index 7e30562e97..40333fd77f 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -348,9 +348,6 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
case *syntax.InterfaceType:
typ := check.newInterface()
def.setUnderlying(typ)
- if def != nil {
- typ.obj = def.obj
- }
check.interfaceType(typ, e, def)
return typ
diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go
index 11c81863a9..1deff3961f 100644
--- a/src/cmd/compile/internal/types2/universe.go
+++ b/src/cmd/compile/internal/types2/universe.go
@@ -97,7 +97,7 @@ func defPredeclaredTypes() {
err := NewFunc(nopos, nil, "Error", sig)
// interface{ Error() string }
- ityp := &Interface{obj: obj, methods: []*Func{err}, complete: true}
+ ityp := &Interface{methods: []*Func{err}, complete: true}
computeInterfaceTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset
typ.SetUnderlying(ityp)
@@ -111,7 +111,7 @@ func defPredeclaredTypes() {
typ := NewNamed(obj, nil, nil)
// interface{} // marked as comparable
- ityp := &Interface{obj: obj, complete: true, tset: &_TypeSet{nil, allTermlist, true}}
+ ityp := &Interface{complete: true, tset: &_TypeSet{nil, allTermlist, true}}
typ.SetUnderlying(ityp)
def(obj)
diff --git a/src/go/types/interface.go b/src/go/types/interface.go
index 3db3580a91..361ef7eddf 100644
--- a/src/go/types/interface.go
+++ b/src/go/types/interface.go
@@ -15,7 +15,6 @@ import (
// An Interface represents an interface type.
type Interface struct {
check *Checker // for error reporting; nil once type set is computed
- obj *TypeName // type name object defining this interface; or nil (for better error messages)
methods []*Func // ordered list of explicitly declared methods
embeddeds []Type // ordered list of explicitly embedded elements
embedPos *[]token.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space
diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go
index bfd14a8109..ba8edf8ad5 100644
--- a/src/go/types/sizeof_test.go
+++ b/src/go/types/sizeof_test.go
@@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) {
{Tuple{}, 12, 24},
{Signature{}, 28, 56},
{Union{}, 12, 24},
- {Interface{}, 44, 88},
+ {Interface{}, 40, 80},
{Map{}, 16, 32},
{Chan{}, 12, 24},
{Named{}, 56, 104},
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 5bb2d8f811..d72b48185a 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -329,9 +329,6 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
case *ast.InterfaceType:
typ := check.newInterface()
def.setUnderlying(typ)
- if def != nil {
- typ.obj = def.obj
- }
check.interfaceType(typ, e, def)
return typ
diff --git a/src/go/types/universe.go b/src/go/types/universe.go
index 303ada4e57..f58128f480 100644
--- a/src/go/types/universe.go
+++ b/src/go/types/universe.go
@@ -98,7 +98,7 @@ func defPredeclaredTypes() {
err := NewFunc(token.NoPos, nil, "Error", sig)
// interface{ Error() string }
- ityp := &Interface{obj: obj, methods: []*Func{err}, complete: true}
+ ityp := &Interface{methods: []*Func{err}, complete: true}
computeInterfaceTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset
typ.SetUnderlying(ityp)
@@ -112,7 +112,7 @@ func defPredeclaredTypes() {
typ := NewNamed(obj, nil, nil)
// interface{} // marked as comparable
- ityp := &Interface{obj: obj, complete: true, tset: &_TypeSet{nil, allTermlist, true}}
+ ityp := &Interface{complete: true, tset: &_TypeSet{nil, allTermlist, true}}
typ.SetUnderlying(ityp)
def(obj)
From 6e49c592de91fd7ea7d47aa50360a1c4f49172f8 Mon Sep 17 00:00:00 2001
From: Matthew Dempsky
Date: Mon, 14 Feb 2022 17:20:48 -0800
Subject: [PATCH 109/276] go/types: return Universe for (*Package)(nil).Scope()
Port of go.dev/cl/325469.
Fixes #46594.
Change-Id: I4bcdafecaa86885360599c204678871646bb221b
Reviewed-on: https://go-review.googlesource.com/c/go/+/385997
Trust: Matthew Dempsky
Run-TryBot: Matthew Dempsky
Reviewed-by: David Chase
TryBot-Result: Gopher Robot
Reviewed-by: Robert Findley
---
src/go/types/package.go | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/go/types/package.go b/src/go/types/package.go
index 7b89def1b5..26385dc39b 100644
--- a/src/go/types/package.go
+++ b/src/go/types/package.go
@@ -39,7 +39,13 @@ func (pkg *Package) SetName(name string) { pkg.name = name }
// Scope returns the (complete or incomplete) package scope
// holding the objects declared at package level (TypeNames,
// Consts, Vars, and Funcs).
-func (pkg *Package) Scope() *Scope { return pkg.scope }
+// For a nil pkg receiver, Scope returns the Universe scope.
+func (pkg *Package) Scope() *Scope {
+ if pkg != nil {
+ return pkg.scope
+ }
+ return Universe
+}
// A package is complete if its scope contains (at least) all
// exported objects; otherwise it is incomplete.
From d34287a4f68de5b8a796ec50b8c6b0582a4afc40 Mon Sep 17 00:00:00 2001
From: Meng Zhuo
Date: Wed, 26 Jan 2022 10:23:48 +0800
Subject: [PATCH 110/276] cmd/link: default generic ABI compression for ELF
This CL change all debug dwarf headers to generic ABI
"Compression header" for ELF
(http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header)
Fixes #50796
Change-Id: I188625e596f11cd120dbd802ac2d79341d5eaf41
Reviewed-on: https://go-review.googlesource.com/c/go/+/380755
Trust: mzh
Run-TryBot: mzh
TryBot-Result: Gopher Robot
Reviewed-by: Than McIntosh
Reviewed-by: Cherry Mui
---
src/cmd/link/elf_test.go | 3 +++
src/cmd/link/internal/ld/data.go | 27 ++++++++++++++++++----
src/cmd/link/internal/ld/dwarf.go | 11 +++++++--
src/cmd/link/internal/ld/elf.go | 3 +++
src/cmd/link/internal/ld/lib.go | 2 +-
src/cmd/link/internal/sym/segment.go | 2 ++
src/debug/elf/file.go | 34 ++++++++++++++++++++++++----
7 files changed, 71 insertions(+), 11 deletions(-)
diff --git a/src/cmd/link/elf_test.go b/src/cmd/link/elf_test.go
index 760d9ea60d..318bd76aba 100644
--- a/src/cmd/link/elf_test.go
+++ b/src/cmd/link/elf_test.go
@@ -455,6 +455,9 @@ func TestPIESize(t *testing.T) {
extraexe := extrasize(elfexe)
extrapie := extrasize(elfpie)
+ if sizepie < sizeexe || sizepie-extrapie < sizeexe-extraexe {
+ return
+ }
diffReal := (sizepie - extrapie) - (sizeexe - extraexe)
diffExpected := (textpie + dynpie) - (textexe + dynexe)
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index 95a8e0facb..0ec1e526a9 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -2778,10 +2778,29 @@ func compressSyms(ctxt *Link, syms []loader.Sym) []byte {
}
var buf bytes.Buffer
- buf.Write([]byte("ZLIB"))
- var sizeBytes [8]byte
- binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
- buf.Write(sizeBytes[:])
+ if ctxt.IsELF {
+ switch ctxt.Arch.PtrSize {
+ case 8:
+ binary.Write(&buf, ctxt.Arch.ByteOrder, elf.Chdr64{
+ Type: uint32(elf.COMPRESS_ZLIB),
+ Size: uint64(total),
+ Addralign: uint64(ctxt.Arch.Alignment),
+ })
+ case 4:
+ binary.Write(&buf, ctxt.Arch.ByteOrder, elf.Chdr32{
+ Type: uint32(elf.COMPRESS_ZLIB),
+ Size: uint32(total),
+ Addralign: uint32(ctxt.Arch.Alignment),
+ })
+ default:
+ log.Fatalf("can't compress header size:%d", ctxt.Arch.PtrSize)
+ }
+ } else {
+ buf.Write([]byte("ZLIB"))
+ var sizeBytes [8]byte
+ binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
+ buf.Write(sizeBytes[:])
+ }
var relocbuf []byte // temporary buffer for applying relocations
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index 4aaed7baf0..289ebcb595 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -2227,11 +2227,18 @@ func dwarfcompress(ctxt *Link) {
newDwarfp = append(newDwarfp, ds)
Segdwarf.Sections = append(Segdwarf.Sections, ldr.SymSect(s))
} else {
- compressedSegName := ".zdebug_" + ldr.SymSect(s).Name[len(".debug_"):]
+ var compressedSegName string
+ if ctxt.IsELF {
+ compressedSegName = ldr.SymSect(s).Name
+ } else {
+ compressedSegName = ".zdebug_" + ldr.SymSect(s).Name[len(".debug_"):]
+ }
sect := addsection(ctxt.loader, ctxt.Arch, &Segdwarf, compressedSegName, 04)
sect.Align = 1
sect.Length = uint64(len(z.compressed))
- newSym := ldr.CreateSymForUpdate(compressedSegName, 0)
+ sect.Compressed = true
+ newSym := ldr.MakeSymbolBuilder(compressedSegName)
+ ldr.SetAttrReachable(s, true)
newSym.SetData(z.compressed)
newSym.SetSize(int64(len(z.compressed)))
ldr.SetSymSect(newSym.Sym(), sect)
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index 1bdfb3369c..7f45a8fce5 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -1102,6 +1102,9 @@ func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
}
if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") {
sh.Flags = 0
+ if sect.Compressed {
+ sh.Flags |= uint64(elf.SHF_COMPRESSED)
+ }
}
if linkmode != LinkExternal {
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index f1a37e955e..a81232b2a4 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1477,7 +1477,7 @@ func (ctxt *Link) hostlink() {
argv = append(argv, unusedArguments)
}
- const compressDWARF = "-Wl,--compress-debug-sections=zlib-gnu"
+ const compressDWARF = "-Wl,--compress-debug-sections=zlib"
if ctxt.compressDWARF && linkerFlagSupported(ctxt.Arch, argv[0], altLinker, compressDWARF) {
argv = append(argv, compressDWARF)
}
diff --git a/src/cmd/link/internal/sym/segment.go b/src/cmd/link/internal/sym/segment.go
index 97853b9355..c889e71ad6 100644
--- a/src/cmd/link/internal/sym/segment.go
+++ b/src/cmd/link/internal/sym/segment.go
@@ -63,4 +63,6 @@ type Section struct {
Relcount uint32
Sym LoaderSym // symbol for the section, if any
Index uint16 // each section has a unique index, used internally
+
+ Compressed bool
}
diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go
index 8c84661c5f..e93200a11d 100644
--- a/src/debug/elf/file.go
+++ b/src/debug/elf/file.go
@@ -1150,11 +1150,37 @@ func (f *File) DWARF() (*dwarf.Data, error) {
if err != nil && uint64(len(b)) < s.Size {
return nil, err
}
-
+ var (
+ dlen uint64
+ dbuf []byte
+ )
if len(b) >= 12 && string(b[:4]) == "ZLIB" {
- dlen := binary.BigEndian.Uint64(b[4:12])
- dbuf := make([]byte, dlen)
- r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
+ dlen = binary.BigEndian.Uint64(b[4:12])
+ s.compressionOffset = 12
+ }
+ if dlen == 0 && len(b) >= 12 && s.Flags&SHF_COMPRESSED != 0 &&
+ s.Flags&SHF_ALLOC == 0 &&
+ f.FileHeader.ByteOrder.Uint32(b[:]) == uint32(COMPRESS_ZLIB) {
+ s.compressionType = COMPRESS_ZLIB
+ switch f.FileHeader.Class {
+ case ELFCLASS32:
+ // Chdr32.Size offset
+ dlen = uint64(f.FileHeader.ByteOrder.Uint32(b[4:]))
+ s.compressionOffset = 12
+ case ELFCLASS64:
+ if len(b) < 24 {
+ return nil, errors.New("invalid compress header 64")
+ }
+ // Chdr64.Size offset
+ dlen = f.FileHeader.ByteOrder.Uint64(b[8:])
+ s.compressionOffset = 24
+ default:
+ return nil, fmt.Errorf("unsupported compress header:%s", f.FileHeader.Class)
+ }
+ }
+ if dlen > 0 {
+ dbuf = make([]byte, dlen)
+ r, err := zlib.NewReader(bytes.NewBuffer(b[s.compressionOffset:]))
if err != nil {
return nil, err
}
From 5fd0ed7aaf39f783ea6f505a3f2ac7d9da7cb03b Mon Sep 17 00:00:00 2001
From: fanzha02
Date: Mon, 7 Jun 2021 14:24:45 +0800
Subject: [PATCH 111/276] cmd/compile: set conversions to unsafe.Pointer as an
escaping operation when -asan is enabled
When ASan is enabled, treat conversions to unsafe.Pointer as
an escaping operation. In this way, all pointer operations on
the stack objects will become operations on the escaped heap
objects. As we've already supported ASan detection of error
memory accesses to heap objects. With this trick, we can use
-asan option to report errors on bad stack operations.
Add test cases.
Updates #44853.
CustomizedGitHooks: yes
Change-Id: I4e7fe46a3ce01f0d219e6a67dc50f4aff7d2ad87
Reviewed-on: https://go-review.googlesource.com/c/go/+/325629
Trust: Fannie Zhang
Reviewed-by: Keith Randall
---
misc/cgo/testsanitizers/asan_test.go | 3 ++
.../testdata/asan_unsafe_fail1.go | 27 ++++++++++++++++++
.../testdata/asan_unsafe_fail2.go | 28 +++++++++++++++++++
.../testdata/asan_unsafe_fail3.go | 21 ++++++++++++++
src/cmd/compile/internal/escape/expr.go | 6 ++--
src/cmd/compile/internal/ir/expr.go | 6 ++++
6 files changed, 88 insertions(+), 3 deletions(-)
create mode 100644 misc/cgo/testsanitizers/testdata/asan_unsafe_fail1.go
create mode 100644 misc/cgo/testsanitizers/testdata/asan_unsafe_fail2.go
create mode 100644 misc/cgo/testsanitizers/testdata/asan_unsafe_fail3.go
diff --git a/misc/cgo/testsanitizers/asan_test.go b/misc/cgo/testsanitizers/asan_test.go
index 22dcf23c3b..ff578ac63e 100644
--- a/misc/cgo/testsanitizers/asan_test.go
+++ b/misc/cgo/testsanitizers/asan_test.go
@@ -41,6 +41,9 @@ func TestASAN(t *testing.T) {
{src: "asan4_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan4_fail.go:13"},
{src: "asan5_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan5_fail.go:18"},
{src: "asan_useAfterReturn.go"},
+ {src: "asan_unsafe_fail1.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail1.go:25"},
+ {src: "asan_unsafe_fail2.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail2.go:25"},
+ {src: "asan_unsafe_fail3.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail3.go:18"},
}
for _, tc := range cases {
tc := tc
diff --git a/misc/cgo/testsanitizers/testdata/asan_unsafe_fail1.go b/misc/cgo/testsanitizers/testdata/asan_unsafe_fail1.go
new file mode 100644
index 0000000000..e66387c5a4
--- /dev/null
+++ b/misc/cgo/testsanitizers/testdata/asan_unsafe_fail1.go
@@ -0,0 +1,27 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "unsafe"
+)
+
+func main() {
+ a := 1
+ b := 2
+ c := add(a, b)
+ d := a + b
+ fmt.Println(c, d)
+}
+
+//go:noinline
+func add(a1, b1 int) int {
+ // The arguments.
+ // When -asan is enabled, unsafe.Pointer(&a1) conversion is escaping.
+ var p *int = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&a1)) + 1*unsafe.Sizeof(int(1))))
+ *p = 10 // BOOM
+ return a1 + b1
+}
diff --git a/misc/cgo/testsanitizers/testdata/asan_unsafe_fail2.go b/misc/cgo/testsanitizers/testdata/asan_unsafe_fail2.go
new file mode 100644
index 0000000000..4f25aac1bd
--- /dev/null
+++ b/misc/cgo/testsanitizers/testdata/asan_unsafe_fail2.go
@@ -0,0 +1,28 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "unsafe"
+)
+
+func main() {
+ a := 1
+ b := 2
+ c := add(a, b)
+ d := a + b
+ fmt.Println(c, d)
+}
+
+//go:noinline
+func add(a1, b1 int) (ret int) {
+ // The return value
+ // When -asan is enabled, the unsafe.Pointer(&ret) conversion is escaping.
+ var p *int = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&ret)) + 1*unsafe.Sizeof(int(1))))
+ *p = 123 // BOOM
+ ret = a1 + b1
+ return
+}
diff --git a/misc/cgo/testsanitizers/testdata/asan_unsafe_fail3.go b/misc/cgo/testsanitizers/testdata/asan_unsafe_fail3.go
new file mode 100644
index 0000000000..a05044fc66
--- /dev/null
+++ b/misc/cgo/testsanitizers/testdata/asan_unsafe_fail3.go
@@ -0,0 +1,21 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "unsafe"
+)
+
+func main() {
+ a := 1
+ b := 2
+ // The local variables.
+ // When -asan is enabled, the unsafe.Pointer(&a) conversion is escaping.
+ var p *int = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&a)) + 1*unsafe.Sizeof(int(1))))
+ *p = 20 // BOOM
+ d := a + b
+ fmt.Println(d)
+}
diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go
index ced90a47bc..9c3e09d10d 100644
--- a/src/cmd/compile/internal/escape/expr.go
+++ b/src/cmd/compile/internal/escape/expr.go
@@ -100,9 +100,9 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
case ir.OCONV, ir.OCONVNOP:
n := n.(*ir.ConvExpr)
- if ir.ShouldCheckPtr(e.curfn, 2) && n.Type().IsUnsafePtr() && n.X.Type().IsPtr() {
- // When -d=checkptr=2 is enabled, treat
- // conversions to unsafe.Pointer as an
+ if (ir.ShouldCheckPtr(e.curfn, 2) || ir.ShouldAsanCheckPtr(e.curfn)) && n.Type().IsUnsafePtr() && n.X.Type().IsPtr() {
+ // When -d=checkptr=2 or -asan is enabled,
+ // treat conversions to unsafe.Pointer as an
// escaping operation. This allows better
// runtime instrumentation, since we can more
// easily detect object boundaries on the heap
diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go
index 156fe96493..ebb84ad78f 100644
--- a/src/cmd/compile/internal/ir/expr.go
+++ b/src/cmd/compile/internal/ir/expr.go
@@ -1035,6 +1035,12 @@ func ShouldCheckPtr(fn *Func, level int) bool {
return base.Debug.Checkptr >= level && fn.Pragma&NoCheckPtr == 0
}
+// ShouldAsanCheckPtr reports whether pointer checking should be enabled for
+// function fn when -asan is enabled.
+func ShouldAsanCheckPtr(fn *Func) bool {
+ return base.Flag.ASan && fn.Pragma&NoCheckPtr == 0
+}
+
// IsReflectHeaderDataField reports whether l is an expression p.Data
// where p has type reflect.SliceHeader or reflect.StringHeader.
func IsReflectHeaderDataField(l Node) bool {
From 1a2f72619510f944289587d41fcb86cad9026f7d Mon Sep 17 00:00:00 2001
From: "Bryan C. Mills"
Date: Thu, 10 Mar 2022 10:41:54 -0500
Subject: [PATCH 112/276] runtime/pprof: do not require a GOROOT/src prefix in
tests
When paths are trimmed, the reported file locations begin with the
package import path (not GOROOT/src).
Updates #51461
Change-Id: Idbd408a02e8d03329d10e30b0b08263e69e66285
Reviewed-on: https://go-review.googlesource.com/c/go/+/391812
Trust: Bryan Mills
Run-TryBot: Bryan Mills
Reviewed-by: Ian Lance Taylor
TryBot-Result: Gopher Robot
Reviewed-by: Cherry Mui
---
src/runtime/pprof/mprof_test.go | 18 +++++++-------
src/runtime/pprof/pprof_test.go | 42 ++++++++++++++++-----------------
2 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/src/runtime/pprof/mprof_test.go b/src/runtime/pprof/mprof_test.go
index 665487a7c4..391588d4ac 100644
--- a/src/runtime/pprof/mprof_test.go
+++ b/src/runtime/pprof/mprof_test.go
@@ -93,31 +93,31 @@ func TestMemoryProfiler(t *testing.T) {
}{{
stk: []string{"runtime/pprof.allocatePersistent1K", "runtime/pprof.TestMemoryProfiler"},
legacy: fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
-# 0x[0-9,a-f]+ runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:47
-# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:82
+# 0x[0-9,a-f]+ runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*runtime/pprof/mprof_test\.go:47
+# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*runtime/pprof/mprof_test\.go:82
`, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun),
}, {
stk: []string{"runtime/pprof.allocateTransient1M", "runtime/pprof.TestMemoryProfiler"},
legacy: fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
-# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:24
-# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:79
+# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*runtime/pprof/mprof_test.go:24
+# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*runtime/pprof/mprof_test.go:79
`, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
}, {
stk: []string{"runtime/pprof.allocateTransient2M", "runtime/pprof.TestMemoryProfiler"},
legacy: fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
-# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:30
-# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:80
+# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*runtime/pprof/mprof_test.go:30
+# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*runtime/pprof/mprof_test.go:80
`, memoryProfilerRun, (2<<20)*memoryProfilerRun),
}, {
stk: []string{"runtime/pprof.allocateTransient2MInline", "runtime/pprof.TestMemoryProfiler"},
legacy: fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
-# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:34
-# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:81
+# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+ .*runtime/pprof/mprof_test.go:34
+# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*runtime/pprof/mprof_test.go:81
`, memoryProfilerRun, (2<<20)*memoryProfilerRun),
}, {
stk: []string{"runtime/pprof.allocateReflectTransient"},
legacy: fmt.Sprintf(`0: 0 \[%v: %v\] @( 0x[0-9,a-f]+)+
-# 0x[0-9,a-f]+ runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:55
+# 0x[0-9,a-f]+ runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+ .*runtime/pprof/mprof_test.go:55
`, memoryProfilerRun, (2<<20)*memoryProfilerRun),
}}
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index 322579cdc4..99897fcfdc 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -809,9 +809,9 @@ func TestBlockProfile(t *testing.T) {
},
re: `
[0-9]+ [0-9]+ @( 0x[[:xdigit:]]+)+
-# 0x[0-9a-f]+ runtime\.chanrecv1\+0x[0-9a-f]+ .*/src/runtime/chan.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.blockChanRecv\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime\.chanrecv1\+0x[0-9a-f]+ .*runtime/chan.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.blockChanRecv\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
`},
{
name: "chan send",
@@ -823,9 +823,9 @@ func TestBlockProfile(t *testing.T) {
},
re: `
[0-9]+ [0-9]+ @( 0x[[:xdigit:]]+)+
-# 0x[0-9a-f]+ runtime\.chansend1\+0x[0-9a-f]+ .*/src/runtime/chan.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.blockChanSend\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime\.chansend1\+0x[0-9a-f]+ .*runtime/chan.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.blockChanSend\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
`},
{
name: "chan close",
@@ -837,9 +837,9 @@ func TestBlockProfile(t *testing.T) {
},
re: `
[0-9]+ [0-9]+ @( 0x[[:xdigit:]]+)+
-# 0x[0-9a-f]+ runtime\.chanrecv1\+0x[0-9a-f]+ .*/src/runtime/chan.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.blockChanClose\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime\.chanrecv1\+0x[0-9a-f]+ .*runtime/chan.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.blockChanClose\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
`},
{
name: "select recv async",
@@ -851,9 +851,9 @@ func TestBlockProfile(t *testing.T) {
},
re: `
[0-9]+ [0-9]+ @( 0x[[:xdigit:]]+)+
-# 0x[0-9a-f]+ runtime\.selectgo\+0x[0-9a-f]+ .*/src/runtime/select.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.blockSelectRecvAsync\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime\.selectgo\+0x[0-9a-f]+ .*runtime/select.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.blockSelectRecvAsync\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
`},
{
name: "select send sync",
@@ -865,9 +865,9 @@ func TestBlockProfile(t *testing.T) {
},
re: `
[0-9]+ [0-9]+ @( 0x[[:xdigit:]]+)+
-# 0x[0-9a-f]+ runtime\.selectgo\+0x[0-9a-f]+ .*/src/runtime/select.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.blockSelectSendSync\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime\.selectgo\+0x[0-9a-f]+ .*runtime/select.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.blockSelectSendSync\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
`},
{
name: "mutex",
@@ -879,9 +879,9 @@ func TestBlockProfile(t *testing.T) {
},
re: `
[0-9]+ [0-9]+ @( 0x[[:xdigit:]]+)+
-# 0x[0-9a-f]+ sync\.\(\*Mutex\)\.Lock\+0x[0-9a-f]+ .*/src/sync/mutex\.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.blockMutex\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ sync\.\(\*Mutex\)\.Lock\+0x[0-9a-f]+ .*sync/mutex\.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.blockMutex\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
`},
{
name: "cond",
@@ -893,9 +893,9 @@ func TestBlockProfile(t *testing.T) {
},
re: `
[0-9]+ [0-9]+ @( 0x[[:xdigit:]]+)+
-# 0x[0-9a-f]+ sync\.\(\*Cond\)\.Wait\+0x[0-9a-f]+ .*/src/sync/cond\.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.blockCond\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
-# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*/src/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ sync\.\(\*Cond\)\.Wait\+0x[0-9a-f]+ .*sync/cond\.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.blockCond\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9a-f]+ runtime/pprof\.TestBlockProfile\+0x[0-9a-f]+ .*runtime/pprof/pprof_test.go:[0-9]+
`},
}
From 95395fdbe3e76778a9035d9478f52513fc34a97b Mon Sep 17 00:00:00 2001
From: Cherry Mui
Date: Fri, 7 Jan 2022 12:13:31 -0500
Subject: [PATCH 113/276] syscall: call ABIInternal entersyscall on register
ABI platforms
Currently, when register ABI is used, syscall.Syscall calls
entersyscall via a wrapper, so the actual entersyscall records the
caller PC and SP of the wrapper. At the point of the actual
syscall, the wrapper frame is gone, so the recorded PC and SP are
technically invalid. Furthermore, in some functions on some
platforms (e.g. Syscall9 on NetBSD/AMD64), that frame is
overwritten. If we unwind the stack from the recorded syscallpc
and syscallsp, it may go wrong. Fix this by calling the
ABIInternal function directly.
exitsyscall calls are changed as well. It doesn't really matter,
just changed for consistency.
Change-Id: Iead8dd22cf32b05e382414fef664b7c4c1719b7c
Reviewed-on: https://go-review.googlesource.com/c/go/+/376356
Trust: Cherry Mui
Run-TryBot: Cherry Mui
TryBot-Result: Gopher Robot
Reviewed-by: Michael Knyszek
---
src/syscall/asm9_unix2_amd64.s | 6 +++---
src/syscall/asm_darwin_amd64.s | 18 +++++++++---------
src/syscall/asm_darwin_arm64.s | 18 +++++++++---------
src/syscall/asm_freebsd_arm64.s | 18 +++++++++---------
src/syscall/asm_linux_amd64.s | 12 ++++++------
src/syscall/asm_linux_arm64.s | 12 ++++++------
src/syscall/asm_linux_ppc64x.s | 12 ++++++------
src/syscall/asm_netbsd_amd64.s | 6 +++---
src/syscall/asm_netbsd_arm64.s | 19 +++++++++----------
src/syscall/asm_plan9_amd64.s | 12 ++++++------
src/syscall/asm_unix_amd64.s | 12 ++++++------
11 files changed, 72 insertions(+), 73 deletions(-)
diff --git a/src/syscall/asm9_unix2_amd64.s b/src/syscall/asm9_unix2_amd64.s
index 649bc6024c..5bf53a1251 100644
--- a/src/syscall/asm9_unix2_amd64.s
+++ b/src/syscall/asm9_unix2_amd64.s
@@ -13,7 +13,7 @@
// func Syscall9(trap int64, a1, a2, a3, a4, a5, a6, a7, a8, a9 int64) (r1, r2, err int64);
TEXT ·Syscall9(SB),NOSPLIT,$0-104
- CALL runtime·entersyscall(SB)
+ CALL runtime·entersyscall(SB)
MOVQ num+0(FP), AX // syscall entry
MOVQ a1+8(FP), DI
MOVQ a2+16(FP), SI
@@ -38,11 +38,11 @@ TEXT ·Syscall9(SB),NOSPLIT,$0-104
MOVQ $-1, r1+80(FP) // r1
MOVQ $0, r2+88(FP) // r2
MOVQ AX, err+96(FP) // errno
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
ok9:
MOVQ AX, r1+80(FP) // r1
MOVQ DX, r2+88(FP) // r2
MOVQ $0, err+96(FP) // errno
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
diff --git a/src/syscall/asm_darwin_amd64.s b/src/syscall/asm_darwin_amd64.s
index c863889a71..77b58e051b 100644
--- a/src/syscall/asm_darwin_amd64.s
+++ b/src/syscall/asm_darwin_amd64.s
@@ -13,7 +13,7 @@
// func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno);
TEXT ·Syscall(SB),NOSPLIT,$0-56
- CALL runtime·entersyscall(SB)
+ CALL runtime·entersyscall(SB)
MOVQ a1+8(FP), DI
MOVQ a2+16(FP), SI
MOVQ a3+24(FP), DX
@@ -24,18 +24,18 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
MOVQ $-1, r1+32(FP)
MOVQ $0, r2+40(FP)
MOVQ AX, err+48(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
ok:
MOVQ AX, r1+32(FP)
MOVQ DX, r2+40(FP)
MOVQ $0, err+48(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno);
TEXT ·Syscall6(SB),NOSPLIT,$0-80
- CALL runtime·entersyscall(SB)
+ CALL runtime·entersyscall(SB)
MOVQ a1+8(FP), DI
MOVQ a2+16(FP), SI
MOVQ a3+24(FP), DX
@@ -49,18 +49,18 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-80
MOVQ $-1, r1+56(FP)
MOVQ $0, r2+64(FP)
MOVQ AX, err+72(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
ok6:
MOVQ AX, r1+56(FP)
MOVQ DX, r2+64(FP)
MOVQ $0, err+72(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
// func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
- CALL runtime·entersyscall(SB)
+ CALL runtime·entersyscall(SB)
MOVQ trap+0(FP), AX // syscall entry
MOVQ a1+8(FP), DI
MOVQ a2+16(FP), SI
@@ -82,14 +82,14 @@ TEXT ·Syscall9(SB),NOSPLIT,$0-104
MOVQ $-1, r1+80(FP)
MOVQ $0, r2+88(FP)
MOVQ AX, err+96(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
ok9:
ADDQ $32, SP
MOVQ AX, r1+80(FP)
MOVQ DX, r2+88(FP)
MOVQ $0, err+96(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
// func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
diff --git a/src/syscall/asm_darwin_arm64.s b/src/syscall/asm_darwin_arm64.s
index 95b6dc0db5..22e07666df 100644
--- a/src/syscall/asm_darwin_arm64.s
+++ b/src/syscall/asm_darwin_arm64.s
@@ -10,7 +10,7 @@
// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr)
TEXT ·Syscall(SB),NOSPLIT,$0-56
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD trap+0(FP), R16
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
@@ -21,13 +21,13 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
MOVD R1, r1+32(FP) // r1
MOVD ZR, r2+40(FP) // r2
MOVD R0, err+48(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+32(FP) // r1
MOVD R1, r2+40(FP) // r2
MOVD ZR, err+48(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
// func RawSyscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr)
@@ -51,7 +51,7 @@ ok:
// func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD trap+0(FP), R16 // syscall entry
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
@@ -65,13 +65,13 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-80
MOVD R1, r1+56(FP) // r1
MOVD ZR, r2+64(FP) // r2
MOVD R0, err+72(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+56(FP) // r1
MOVD R1, r2+64(FP) // r2
MOVD ZR, err+72(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
// func RawSyscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
@@ -99,7 +99,7 @@ ok:
// Actually Syscall7
TEXT ·Syscall9(SB),NOSPLIT,$0-104
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD num+0(FP), R16 // syscall entry
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
@@ -116,12 +116,12 @@ TEXT ·Syscall9(SB),NOSPLIT,$0-104
MOVD R1, r1+80(FP) // r1
MOVD ZR, r2+88(FP) // r2
MOVD R0, err+96(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+80(FP) // r1
MOVD R1, r2+88(FP) // r2
MOVD ZR, err+96(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
diff --git a/src/syscall/asm_freebsd_arm64.s b/src/syscall/asm_freebsd_arm64.s
index 7a0809b8ec..b032ce7f69 100644
--- a/src/syscall/asm_freebsd_arm64.s
+++ b/src/syscall/asm_freebsd_arm64.s
@@ -12,7 +12,7 @@
// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr)
TEXT ·Syscall(SB),NOSPLIT,$0-56
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD trap+0(FP), R8 // syscall entry
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
@@ -23,13 +23,13 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
MOVD R1, r1+32(FP)
MOVD ZR, r2+40(FP)
MOVD R0, err+48(FP)
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+32(FP)
MOVD R1, r2+40(FP)
MOVD ZR, err+48(FP)
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
// func RawSyscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr)
@@ -53,7 +53,7 @@ ok:
// func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD trap+0(FP), R8 // syscall entry
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
@@ -67,13 +67,13 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-80
MOVD R1, r1+56(FP)
MOVD ZR, r2+64(FP)
MOVD R0, err+72(FP)
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+56(FP)
MOVD R1, r2+64(FP)
MOVD ZR, err+72(FP)
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
// func RawSyscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
@@ -101,7 +101,7 @@ ok:
// Actually Syscall7
// func Syscall9(num uintptr, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD num+0(FP), R8 // syscall entry
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
@@ -118,11 +118,11 @@ TEXT ·Syscall9(SB),NOSPLIT,$0-104
MOVD R1, r1+80(FP)
MOVD ZR, r2+88(FP)
MOVD R0, err+96(FP)
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+80(FP)
MOVD R1, r2+88(FP)
MOVD ZR, err+96(FP)
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s
index a9af68d51d..0b55a30fa0 100644
--- a/src/syscall/asm_linux_amd64.s
+++ b/src/syscall/asm_linux_amd64.s
@@ -17,7 +17,7 @@
// would pass 4th arg in CX, not R10.
TEXT ·Syscall(SB),NOSPLIT,$0-56
- CALL runtime·entersyscall(SB)
+ CALL runtime·entersyscall(SB)
MOVQ a1+8(FP), DI
MOVQ a2+16(FP), SI
MOVQ a3+24(FP), DX
@@ -29,18 +29,18 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
MOVQ $0, r2+40(FP)
NEGQ AX
MOVQ AX, err+48(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
ok:
MOVQ AX, r1+32(FP)
MOVQ DX, r2+40(FP)
MOVQ $0, err+48(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
- CALL runtime·entersyscall(SB)
+ CALL runtime·entersyscall(SB)
MOVQ a1+8(FP), DI
MOVQ a2+16(FP), SI
MOVQ a3+24(FP), DX
@@ -55,13 +55,13 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-80
MOVQ $0, r2+64(FP)
NEGQ AX
MOVQ AX, err+72(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
ok6:
MOVQ AX, r1+56(FP)
MOVQ DX, r2+64(FP)
MOVQ $0, err+72(FP)
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
// func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s
index a30e4d87d4..6c50fa9d7c 100644
--- a/src/syscall/asm_linux_arm64.s
+++ b/src/syscall/asm_linux_arm64.s
@@ -6,7 +6,7 @@
// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
TEXT ·Syscall(SB),NOSPLIT,$0-56
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
MOVD a3+24(FP), R2
@@ -22,17 +22,17 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
MOVD ZR, r2+40(FP) // r2
NEG R0, R0
MOVD R0, err+48(FP) // errno
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+32(FP) // r1
MOVD R1, r2+40(FP) // r2
MOVD ZR, err+48(FP) // errno
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
TEXT ·Syscall6(SB),NOSPLIT,$0-80
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
MOVD a3+24(FP), R2
@@ -48,13 +48,13 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-80
MOVD ZR, r2+64(FP) // r2
NEG R0, R0
MOVD R0, err+72(FP) // errno
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+56(FP) // r1
MOVD R1, r2+64(FP) // r2
MOVD ZR, err+72(FP) // errno
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s
index 1f5cb37ffe..bf701e5291 100644
--- a/src/syscall/asm_linux_ppc64x.s
+++ b/src/syscall/asm_linux_ppc64x.s
@@ -12,7 +12,7 @@
// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
TEXT ·Syscall(SB),NOSPLIT,$0-56
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD a1+8(FP), R3
MOVD a2+16(FP), R4
MOVD a3+24(FP), R5
@@ -26,17 +26,17 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
MOVD R4, r1+32(FP) // r1
MOVD R0, r2+40(FP) // r2
MOVD R3, err+48(FP) // errno
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R3, r1+32(FP) // r1
MOVD R0, r2+40(FP) // r2
MOVD R0, err+48(FP) // errno
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
TEXT ·Syscall6(SB),NOSPLIT,$0-80
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD a1+8(FP), R3
MOVD a2+16(FP), R4
MOVD a3+24(FP), R5
@@ -50,13 +50,13 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-80
MOVD R4, r1+56(FP) // r1
MOVD R0, r2+64(FP) // r2
MOVD R3, err+72(FP) // errno
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok6:
MOVD R3, r1+56(FP) // r1
MOVD R0, r2+64(FP) // r2
MOVD R0, err+72(FP) // errno
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
diff --git a/src/syscall/asm_netbsd_amd64.s b/src/syscall/asm_netbsd_amd64.s
index 9e4dd20ad3..457e207296 100644
--- a/src/syscall/asm_netbsd_amd64.s
+++ b/src/syscall/asm_netbsd_amd64.s
@@ -11,7 +11,7 @@
// func Syscall9(trap int64, a1, a2, a3, a4, a5, a6, a7, a8, a9 int64) (r1, r2, err int64);
TEXT ·Syscall9(SB),NOSPLIT,$0-104
- CALL runtime·entersyscall(SB)
+ CALL runtime·entersyscall(SB)
MOVQ num+0(FP), AX // syscall entry
MOVQ a1+8(FP), DI
MOVQ a2+16(FP), SI
@@ -32,12 +32,12 @@ TEXT ·Syscall9(SB),NOSPLIT,$0-104
MOVQ $-1, 88(SP) // r1
MOVQ $0, 96(SP) // r2
MOVQ AX, 104(SP) // errno
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
ok9:
ADDQ $32, SP
MOVQ AX, 88(SP) // r1
MOVQ DX, 96(SP) // r2
MOVQ $0, 104(SP) // errno
- CALL runtime·exitsyscall(SB)
+ CALL runtime·exitsyscall(SB)
RET
diff --git a/src/syscall/asm_netbsd_arm64.s b/src/syscall/asm_netbsd_arm64.s
index fbcd3388c9..aebd83f325 100644
--- a/src/syscall/asm_netbsd_arm64.s
+++ b/src/syscall/asm_netbsd_arm64.s
@@ -12,7 +12,7 @@
// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr)
TEXT ·Syscall(SB),NOSPLIT,$0-56
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD trap+0(FP), R17
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
@@ -23,13 +23,13 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
MOVD R1, r1+32(FP) // r1
MOVD ZR, r2+40(FP) // r2
MOVD R0, err+48(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+32(FP) // r1
MOVD R1, r2+40(FP) // r2
MOVD ZR, err+48(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
// func RawSyscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr)
@@ -53,7 +53,7 @@ ok:
// func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD trap+0(FP), R17 // syscall entry
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
@@ -67,13 +67,13 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-80
MOVD R1, r1+56(FP) // r1
MOVD ZR, r2+64(FP) // r2
MOVD R0, err+72(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+56(FP) // r1
MOVD R1, r2+64(FP) // r2
MOVD ZR, err+72(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
// func RawSyscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
@@ -101,7 +101,7 @@ ok:
// Actually Syscall7
TEXT ·Syscall9(SB),NOSPLIT,$0-104
- BL runtime·entersyscall(SB)
+ BL runtime·entersyscall(SB)
MOVD num+0(FP), R17 // syscall entry
MOVD a1+8(FP), R0
MOVD a2+16(FP), R1
@@ -118,12 +118,11 @@ TEXT ·Syscall9(SB),NOSPLIT,$0-104
MOVD R1, r1+80(FP) // r1
MOVD ZR, r2+88(FP) // r2
MOVD R0, err+96(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall(SB)
RET
ok:
MOVD R0, r1+80(FP) // r1
MOVD R1, r2+88(FP) // r2
MOVD ZR, err+96(FP) // err
- BL runtime·exitsyscall(SB)
+ BL runtime·exitsyscall