aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2025-10-03 10:11:20 -0400
committerCherry Mui <cherryyz@google.com>2025-10-03 10:11:21 -0400
commitfb1749a3fe6ac40c56127d8fcea2e8b13db820e8 (patch)
tree72dd38fc84286bf88311850a99e6becf2cbd99bf /src/cmd
parent703a5fbaad81f1285776bf6f2900506d3c751ea1 (diff)
parentadce7f196e6ac6d22e9bc851efea5f3ab650947c (diff)
downloadgo-fb1749a3fe6ac40c56127d8fcea2e8b13db820e8.tar.xz
[dev.simd] all: merge master (adce7f1) into dev.simd
Conflicts: - src/internal/goexperiment/flags.go - src/runtime/export_test.go Merge List: + 2025-10-03 adce7f196e cmd/link: support .def file with MSVC clang toolchain + 2025-10-03 d5b950399d cmd/cgo: fix unaligned arguments typedmemmove crash on iOS + 2025-10-02 53845004d6 net/http/httputil: deprecate ReverseProxy.Director + 2025-10-02 bbdff9e8e1 net/http: update bundled x/net/http2 and delete obsolete http2inTests + 2025-10-02 4008e07080 io/fs: move path name documentation up to the package doc comment + 2025-10-02 0e4e2e6832 runtime: skip TestGoroutineLeakProfile under mayMoreStackPreempt + 2025-10-02 f03c392295 runtime: fix aix/ppc64 library initialization + 2025-10-02 707454b41f cmd/go: update `go help mod edit` with the tool and ignore sections + 2025-10-02 8c68a1c1ab runtime,net/http/pprof: goroutine leak detection by using the garbage collector + 2025-10-02 84db201ae1 cmd/compile: propagate len([]T{}) to make builtin to allow stack allocation + 2025-10-02 5799c139a7 crypto/tls: rm marshalEncryptedClientHelloConfigList dead code + 2025-10-01 633dd1d475 encoding/json: fix Decoder.InputOffset regression in goexperiment.jsonv2 + 2025-10-01 8ad27fb656 doc/go_spec.html: update date + 2025-10-01 3f451f2c54 testing/synctest: fix inverted test failure message in TestContextAfterFunc + 2025-10-01 be0fed8a5f cmd/go/testdata/script/test_fuzz_fuzztime.txt: disable + 2025-09-30 eb1c7f6e69 runtime: move loong64 library entry point to os-agnostic file + 2025-09-30 c9257151e5 runtime: unify ppc64/ppc64le library entry point + 2025-09-30 4ff8a457db test/codegen: codify handling of floating point constants on arm64 + 2025-09-30 fcb893fc4b cmd/compile/internal/ssa: remove redundant "type:" prefix check + 2025-09-30 19cc1022ba mime: reduce allocs incurred by ParseMediaType + 2025-09-30 08afc50bea mime: extend "builtinTypes" to include a more complete list of common types + 2025-09-30 97da068774 cmd/compile: eliminate nil checks on .dict arg + 2025-09-30 300d9d2714 runtime: initialise debug settings much earlier in startup process + 2025-09-30 a846bb0aa5 errors: add AsType + 2025-09-30 7c8166d02d cmd/link/internal/arm64: support Mach-O ARM64_RELOC_SUBTRACTOR in internal linking + 2025-09-30 6e95748335 cmd/link/internal/arm64: support Mach-O ARM64_RELOC_POINTER_TO_GOT in internal linking + 2025-09-30 742f92063e cmd/compile, runtime: always enable Wasm signext and satconv features + 2025-09-30 db10db6be3 internal/poll: remove operation fields from FD + 2025-09-29 75c87df58e internal/poll: pass the I/O mode instead of an overlapped object in execIO + 2025-09-29 fc88e18b4a crypto/internal/fips140/entropy: add CPU jitter-based entropy source + 2025-09-29 db4fade759 crypto/internal/fips140/mlkem: make CAST conditional + 2025-09-29 db3cb3fd9a runtime: correct reference to getStackMap in comment + 2025-09-29 690fc2fb05 internal/poll: remove buf field from operation + 2025-09-29 eaf2345256 cmd/link: use a .def file to mark exported symbols on Windows + 2025-09-29 4b77733565 internal/syscall/windows: regenerate GetFileSizeEx + 2025-09-29 4e9006a716 crypto/tls: quote protocols in ALPN error message + 2025-09-29 047c2ab841 cmd/link: don't pass -Wl,-S on Solaris + 2025-09-29 ae8eba071b cmd/link: use correct length for pcln.cutab + 2025-09-29 fe3ba74b9e cmd/link: skip TestFlagW on platforms without DWARF symbol table + 2025-09-29 d42d56b764 encoding/xml: make use of reflect.TypeAssert + 2025-09-29 6d51f93257 runtime: jump instead of branch in netbsd/arm64 entry point + 2025-09-28 5500cbf0e4 debug/elf: prevent offset overflow + 2025-09-27 34e67623a8 all: fix typos + 2025-09-27 af6999e60d cmd/compile: implement jump table on loong64 + 2025-09-26 63cd912083 os/user: simplify go:build + 2025-09-26 53009b26dd runtime: use a smaller arena size on Wasm + 2025-09-26 3a5df9d2b2 net/http: add HTTP2Config.StrictMaxConcurrentRequests + 2025-09-26 16be34df02 net/http: add more tests of transport connection pool + 2025-09-26 3e4540b49d os/user: use getgrouplist on illumos && cgo + 2025-09-26 15fbe3480b internal/poll: simplify WriteMsg and ReadMsg on Windows + 2025-09-26 16ae11a9e1 runtime: move TestReadMetricsSched to testprog + 2025-09-26 459f3a3adc cmd/link: don't pass -Wl,-S on AIX + 2025-09-26 4631a2d3c6 cmd/link: skip TestFlagW on AIX + 2025-09-26 0f31d742cd cmd/compile: fix ICE with new(<untyped expr>) + 2025-09-26 7d7cd6e07b internal/poll: don't call SetFilePointerEx in Seek for overlapped handles + 2025-09-26 41cba31e66 mime/multipart: percent-encode CR and LF in header values to avoid CRLF injection + 2025-09-26 dd1d597c3a Revert "cmd/internal/obj/loong64: use the MOVVP instruction to optimize prologue" + 2025-09-26 45d6bc76af runtime: unify arm64 entry point code + 2025-09-25 fdea7da3e6 runtime: use common library entry point on windows amd64/386 + 2025-09-25 e8a4f508d1 lib/fips140: re-seal v1.0.0 + 2025-09-25 9b7a328089 crypto/internal/fips140: remove key import PCTs, make keygen PCTs fatal + 2025-09-25 7f9ab7203f crypto/internal/fips140: update frozen module version to "v1.0.0" + 2025-09-25 fb5719cbda crypto/internal/fips140/ecdsa: make TestingOnlyNewDRBG generic + 2025-09-25 56067e31f2 std: remove unused declarations Change-Id: Iecb28fd62c69fbed59da557f46d31bae55889e2c
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/cgo/internal/testcshared/cshared_test.go75
-rw-r--r--src/cmd/cgo/internal/testout/out_test.go144
-rw-r--r--src/cmd/cgo/internal/testout/testdata/aligned.go63
-rw-r--r--src/cmd/cgo/out.go19
-rw-r--r--src/cmd/compile/internal/escape/escape.go13
-rw-r--r--src/cmd/compile/internal/loong64/ssa.go23
-rw-r--r--src/cmd/compile/internal/noder/reader.go1
-rw-r--r--src/cmd/compile/internal/ssa/_gen/LOONG64.rules2
-rw-r--r--src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go6
-rw-r--r--src/cmd/compile/internal/ssa/_gen/Wasm.rules9
-rw-r--r--src/cmd/compile/internal/ssa/_gen/generic.rules3
-rw-r--r--src/cmd/compile/internal/ssa/opGen.go30
-rw-r--r--src/cmd/compile/internal/ssa/rewrite.go24
-rw-r--r--src/cmd/compile/internal/ssa/rewriteLOONG64.go13
-rw-r--r--src/cmd/compile/internal/ssa/rewriteWasm.go109
-rw-r--r--src/cmd/compile/internal/ssa/rewritegeneric.go15
-rw-r--r--src/cmd/compile/internal/wasm/ssa.go21
-rw-r--r--src/cmd/go/alldocs.go12
-rw-r--r--src/cmd/go/internal/fips140/mkzip.go8
-rw-r--r--src/cmd/go/internal/modcmd/edit.go12
-rw-r--r--src/cmd/go/testdata/script/fipssnap.txt5
-rw-r--r--src/cmd/go/testdata/script/test_fuzz_fuzztime.txt2
-rw-r--r--src/cmd/internal/obj/link.go20
-rw-r--r--src/cmd/internal/obj/loong64/asm.go9
-rw-r--r--src/cmd/internal/obj/loong64/obj.go2
-rw-r--r--src/cmd/internal/sys/arch.go1
-rw-r--r--src/cmd/link/dwarf_test.go9
-rw-r--r--src/cmd/link/internal/arm64/asm.go33
-rw-r--r--src/cmd/link/internal/ld/lib.go17
-rw-r--r--src/cmd/link/internal/ld/macho.go2
-rw-r--r--src/cmd/link/internal/ld/pe.go44
-rw-r--r--src/cmd/link/internal/ld/symtab.go4
-rw-r--r--src/cmd/link/internal/ld/xcoff.go5
-rw-r--r--src/cmd/link/internal/loader/loader.go16
34 files changed, 531 insertions, 240 deletions
diff --git a/src/cmd/cgo/internal/testcshared/cshared_test.go b/src/cmd/cgo/internal/testcshared/cshared_test.go
index f1c30f8f9a..2ce705adba 100644
--- a/src/cmd/cgo/internal/testcshared/cshared_test.go
+++ b/src/cmd/cgo/internal/testcshared/cshared_test.go
@@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"cmd/cgo/internal/cgotest"
+ "cmp"
"debug/elf"
"debug/pe"
"encoding/binary"
@@ -272,7 +273,7 @@ func createHeaders() error {
// which results in the linkers output implib getting overwritten at each step. So instead build the
// import library the traditional way, using a def file.
err = os.WriteFile("libgo.def",
- []byte("LIBRARY libgo.dll\nEXPORTS\n\tDidInitRun\n\tDidMainRun\n\tDivu\n\tFromPkg\n\t_cgo_dummy_export\n"),
+ []byte("LIBRARY libgo.dll\nEXPORTS\n\tDidInitRun\n\tDidMainRun\n\tDivu\n\tFromPkg\n"),
0644)
if err != nil {
return fmt.Errorf("unable to write def file: %v", err)
@@ -375,9 +376,23 @@ func TestExportedSymbols(t *testing.T) {
}
}
-func checkNumberOfExportedFunctionsWindows(t *testing.T, prog string, exportedFunctions int, wantAll bool) {
+func checkNumberOfExportedSymbolsWindows(t *testing.T, exportedSymbols int, wantAll bool) {
+ t.Parallel()
tmpdir := t.TempDir()
+ prog := `
+package main
+import "C"
+func main() {}
+`
+
+ for i := range exportedSymbols {
+ prog += fmt.Sprintf(`
+//export GoFunc%d
+func GoFunc%d() {}
+`, i, i)
+ }
+
srcfile := filepath.Join(tmpdir, "test.go")
objfile := filepath.Join(tmpdir, "test.dll")
if err := os.WriteFile(srcfile, []byte(prog), 0666); err != nil {
@@ -443,18 +458,19 @@ func checkNumberOfExportedFunctionsWindows(t *testing.T, prog string, exportedFu
t.Fatalf("binary.Read failed: %v", err)
}
- // Only the two exported functions and _cgo_dummy_export should be exported.
+ exportedSymbols = cmp.Or(exportedSymbols, 1) // _cgo_stub_export is exported if there are no other symbols exported
+
// NumberOfNames is the number of functions exported with a unique name.
// NumberOfFunctions can be higher than that because it also counts
// functions exported only by ordinal, a unique number asigned by the linker,
// and linkers might add an unknown number of their own ordinal-only functions.
if wantAll {
- if e.NumberOfNames <= uint32(exportedFunctions) {
- t.Errorf("got %d exported names, want > %d", e.NumberOfNames, exportedFunctions)
+ if e.NumberOfNames <= uint32(exportedSymbols) {
+ t.Errorf("got %d exported names, want > %d", e.NumberOfNames, exportedSymbols)
}
} else {
- if e.NumberOfNames > uint32(exportedFunctions) {
- t.Errorf("got %d exported names, want <= %d", e.NumberOfNames, exportedFunctions)
+ if e.NumberOfNames != uint32(exportedSymbols) {
+ t.Errorf("got %d exported names, want %d", e.NumberOfNames, exportedSymbols)
}
}
}
@@ -470,43 +486,14 @@ func TestNumberOfExportedFunctions(t *testing.T) {
t.Parallel()
- const prog0 = `
-package main
-
-import "C"
-
-func main() {
-}
-`
-
- const prog2 = `
-package main
-
-import "C"
-
-//export GoFunc
-func GoFunc() {
- println(42)
-}
-
-//export GoFunc2
-func GoFunc2() {
- println(24)
-}
-
-func main() {
-}
-`
- // All programs export _cgo_dummy_export, so add 1 to the expected counts.
- t.Run("OnlyExported/0", func(t *testing.T) {
- checkNumberOfExportedFunctionsWindows(t, prog0, 0+1, false)
- })
- t.Run("OnlyExported/2", func(t *testing.T) {
- checkNumberOfExportedFunctionsWindows(t, prog2, 2+1, false)
- })
- t.Run("All", func(t *testing.T) {
- checkNumberOfExportedFunctionsWindows(t, prog2, 2+1, true)
- })
+ for i := range 3 {
+ t.Run(fmt.Sprintf("OnlyExported/%d", i), func(t *testing.T) {
+ checkNumberOfExportedSymbolsWindows(t, i, false)
+ })
+ t.Run(fmt.Sprintf("All/%d", i), func(t *testing.T) {
+ checkNumberOfExportedSymbolsWindows(t, i, true)
+ })
+ }
}
// test1: shared library can be dynamically loaded and exported symbols are accessible.
diff --git a/src/cmd/cgo/internal/testout/out_test.go b/src/cmd/cgo/internal/testout/out_test.go
new file mode 100644
index 0000000000..81dfa36587
--- /dev/null
+++ b/src/cmd/cgo/internal/testout/out_test.go
@@ -0,0 +1,144 @@
+// Copyright 2025 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 out_test
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "internal/testenv"
+ "internal/goarch"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+type methodAlign struct {
+ Method string
+ Align int
+}
+
+var wantAligns = map[string]int{
+ "ReturnEmpty": 1,
+ "ReturnOnlyUint8": 1,
+ "ReturnOnlyUint16": 2,
+ "ReturnOnlyUint32": 4,
+ "ReturnOnlyUint64": goarch.PtrSize,
+ "ReturnOnlyInt": goarch.PtrSize,
+ "ReturnOnlyPtr": goarch.PtrSize,
+ "ReturnByteSlice": goarch.PtrSize,
+ "ReturnString": goarch.PtrSize,
+ "InputAndReturnUint8": 1,
+ "MixedTypes": goarch.PtrSize,
+}
+
+// TestAligned tests that the generated _cgo_export.c file has the wanted
+// align attributes for struct types used as arguments or results of
+// //exported functions.
+func TestAligned(t *testing.T) {
+ testenv.MustHaveGoRun(t)
+ testenv.MustHaveCGO(t)
+
+ testdata, err := filepath.Abs("testdata")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ objDir := t.TempDir()
+
+ cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "cgo",
+ "-objdir", objDir,
+ filepath.Join(testdata, "aligned.go"))
+ cmd.Stderr = new(bytes.Buffer)
+
+ err = cmd.Run()
+ if err != nil {
+ t.Fatalf("%#q: %v\n%s", cmd, err, cmd.Stderr)
+ }
+
+ haveAligns, err := parseAlign(filepath.Join(objDir, "_cgo_export.c"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Check that we have all the wanted methods
+ if len(haveAligns) != len(wantAligns) {
+ t.Fatalf("have %d methods with aligned, want %d", len(haveAligns), len(wantAligns))
+ }
+
+ for i := range haveAligns {
+ method := haveAligns[i].Method
+ haveAlign := haveAligns[i].Align
+
+ wantAlign, ok := wantAligns[method]
+ if !ok {
+ t.Errorf("method %s: have aligned %d, want missing entry", method, haveAlign)
+ } else if haveAlign != wantAlign {
+ t.Errorf("method %s: have aligned %d, want %d", method, haveAlign, wantAlign)
+ }
+ }
+}
+
+func parseAlign(filename string) ([]methodAlign, error) {
+ file, err := os.Open(filename)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open file: %w", err)
+ }
+ defer file.Close()
+
+ var results []methodAlign
+ scanner := bufio.NewScanner(file)
+
+ // Regex to match function declarations like "struct MethodName_return MethodName("
+ funcRegex := regexp.MustCompile(`^struct\s+(\w+)_return\s+(\w+)\(`)
+ // Regex to match simple function declarations like "GoSlice MethodName("
+ simpleFuncRegex := regexp.MustCompile(`^Go\w+\s+(\w+)\(`)
+ // Regex to match void-returning exported functions like "void ReturnEmpty("
+ voidFuncRegex := regexp.MustCompile(`^void\s+(\w+)\(`)
+ // Regex to match align attributes like "__attribute__((aligned(8)))"
+ alignRegex := regexp.MustCompile(`__attribute__\(\(aligned\((\d+)\)\)\)`)
+
+ var currentMethod string
+
+ for scanner.Scan() {
+ line := strings.TrimSpace(scanner.Text())
+
+ // Check if this line declares a function with struct return type
+ if matches := funcRegex.FindStringSubmatch(line); matches != nil {
+ currentMethod = matches[2] // Extract the method name
+ } else if matches := simpleFuncRegex.FindStringSubmatch(line); matches != nil {
+ // Check if this line declares a function with simple return type (like GoSlice)
+ currentMethod = matches[1] // Extract the method name
+ } else if matches := voidFuncRegex.FindStringSubmatch(line); matches != nil {
+ // Check if this line declares a void-returning function
+ currentMethod = matches[1] // Extract the method name
+ }
+
+ // Check if this line contains align information
+ if alignMatches := alignRegex.FindStringSubmatch(line); alignMatches != nil && currentMethod != "" {
+ alignStr := alignMatches[1]
+ align, err := strconv.Atoi(alignStr)
+ if err != nil {
+ // Skip this entry if we can't parse the align as integer
+ currentMethod = ""
+ continue
+ }
+ results = append(results, methodAlign{
+ Method: currentMethod,
+ Align: align,
+ })
+ currentMethod = "" // Reset for next method
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("error reading file: %w", err)
+ }
+
+ return results, nil
+}
diff --git a/src/cmd/cgo/internal/testout/testdata/aligned.go b/src/cmd/cgo/internal/testout/testdata/aligned.go
new file mode 100644
index 0000000000..cea6f2889a
--- /dev/null
+++ b/src/cmd/cgo/internal/testout/testdata/aligned.go
@@ -0,0 +1,63 @@
+// Copyright 2025 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 "C"
+
+//export ReturnEmpty
+func ReturnEmpty() {
+ return
+}
+
+//export ReturnOnlyUint8
+func ReturnOnlyUint8() (uint8, uint8, uint8) {
+ return 1, 2, 3
+}
+
+//export ReturnOnlyUint16
+func ReturnOnlyUint16() (uint16, uint16, uint16) {
+ return 1, 2, 3
+}
+
+//export ReturnOnlyUint32
+func ReturnOnlyUint32() (uint32, uint32, uint32) {
+ return 1, 2, 3
+}
+
+//export ReturnOnlyUint64
+func ReturnOnlyUint64() (uint64, uint64, uint64) {
+ return 1, 2, 3
+}
+
+//export ReturnOnlyInt
+func ReturnOnlyInt() (int, int, int) {
+ return 1, 2, 3
+}
+
+//export ReturnOnlyPtr
+func ReturnOnlyPtr() (*int, *int, *int) {
+ a, b, c := 1, 2, 3
+ return &a, &b, &c
+}
+
+//export ReturnString
+func ReturnString() string {
+ return "hello"
+}
+
+//export ReturnByteSlice
+func ReturnByteSlice() []byte {
+ return []byte{1, 2, 3}
+}
+
+//export InputAndReturnUint8
+func InputAndReturnUint8(a, b, c uint8) (uint8, uint8, uint8) {
+ return a, b, c
+}
+
+//export MixedTypes
+func MixedTypes(a uint8, b uint16, c uint32, d uint64, e int, f *int) (uint8, uint16, uint32, uint64, int, *int) {
+ return a, b, c, d, e, f
+}
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index dfa54e41d3..a2bcdf89c5 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -949,6 +949,8 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
fmt.Fprintf(gotype, "struct {\n")
off := int64(0)
npad := 0
+ // the align is at least 1 (for char)
+ maxAlign := int64(1)
argField := func(typ ast.Expr, namePat string, args ...interface{}) {
name := fmt.Sprintf(namePat, args...)
t := p.cgoType(typ)
@@ -963,6 +965,11 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
noSourceConf.Fprint(gotype, fset, typ)
fmt.Fprintf(gotype, "\n")
off += t.Size
+ // keep track of the maximum alignment among all fields
+ // so that we can align the struct correctly
+ if t.Align > maxAlign {
+ maxAlign = t.Align
+ }
}
if fn.Recv != nil {
argField(fn.Recv.List[0].Type, "recv")
@@ -1005,12 +1012,8 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
}
// Build the wrapper function compiled by gcc.
- gccExport := ""
- if goos == "windows" {
- gccExport = "__declspec(dllexport) "
- }
var s strings.Builder
- fmt.Fprintf(&s, "%s%s %s(", gccExport, gccResult, exp.ExpName)
+ fmt.Fprintf(&s, "%s %s(", gccResult, exp.ExpName)
if fn.Recv != nil {
s.WriteString(p.cgoType(fn.Recv.List[0].Type).C.String())
s.WriteString(" recv")
@@ -1051,7 +1054,11 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
// string.h for memset, and is also robust to C++
// types with constructors. Both GCC and LLVM optimize
// this into just zeroing _cgo_a.
- fmt.Fprintf(fgcc, "\ttypedef %s %v _cgo_argtype;\n", ctype.String(), p.packedAttribute())
+ //
+ // The struct should be aligned to the maximum alignment
+ // of any of its fields. This to avoid alignment
+ // issues.
+ fmt.Fprintf(fgcc, "\ttypedef %s %v __attribute__((aligned(%d))) _cgo_argtype;\n", ctype.String(), p.packedAttribute(), maxAlign)
fmt.Fprintf(fgcc, "\tstatic _cgo_argtype _cgo_zero;\n")
fmt.Fprintf(fgcc, "\t_cgo_argtype _cgo_a = _cgo_zero;\n")
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go
index 6b34830b3d..59250edfef 100644
--- a/src/cmd/compile/internal/escape/escape.go
+++ b/src/cmd/compile/internal/escape/escape.go
@@ -563,7 +563,10 @@ func (b *batch) rewriteWithLiterals(n ir.Node, fn *ir.Func) {
if ro == nil {
base.Fatalf("no ReassignOracle for function %v with closure parent %v", fn, fn.ClosureParent)
}
- if s := ro.StaticValue(*r); s.Op() == ir.OLITERAL {
+
+ s := ro.StaticValue(*r)
+ switch s.Op() {
+ case ir.OLITERAL:
lit, ok := s.(*ir.BasicLit)
if !ok || lit.Val().Kind() != constant.Int {
base.Fatalf("unexpected BasicLit Kind")
@@ -577,6 +580,14 @@ func (b *batch) rewriteWithLiterals(n ir.Node, fn *ir.Func) {
assignTemp(n.Pos(), *r, n.PtrInit())
*r = ir.NewBasicLit(n.Pos(), (*r).Type(), lit.Val())
}
+ case ir.OLEN:
+ x := ro.StaticValue(s.(*ir.UnaryExpr).X)
+ if x.Op() == ir.OSLICELIT {
+ x := x.(*ir.CompLitExpr)
+ // Preserve any side effects of the original expression, then update the value.
+ assignTemp(n.Pos(), *r, n.PtrInit())
+ *r = ir.NewBasicLit(n.Pos(), types.Types[types.TINT], constant.MakeInt64(x.Len))
+ }
}
}
case ir.OCONVIFACE:
diff --git a/src/cmd/compile/internal/loong64/ssa.go b/src/cmd/compile/internal/loong64/ssa.go
index 100ebf0456..bd0d96a695 100644
--- a/src/cmd/compile/internal/loong64/ssa.go
+++ b/src/cmd/compile/internal/loong64/ssa.go
@@ -1266,6 +1266,29 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
p.From.Reg = b.Controls[0].Reg()
}
}
+ case ssa.BlockLOONG64JUMPTABLE:
+ // ALSLV $3, Rarg0, Rarg1, REGTMP
+ // MOVV (REGTMP), REGTMP
+ // JMP (REGTMP)
+ p := s.Prog(loong64.AALSLV)
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = 3 // idx*8
+ p.Reg = b.Controls[0].Reg()
+ p.AddRestSourceReg(b.Controls[1].Reg())
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = loong64.REGTMP
+ p1 := s.Prog(loong64.AMOVV)
+ p1.From.Type = obj.TYPE_MEM
+ p1.From.Reg = loong64.REGTMP
+ p1.From.Offset = 0
+ p1.To.Type = obj.TYPE_REG
+ p1.To.Reg = loong64.REGTMP
+ p2 := s.Prog(obj.AJMP)
+ p2.To.Type = obj.TYPE_MEM
+ p2.To.Reg = loong64.REGTMP
+ // Save jump tables for later resolution of the target blocks.
+ s.JumpTables = append(s.JumpTables, b)
+
default:
b.Fatalf("branch not implemented: %s", b.LongString())
}
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index ca7c6bf151..41eb2dce1c 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -2434,6 +2434,7 @@ func (r *reader) expr() (res ir.Node) {
if r.Bool() {
// new(expr) -> tmp := expr; &tmp
x := r.expr()
+ x = typecheck.DefaultLit(x, nil) // See TODO in exprConvert case.
var init ir.Nodes
addr := ir.NewAddrExpr(pos, r.tempCopy(pos, x, &init))
addr.SetInit(init)
diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules
index 0d2384143c..287eedee37 100644
--- a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules
+++ b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules
@@ -504,6 +504,8 @@
(MOVBUreg x:((SGT|SGTU) _ _)) => x
(MOVBUreg x:(XOR (MOVVconst [1]) ((SGT|SGTU) _ _))) => x
+(JumpTable idx) => (JUMPTABLE {makeJumpTableSym(b)} idx (MOVVaddr <typ.Uintptr> {makeJumpTableSym(b)} (SB)))
+
// Write barrier.
(WB ...) => (LoweredWB ...)
diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
index a3db4def56..a85a566660 100644
--- a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
+++ b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
@@ -577,6 +577,12 @@ func init() {
{name: "BLT", controls: 2}, // controls[0] < controls[1]
{name: "BGEU", controls: 2}, // controls[0] >= controls[1], unsigned
{name: "BLTU", controls: 2}, // controls[0] < controls[1], unsigned
+
+ // JUMPTABLE implements jump tables.
+ // Aux is the symbol (an *obj.LSym) for the jump table.
+ // control[0] is the index into the jump table.
+ // control[1] is the address of the jump table (the address of the symbol stored in Aux).
+ {name: "JUMPTABLE", controls: 2, aux: "Sym"},
}
archs = append(archs, arch{
diff --git a/src/cmd/compile/internal/ssa/_gen/Wasm.rules b/src/cmd/compile/internal/ssa/_gen/Wasm.rules
index f3bd8d8b4f..f632a01109 100644
--- a/src/cmd/compile/internal/ssa/_gen/Wasm.rules
+++ b/src/cmd/compile/internal/ssa/_gen/Wasm.rules
@@ -55,12 +55,9 @@
(ZeroExt32to64 x:(I64Load32U _ _)) => x
(ZeroExt16to(64|32) x:(I64Load16U _ _)) => x
(ZeroExt8to(64|32|16) x:(I64Load8U _ _)) => x
-(SignExt32to64 x) && buildcfg.GOWASM.SignExt => (I64Extend32S x)
-(SignExt8to(64|32|16) x) && buildcfg.GOWASM.SignExt => (I64Extend8S x)
-(SignExt16to(64|32) x) && buildcfg.GOWASM.SignExt => (I64Extend16S x)
-(SignExt32to64 x) => (I64ShrS (I64Shl x (I64Const [32])) (I64Const [32]))
-(SignExt16to(64|32) x) => (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48]))
-(SignExt8to(64|32|16) x) => (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
+(SignExt32to64 x) => (I64Extend32S x)
+(SignExt8to(64|32|16) x) => (I64Extend8S x)
+(SignExt16to(64|32) x) => (I64Extend16S x)
(ZeroExt32to64 x) => (I64And x (I64Const [0xffffffff]))
(ZeroExt16to(64|32) x) => (I64And x (I64Const [0xffff]))
(ZeroExt8to(64|32|16) x) => (I64And x (I64Const [0xff]))
diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules
index dae33d19e1..78f177468c 100644
--- a/src/cmd/compile/internal/ssa/_gen/generic.rules
+++ b/src/cmd/compile/internal/ssa/_gen/generic.rules
@@ -2083,6 +2083,9 @@
&& warnRule(fe.Debug_checknil(), v, "removed nil check")
=> ptr
+// .dict args are always non-nil.
+(NilCheck ptr:(Arg {sym}) _) && isDictArgSym(sym) => ptr
+
// Nil checks of nil checks are redundant.
// See comment at the end of https://go-review.googlesource.com/c/go/+/537775.
(NilCheck ptr:(NilCheck _ _) _ ) => ptr
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index 7e44a31956..aef077bb8e 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -108,6 +108,7 @@ const (
BlockLOONG64BLT
BlockLOONG64BGEU
BlockLOONG64BLTU
+ BlockLOONG64JUMPTABLE
BlockMIPSEQ
BlockMIPSNE
@@ -250,20 +251,21 @@ var blockString = [...]string{
BlockARM64GEnoov: "GEnoov",
BlockARM64JUMPTABLE: "JUMPTABLE",
- BlockLOONG64EQZ: "EQZ",
- BlockLOONG64NEZ: "NEZ",
- BlockLOONG64LTZ: "LTZ",
- BlockLOONG64LEZ: "LEZ",
- BlockLOONG64GTZ: "GTZ",
- BlockLOONG64GEZ: "GEZ",
- BlockLOONG64FPT: "FPT",
- BlockLOONG64FPF: "FPF",
- BlockLOONG64BEQ: "BEQ",
- BlockLOONG64BNE: "BNE",
- BlockLOONG64BGE: "BGE",
- BlockLOONG64BLT: "BLT",
- BlockLOONG64BGEU: "BGEU",
- BlockLOONG64BLTU: "BLTU",
+ BlockLOONG64EQZ: "EQZ",
+ BlockLOONG64NEZ: "NEZ",
+ BlockLOONG64LTZ: "LTZ",
+ BlockLOONG64LEZ: "LEZ",
+ BlockLOONG64GTZ: "GTZ",
+ BlockLOONG64GEZ: "GEZ",
+ BlockLOONG64FPT: "FPT",
+ BlockLOONG64FPF: "FPF",
+ BlockLOONG64BEQ: "BEQ",
+ BlockLOONG64BNE: "BNE",
+ BlockLOONG64BGE: "BGE",
+ BlockLOONG64BLT: "BLT",
+ BlockLOONG64BGEU: "BGEU",
+ BlockLOONG64BLTU: "BLTU",
+ BlockLOONG64JUMPTABLE: "JUMPTABLE",
BlockMIPSEQ: "EQ",
BlockMIPSNE: "NE",
diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go
index 6d83ba5653..47f225c7ae 100644
--- a/src/cmd/compile/internal/ssa/rewrite.go
+++ b/src/cmd/compile/internal/ssa/rewrite.go
@@ -6,9 +6,11 @@ package ssa
import (
"cmd/compile/internal/base"
+ "cmd/compile/internal/ir"
"cmd/compile/internal/logopt"
"cmd/compile/internal/reflectdata"
"cmd/compile/internal/rttype"
+ "cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/obj/s390x"
@@ -2057,12 +2059,12 @@ func isFixedLoad(v *Value, sym Sym, off int64) bool {
return false
}
- if strings.HasPrefix(lsym.Name, "type:") {
+ if ti := lsym.TypeInfo(); ti != nil {
// Type symbols do not contain information about their fields, unlike the cases above.
// Hand-implement field accesses.
// TODO: can this be replaced with reflectdata.writeType and just use the code above?
- t := (*lsym.Extra).(*obj.TypeInfo).Type.(*types.Type)
+ t := ti.Type.(*types.Type)
for _, f := range rttype.Type.Fields() {
if f.Offset == off && copyCompatibleType(v.Type, f.Type) {
@@ -2116,12 +2118,12 @@ func rewriteFixedLoad(v *Value, sym Sym, sb *Value, off int64) *Value {
base.Fatalf("fixedLoad data not known for %s:%d", sym, off)
}
- if strings.HasPrefix(lsym.Name, "type:") {
+ if ti := lsym.TypeInfo(); ti != nil {
// Type symbols do not contain information about their fields, unlike the cases above.
// Hand-implement field accesses.
// TODO: can this be replaced with reflectdata.writeType and just use the code above?
- t := (*lsym.Extra).(*obj.TypeInfo).Type.(*types.Type)
+ t := ti.Type.(*types.Type)
ptrSizedOpConst := OpConst64
if f.Config.PtrSize == 4 {
@@ -2611,10 +2613,7 @@ func isDirectType1(v *Value) bool {
return isDirectType2(v.Args[0])
case OpAddr:
lsym := v.Aux.(*obj.LSym)
- if lsym.Extra == nil {
- return false
- }
- if ti, ok := (*lsym.Extra).(*obj.TypeInfo); ok {
+ if ti := lsym.TypeInfo(); ti != nil {
return types.IsDirectIface(ti.Type.(*types.Type))
}
}
@@ -2647,10 +2646,7 @@ func isDirectIface1(v *Value, depth int) bool {
return isDirectIface2(v.Args[0], depth-1)
case OpAddr:
lsym := v.Aux.(*obj.LSym)
- if lsym.Extra == nil {
- return false
- }
- if ii, ok := (*lsym.Extra).(*obj.ItabInfo); ok {
+ if ii := lsym.ItabInfo(); ii != nil {
return types.IsDirectIface(ii.Type.(*types.Type))
}
case OpConstNil:
@@ -2744,3 +2740,7 @@ func panicBoundsCToAux(p PanicBoundsC) Aux {
func panicBoundsCCToAux(p PanicBoundsCC) Aux {
return p
}
+
+func isDictArgSym(sym Sym) bool {
+ return sym.(*ir.Name).Sym().Name == typecheck.LocalDictName
+}
diff --git a/src/cmd/compile/internal/ssa/rewriteLOONG64.go b/src/cmd/compile/internal/ssa/rewriteLOONG64.go
index 3990b2833b..3fc57e9f49 100644
--- a/src/cmd/compile/internal/ssa/rewriteLOONG64.go
+++ b/src/cmd/compile/internal/ssa/rewriteLOONG64.go
@@ -12148,6 +12148,19 @@ func rewriteBlockLOONG64(b *Block) bool {
b.resetWithControl(BlockLOONG64NEZ, v0)
return true
}
+ case BlockJumpTable:
+ // match: (JumpTable idx)
+ // result: (JUMPTABLE {makeJumpTableSym(b)} idx (MOVVaddr <typ.Uintptr> {makeJumpTableSym(b)} (SB)))
+ for {
+ idx := b.Controls[0]
+ v0 := b.NewValue0(b.Pos, OpLOONG64MOVVaddr, typ.Uintptr)
+ v0.Aux = symToAux(makeJumpTableSym(b))
+ v1 := b.NewValue0(b.Pos, OpSB, typ.Uintptr)
+ v0.AddArg(v1)
+ b.resetWithControl2(BlockLOONG64JUMPTABLE, idx, v0)
+ b.Aux = symToAux(makeJumpTableSym(b))
+ return true
+ }
case BlockLOONG64LEZ:
// match: (LEZ (MOVVconst [c]) yes no)
// cond: c <= 0
diff --git a/src/cmd/compile/internal/ssa/rewriteWasm.go b/src/cmd/compile/internal/ssa/rewriteWasm.go
index c3c5528aaa..a164a6eee5 100644
--- a/src/cmd/compile/internal/ssa/rewriteWasm.go
+++ b/src/cmd/compile/internal/ssa/rewriteWasm.go
@@ -2,7 +2,6 @@
package ssa
-import "internal/buildcfg"
import "math"
import "cmd/compile/internal/types"
@@ -3202,8 +3201,6 @@ func rewriteValueWasm_OpRsh8x8(v *Value) bool {
}
func rewriteValueWasm_OpSignExt16to32(v *Value) bool {
v_0 := v.Args[0]
- b := v.Block
- typ := &b.Func.Config.Types
// match: (SignExt16to32 x:(I64Load16S _ _))
// result: x
for {
@@ -3215,34 +3212,16 @@ func rewriteValueWasm_OpSignExt16to32(v *Value) bool {
return true
}
// match: (SignExt16to32 x)
- // cond: buildcfg.GOWASM.SignExt
// result: (I64Extend16S x)
for {
x := v_0
- if !(buildcfg.GOWASM.SignExt) {
- break
- }
v.reset(OpWasmI64Extend16S)
v.AddArg(x)
return true
}
- // match: (SignExt16to32 x)
- // result: (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48]))
- for {
- x := v_0
- v.reset(OpWasmI64ShrS)
- v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
- v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
- v1.AuxInt = int64ToAuxInt(48)
- v0.AddArg2(x, v1)
- v.AddArg2(v0, v1)
- return true
- }
}
func rewriteValueWasm_OpSignExt16to64(v *Value) bool {
v_0 := v.Args[0]
- b := v.Block
- typ := &b.Func.Config.Types
// match: (SignExt16to64 x:(I64Load16S _ _))
// result: x
for {
@@ -3254,34 +3233,16 @@ func rewriteValueWasm_OpSignExt16to64(v *Value) bool {
return true
}
// match: (SignExt16to64 x)
- // cond: buildcfg.GOWASM.SignExt
// result: (I64Extend16S x)
for {
x := v_0
- if !(buildcfg.GOWASM.SignExt) {
- break
- }
v.reset(OpWasmI64Extend16S)
v.AddArg(x)
return true
}
- // match: (SignExt16to64 x)
- // result: (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48]))
- for {
- x := v_0
- v.reset(OpWasmI64ShrS)
- v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
- v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
- v1.AuxInt = int64ToAuxInt(48)
- v0.AddArg2(x, v1)
- v.AddArg2(v0, v1)
- return true
- }
}
func rewriteValueWasm_OpSignExt32to64(v *Value) bool {
v_0 := v.Args[0]
- b := v.Block
- typ := &b.Func.Config.Types
// match: (SignExt32to64 x:(I64Load32S _ _))
// result: x
for {
@@ -3293,34 +3254,16 @@ func rewriteValueWasm_OpSignExt32to64(v *Value) bool {
return true
}
// match: (SignExt32to64 x)
- // cond: buildcfg.GOWASM.SignExt
// result: (I64Extend32S x)
for {
x := v_0
- if !(buildcfg.GOWASM.SignExt) {
- break
- }
v.reset(OpWasmI64Extend32S)
v.AddArg(x)
return true
}
- // match: (SignExt32to64 x)
- // result: (I64ShrS (I64Shl x (I64Const [32])) (I64Const [32]))
- for {
- x := v_0
- v.reset(OpWasmI64ShrS)
- v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
- v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
- v1.AuxInt = int64ToAuxInt(32)
- v0.AddArg2(x, v1)
- v.AddArg2(v0, v1)
- return true
- }
}
func rewriteValueWasm_OpSignExt8to16(v *Value) bool {
v_0 := v.Args[0]
- b := v.Block
- typ := &b.Func.Config.Types
// match: (SignExt8to16 x:(I64Load8S _ _))
// result: x
for {
@@ -3332,34 +3275,16 @@ func rewriteValueWasm_OpSignExt8to16(v *Value) bool {
return true
}
// match: (SignExt8to16 x)
- // cond: buildcfg.GOWASM.SignExt
// result: (I64Extend8S x)
for {
x := v_0
- if !(buildcfg.GOWASM.SignExt) {
- break
- }
v.reset(OpWasmI64Extend8S)
v.AddArg(x)
return true
}
- // match: (SignExt8to16 x)
- // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
- for {
- x := v_0
- v.reset(OpWasmI64ShrS)
- v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
- v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
- v1.AuxInt = int64ToAuxInt(56)
- v0.AddArg2(x, v1)
- v.AddArg2(v0, v1)
- return true
- }
}
func rewriteValueWasm_OpSignExt8to32(v *Value) bool {
v_0 := v.Args[0]
- b := v.Block
- typ := &b.Func.Config.Types
// match: (SignExt8to32 x:(I64Load8S _ _))
// result: x
for {
@@ -3371,34 +3296,16 @@ func rewriteValueWasm_OpSignExt8to32(v *Value) bool {
return true
}
// match: (SignExt8to32 x)
- // cond: buildcfg.GOWASM.SignExt
// result: (I64Extend8S x)
for {
x := v_0
- if !(buildcfg.GOWASM.SignExt) {
- break
- }
v.reset(OpWasmI64Extend8S)
v.AddArg(x)
return true
}
- // match: (SignExt8to32 x)
- // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
- for {
- x := v_0
- v.reset(OpWasmI64ShrS)
- v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
- v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
- v1.AuxInt = int64ToAuxInt(56)
- v0.AddArg2(x, v1)
- v.AddArg2(v0, v1)
- return true
- }
}
func rewriteValueWasm_OpSignExt8to64(v *Value) bool {
v_0 := v.Args[0]
- b := v.Block
- typ := &b.Func.Config.Types
// match: (SignExt8to64 x:(I64Load8S _ _))
// result: x
for {
@@ -3410,29 +3317,13 @@ func rewriteValueWasm_OpSignExt8to64(v *Value) bool {
return true
}
// match: (SignExt8to64 x)
- // cond: buildcfg.GOWASM.SignExt
// result: (I64Extend8S x)
for {
x := v_0
- if !(buildcfg.GOWASM.SignExt) {
- break
- }
v.reset(OpWasmI64Extend8S)
v.AddArg(x)
return true
}
- // match: (SignExt8to64 x)
- // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56]))
- for {
- x := v_0
- v.reset(OpWasmI64ShrS)
- v0 := b.NewValue0(v.Pos, OpWasmI64Shl, typ.Int64)
- v1 := b.NewValue0(v.Pos, OpWasmI64Const, typ.Int64)
- v1.AuxInt = int64ToAuxInt(56)
- v0.AddArg2(x, v1)
- v.AddArg2(v0, v1)
- return true
- }
}
func rewriteValueWasm_OpSlicemask(v *Value) bool {
v_0 := v.Args[0]
diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go
index 232d29c0e9..bda3d5116a 100644
--- a/src/cmd/compile/internal/ssa/rewritegeneric.go
+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go
@@ -21395,6 +21395,21 @@ func rewriteValuegeneric_OpNilCheck(v *Value) bool {
v.copyOf(ptr)
return true
}
+ // match: (NilCheck ptr:(Arg {sym}) _)
+ // cond: isDictArgSym(sym)
+ // result: ptr
+ for {
+ ptr := v_0
+ if ptr.Op != OpArg {
+ break
+ }
+ sym := auxToSym(ptr.Aux)
+ if !(isDictArgSym(sym)) {
+ break
+ }
+ v.copyOf(ptr)
+ return true
+ }
// match: (NilCheck ptr:(NilCheck _ _) _ )
// result: ptr
for {
diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go
index daee82f1fd..1e3b318e8c 100644
--- a/src/cmd/compile/internal/wasm/ssa.go
+++ b/src/cmd/compile/internal/wasm/ssa.go
@@ -14,7 +14,6 @@ import (
"cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/obj/wasm"
- "internal/buildcfg"
)
/*
@@ -425,27 +424,11 @@ func ssaGenValueOnStack(s *ssagen.State, v *ssa.Value, extend bool) {
case ssa.OpWasmI64TruncSatF32S, ssa.OpWasmI64TruncSatF64S:
getValue64(s, v.Args[0])
- if buildcfg.GOWASM.SatConv {
- s.Prog(v.Op.Asm())
- } else {
- if v.Op == ssa.OpWasmI64TruncSatF32S {
- s.Prog(wasm.AF64PromoteF32)
- }
- p := s.Prog(wasm.ACall)
- p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: ir.Syms.WasmTruncS}
- }
+ s.Prog(v.Op.Asm())
case ssa.OpWasmI64TruncSatF32U, ssa.OpWasmI64TruncSatF64U:
getValue64(s, v.Args[0])
- if buildcfg.GOWASM.SatConv {
- s.Prog(v.Op.Asm())
- } else {
- if v.Op == ssa.OpWasmI64TruncSatF32U {
- s.Prog(wasm.AF64PromoteF32)
- }
- p := s.Prog(wasm.ACall)
- p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: ir.Syms.WasmTruncU}
- }
+ s.Prog(v.Op.Asm())
case ssa.OpWasmF32DemoteF64:
getValue64(s, v.Args[0])
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index f1e1b1c333..19b48f0579 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -1280,11 +1280,6 @@
// The -json flag prints the final go.mod file in JSON format instead of
// writing it back to go.mod. The JSON output corresponds to these Go types:
//
-// type Module struct {
-// Path string
-// Version string
-// }
-//
// type GoMod struct {
// Module ModPath
// Go string
@@ -1294,6 +1289,13 @@
// Exclude []Module
// Replace []Replace
// Retract []Retract
+// Tool []Tool
+// Ignore []Ignore
+// }
+//
+// type Module struct {
+// Path string
+// Version string
// }
//
// type ModPath struct {
diff --git a/src/cmd/go/internal/fips140/mkzip.go b/src/cmd/go/internal/fips140/mkzip.go
index 7a6ba80324..a139a0f2e2 100644
--- a/src/cmd/go/internal/fips140/mkzip.go
+++ b/src/cmd/go/internal/fips140/mkzip.go
@@ -27,10 +27,10 @@ import (
"log"
"os"
"path/filepath"
- "regexp"
"strings"
"golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
modzip "golang.org/x/mod/zip"
)
@@ -61,7 +61,7 @@ func main() {
// Must have valid version, and must not overwrite existing file.
version := flag.Arg(0)
- if !regexp.MustCompile(`^v\d+\.\d+\.\d+$`).MatchString(version) {
+ if semver.Canonical(version) != version {
log.Fatalf("invalid version %q; must be vX.Y.Z", version)
}
if _, err := os.Stat(version + ".zip"); err == nil {
@@ -117,7 +117,9 @@ func main() {
if !bytes.Contains(contents, []byte(returnLine)) {
log.Fatalf("did not find %q in fips140.go", returnLine)
}
- newLine := `return "` + version + `"`
+ // Use only the vX.Y.Z part of a possible vX.Y.Z-hash version.
+ v, _, _ := strings.Cut(version, "-")
+ newLine := `return "` + v + `"`
contents = bytes.ReplaceAll(contents, []byte(returnLine), []byte(newLine))
wf, err := zw.Create(f.Name)
if err != nil {
diff --git a/src/cmd/go/internal/modcmd/edit.go b/src/cmd/go/internal/modcmd/edit.go
index aafd9752a8..041b4432bf 100644
--- a/src/cmd/go/internal/modcmd/edit.go
+++ b/src/cmd/go/internal/modcmd/edit.go
@@ -104,11 +104,6 @@ writing it back to go.mod.
The -json flag prints the final go.mod file in JSON format instead of
writing it back to go.mod. The JSON output corresponds to these Go types:
- type Module struct {
- Path string
- Version string
- }
-
type GoMod struct {
Module ModPath
Go string
@@ -118,6 +113,13 @@ writing it back to go.mod. The JSON output corresponds to these Go types:
Exclude []Module
Replace []Replace
Retract []Retract
+ Tool []Tool
+ Ignore []Ignore
+ }
+
+ type Module struct {
+ Path string
+ Version string
}
type ModPath struct {
diff --git a/src/cmd/go/testdata/script/fipssnap.txt b/src/cmd/go/testdata/script/fipssnap.txt
index 9888bc82f1..4d96aedf2a 100644
--- a/src/cmd/go/testdata/script/fipssnap.txt
+++ b/src/cmd/go/testdata/script/fipssnap.txt
@@ -1,4 +1,4 @@
-env snap=v1.0.0
+env snap=v1.0.0-c2097c7c
env alias=inprocess
env GOFIPS140=$snap
@@ -23,8 +23,7 @@ stdout crypto/internal/fips140/$snap/sha256
! stdout crypto/internal/fips140/check
# again with GOFIPS140=$alias
-# TODO: enable when we add inprocess.txt
-# env GOFIPS140=$alias
+env GOFIPS140=$alias
# default GODEBUG includes fips140=on
go list -f '{{.DefaultGODEBUG}}'
diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt
index 027c434a32..3cc23985a3 100644
--- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt
@@ -1,3 +1,5 @@
+skip # a 5s timeout is never going to be reliable (go.dev/issue/72140)
+
[!fuzz] skip
[short] skip
env GOCACHE=$WORK/cache
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index 6513e11687..816fed026f 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -464,7 +464,7 @@ type LSym struct {
P []byte
R []Reloc
- Extra *interface{} // *FuncInfo, *VarInfo, *FileInfo, or *TypeInfo, if present
+ Extra *interface{} // *FuncInfo, *VarInfo, *FileInfo, *TypeInfo, or *ItabInfo, if present
Pkg string
PkgIdx int32
@@ -604,6 +604,15 @@ func (s *LSym) NewTypeInfo() *TypeInfo {
return t
}
+// TypeInfo returns the *TypeInfo associated with s, or else nil.
+func (s *LSym) TypeInfo() *TypeInfo {
+ if s.Extra == nil {
+ return nil
+ }
+ t, _ := (*s.Extra).(*TypeInfo)
+ return t
+}
+
// An ItabInfo contains information for a symbol
// that contains a runtime.itab.
type ItabInfo struct {
@@ -620,6 +629,15 @@ func (s *LSym) NewItabInfo() *ItabInfo {
return t
}
+// ItabInfo returns the *ItabInfo associated with s, or else nil.
+func (s *LSym) ItabInfo() *ItabInfo {
+ if s.Extra == nil {
+ return nil
+ }
+ i, _ := (*s.Extra).(*ItabInfo)
+ return i
+}
+
// WasmImport represents a WebAssembly (WASM) imported function with
// parameters and results translated into WASM types based on the Go function
// declaration.
diff --git a/src/cmd/internal/obj/loong64/asm.go b/src/cmd/internal/obj/loong64/asm.go
index e20ceaae95..ca6e2be4aa 100644
--- a/src/cmd/internal/obj/loong64/asm.go
+++ b/src/cmd/internal/obj/loong64/asm.go
@@ -707,6 +707,15 @@ func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
// so instruction sequences that use REGTMP are unsafe to
// preempt asynchronously.
obj.MarkUnsafePoints(c.ctxt, c.cursym.Func().Text, c.newprog, c.isUnsafePoint, c.isRestartable)
+
+ // Now that we know byte offsets, we can generate jump table entries.
+ for _, jt := range cursym.Func().JumpTables {
+ for i, p := range jt.Targets {
+ // The ith jumptable entry points to the p.Pc'th
+ // byte in the function symbol s.
+ jt.Sym.WriteAddr(ctxt, int64(i)*8, 8, cursym, p.Pc)
+ }
+ }
}
// isUnsafePoint returns whether p is an unsafe point.
diff --git a/src/cmd/internal/obj/loong64/obj.go b/src/cmd/internal/obj/loong64/obj.go
index ea110f00cb..a97217d316 100644
--- a/src/cmd/internal/obj/loong64/obj.go
+++ b/src/cmd/internal/obj/loong64/obj.go
@@ -324,7 +324,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q = c.ctxt.StartUnsafePoint(q, c.newprog)
q = obj.Appendp(q, newprog)
- q.As = AMOVVP
+ q.As = mov
q.Pos = p.Pos
q.From.Type = obj.TYPE_REG
q.From.Reg = REGLINK
diff --git a/src/cmd/internal/sys/arch.go b/src/cmd/internal/sys/arch.go
index 484538f28f..3c92a6bbf2 100644
--- a/src/cmd/internal/sys/arch.go
+++ b/src/cmd/internal/sys/arch.go
@@ -145,6 +145,7 @@ var ArchLoong64 = &Arch{
MinLC: 4,
Alignment: 8, // Unaligned accesses are not guaranteed to be fast
CanMergeLoads: true,
+ CanJumpTable: true,
HasLR: true,
FixedFrameSize: 8, // LR
}
diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go
index 4ca578498d..56a076002a 100644
--- a/src/cmd/link/dwarf_test.go
+++ b/src/cmd/link/dwarf_test.go
@@ -361,6 +361,13 @@ func TestDWARFLocationList(t *testing.T) {
func TestFlagW(t *testing.T) {
testenv.MustHaveGoBuild(t)
+ if runtime.GOOS == "aix" {
+ t.Skip("internal/xcoff cannot parse file without symbol table")
+ }
+ if !platform.ExecutableHasDWARF(runtime.GOOS, runtime.GOARCH) {
+ t.Skipf("skipping on %s/%s: no DWARF symbol table in executables", runtime.GOOS, runtime.GOARCH)
+ }
+
t.Parallel()
tmpdir := t.TempDir()
@@ -379,7 +386,7 @@ func TestFlagW(t *testing.T) {
{"-s", false}, // -s implies -w
{"-s -w=0", true}, // -w=0 negates the implied -w
}
- if testenv.HasCGO() {
+ if testenv.HasCGO() && runtime.GOOS != "solaris" { // Solaris linker doesn't support the -S flag
tests = append(tests,
testCase{"-w -linkmode=external", false},
testCase{"-s -linkmode=external", false},
diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go
index 68474b4484..8d8ea8ac54 100644
--- a/src/cmd/link/internal/arm64/asm.go
+++ b/src/cmd/link/internal/arm64/asm.go
@@ -224,6 +224,28 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
}
return true
+ case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_SUBTRACTOR*2:
+ // ARM64_RELOC_SUBTRACTOR must be followed by ARM64_RELOC_UNSIGNED.
+ // The pair of relocations resolves to the difference between two
+ // symbol addresses (each relocation specifies a symbol).
+ outer, off := ld.FoldSubSymbolOffset(ldr, targ)
+ if outer != s {
+ // TODO: support subtracted symbol in different section.
+ ldr.Errorf(s, "unsupported ARM64_RELOC_SUBTRACTOR reloc: target %s, outer %s", ldr.SymName(targ), ldr.SymName(outer))
+ break
+ }
+ su := ldr.MakeSymbolUpdater(s)
+ relocs := su.Relocs()
+ if rIdx+1 >= relocs.Count() || relocs.At(rIdx+1).Type() != objabi.MachoRelocOffset+ld.MACHO_ARM64_RELOC_UNSIGNED*2 || relocs.At(rIdx+1).Off() != r.Off() {
+ ldr.Errorf(s, "unexpected ARM64_RELOC_SUBTRACTOR reloc, must be followed by ARM64_RELOC_UNSIGNED at same offset")
+ break
+ }
+ su.SetRelocType(rIdx+1, objabi.R_PCREL)
+ su.SetRelocAdd(rIdx+1, r.Add()+int64(r.Off())+int64(r.Siz())-off)
+ // Remove the other relocation
+ su.SetRelocSiz(rIdx, 0)
+ return true
+
case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_BRANCH26*2 + pcrel:
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_CALLARM64)
@@ -277,6 +299,17 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
su.SetRelocSym(rIdx, syms.GOT)
su.SetRelocAdd(rIdx, int64(ldr.SymGot(targ)))
return true
+
+ case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_POINTER_TO_GOT*2 + pcrel:
+ if targType != sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", ldr.SymName(targ))
+ }
+ ld.AddGotSym(target, ldr, syms, targ, 0)
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_PCREL)
+ su.SetRelocSym(rIdx, syms.GOT)
+ su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz())+int64(ldr.SymGot(targ)))
+ return true
}
// Reread the reloc to incorporate any changes in type above.
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 623acc1ad4..2c861129b5 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1452,7 +1452,9 @@ func (ctxt *Link) hostlink() {
argv = append(argv, "-s")
}
} else if *FlagW {
- argv = append(argv, "-Wl,-S") // suppress debugging symbols
+ if !ctxt.IsAIX() && !ctxt.IsSolaris() { // The AIX and Solaris linkers' -S has different meaning
+ argv = append(argv, "-Wl,-S") // suppress debugging symbols
+ }
}
// On darwin, whether to combine DWARF into executable.
@@ -1770,7 +1772,8 @@ func (ctxt *Link) hostlink() {
}
// Force global symbols to be exported for dlopen, etc.
- if ctxt.IsELF {
+ switch {
+ case ctxt.IsELF:
if ctxt.DynlinkingGo() || ctxt.BuildMode == BuildModeCShared || !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "-Wl,--export-dynamic-symbol=main") {
argv = append(argv, "-rdynamic")
} else {
@@ -1781,10 +1784,16 @@ func (ctxt *Link) hostlink() {
sort.Strings(exports)
argv = append(argv, exports...)
}
- }
- if ctxt.HeadType == objabi.Haix {
+ case ctxt.IsAIX():
fileName := xcoffCreateExportFile(ctxt)
argv = append(argv, "-Wl,-bE:"+fileName)
+ case ctxt.IsWindows() && !slices.Contains(flagExtldflags, wlPrefix+"export-all-symbols"):
+ fileName := peCreateExportFile(ctxt, filepath.Base(outopt))
+ prefix := ""
+ if isMSVC {
+ prefix = "-Wl,-def:"
+ }
+ argv = append(argv, prefix+fileName)
}
const unusedArguments = "-Qunused-arguments"
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index 431dad9d6b..c262634666 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -106,11 +106,13 @@ const (
MACHO_ARM_RELOC_SECTDIFF = 2
MACHO_ARM_RELOC_BR24 = 5
MACHO_ARM64_RELOC_UNSIGNED = 0
+ MACHO_ARM64_RELOC_SUBTRACTOR = 1
MACHO_ARM64_RELOC_BRANCH26 = 2
MACHO_ARM64_RELOC_PAGE21 = 3
MACHO_ARM64_RELOC_PAGEOFF12 = 4
MACHO_ARM64_RELOC_GOT_LOAD_PAGE21 = 5
MACHO_ARM64_RELOC_GOT_LOAD_PAGEOFF12 = 6
+ MACHO_ARM64_RELOC_POINTER_TO_GOT = 7
MACHO_ARM64_RELOC_ADDEND = 10
MACHO_GENERIC_RELOC_VANILLA = 0
MACHO_FAKE_GOTPCREL = 100
diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index 5219a98dd4..0f0650e5e1 100644
--- a/src/cmd/link/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
@@ -8,6 +8,7 @@
package ld
import (
+ "bytes"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
@@ -17,6 +18,8 @@ import (
"fmt"
"internal/buildcfg"
"math"
+ "os"
+ "path/filepath"
"slices"
"sort"
"strconv"
@@ -1748,3 +1751,44 @@ func asmbPe(ctxt *Link) {
pewrite(ctxt)
}
+
+// peCreateExportFile creates a file with exported symbols for Windows .def files.
+// ld will export all symbols, even those not marked for export, unless a .def file is provided.
+func peCreateExportFile(ctxt *Link, libName string) (fname string) {
+ fname = filepath.Join(*flagTmpdir, "export_file.def")
+ var buf bytes.Buffer
+
+ fmt.Fprintf(&buf, "LIBRARY %s\n", libName)
+ buf.WriteString("EXPORTS\n")
+
+ ldr := ctxt.loader
+ var exports []string
+ for s := range ldr.ForAllCgoExportStatic() {
+ extname := ldr.SymExtname(s)
+ if !strings.HasPrefix(extname, "_cgoexp_") {
+ continue
+ }
+ if ldr.IsFileLocal(s) {
+ continue // Only export non-static symbols
+ }
+ // Retrieve the name of the initial symbol
+ // exported by cgo.
+ // The corresponding Go symbol is:
+ // _cgoexp_hashcode_symname.
+ name := strings.SplitN(extname, "_", 4)[3]
+ exports = append(exports, name)
+ }
+ if len(exports) == 0 {
+ // See runtime/cgo/windows.go for details.
+ exports = append(exports, "_cgo_stub_export")
+ }
+ sort.Strings(exports)
+ buf.WriteString(strings.Join(exports, "\n"))
+
+ err := os.WriteFile(fname, buf.Bytes(), 0666)
+ if err != nil {
+ Errorf("WriteFile %s failed: %v", fname, err)
+ }
+
+ return fname
+}
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 759262286d..2c999ccc4e 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -645,7 +645,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
sliceSym(pcln.funcnametab)
// The cutab slice
- sliceSym(pcln.cutab)
+ slice(pcln.cutab, uint64(ldr.SymSize(pcln.cutab))/4)
// The filetab slice
sliceSym(pcln.filetab)
@@ -654,7 +654,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
sliceSym(pcln.pctab)
// The pclntab slice
- slice(pcln.pclntab, uint64(ldr.SymSize(pcln.pclntab)))
+ sliceSym(pcln.pclntab)
// The ftab slice
slice(pcln.pclntab, uint64(pcln.nfunc+1))
diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go
index 1bce2cf9b6..da728e2545 100644
--- a/src/cmd/link/internal/ld/xcoff.go
+++ b/src/cmd/link/internal/ld/xcoff.go
@@ -1779,10 +1779,7 @@ func xcoffCreateExportFile(ctxt *Link) (fname string) {
var buf bytes.Buffer
ldr := ctxt.loader
- for s, nsym := loader.Sym(1), loader.Sym(ldr.NSym()); s < nsym; s++ {
- if !ldr.AttrCgoExport(s) {
- continue
- }
+ for s := range ldr.ForAllCgoExportStatic() {
extname := ldr.SymExtname(s)
if !strings.HasPrefix(extname, "._cgoexp_") {
continue
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index 9f3ea3e553..0ed20d1bec 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -16,6 +16,7 @@ import (
"fmt"
"internal/abi"
"io"
+ "iter"
"log"
"math/bits"
"os"
@@ -1109,6 +1110,18 @@ func (l *Loader) SetAttrCgoExportStatic(i Sym, v bool) {
}
}
+// ForAllCgoExportStatic returns an iterator over all symbols
+// marked with the "cgo_export_static" compiler directive.
+func (l *Loader) ForAllCgoExportStatic() iter.Seq[Sym] {
+ return func(yield func(Sym) bool) {
+ for s := range l.attrCgoExportStatic {
+ if !yield(s) {
+ break
+ }
+ }
+ }
+}
+
// IsGeneratedSym returns true if a symbol's been previously marked as a
// generator symbol through the SetIsGeneratedSym. The functions for generator
// symbols are kept in the Link context.
@@ -2437,6 +2450,9 @@ var blockedLinknames = map[string][]string{
"sync_test.runtime_blockUntilEmptyCleanupQueue": {"sync_test"},
"time.runtimeIsBubbled": {"time"},
"unique.runtime_blockUntilEmptyCleanupQueue": {"unique"},
+ // Experimental features
+ "runtime.goroutineLeakGC": {"runtime/pprof"},
+ "runtime.goroutineleakcount": {"runtime/pprof"},
// Others
"net.newWindowsFile": {"net"}, // pushed from os
"testing/synctest.testingSynctestTest": {"testing/synctest"}, // pushed from testing