From 2c9d5a47ca33eb69d40bc81a8c93aa97e18cc785 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 22 Dec 2020 21:20:09 +0100 Subject: build: update to go 1.16 beta1 Signed-off-by: Jason A. Donenfeld --- ...d-link-recognize-arm-header-of-PE-objects.patch | 32 - ...ow-builtin-write-function-to-be-redirecte.patch | 59 + ...al-with-ADDR32NB-relocations-the-same-way.patch | 31 - ...cmd-link-handle-grouped-resource-sections.patch | 339 ++++++ ...cmd-link-ignore-SEH-marking-on-PE-objects.patch | 47 - ...-do-not-mark-resource-section-as-writable.patch | 30 - ...cmd-link-handle-grouped-resource-sections.patch | 317 ----- ...ase-branch.go1.15-runtime-detect-services.patch | 135 --- ...me-do-not-explicitly-exit-on-ctrl-handler.patch | 49 - ...ow-callback-functions-with-up-to-8-argume.patch | 60 - ...-CreateWaitableTimerEx-to-implement-uslee.patch | 419 ------- ...ow-for-usleep2HighRes-to-run-without-TLS-.patch | 91 -- ...windows-arm-is-all-pie-so-mark-it-as-such.patch | 44 - ...ust-address-calculation-in-identifying-ab.patch | 44 - ...le-do-not-assume-TST-and-TEQ-set-V-on-arm.patch | 1275 -------------------- ...-runtime-make-write-into-function-pointer.patch | 32 - 16 files changed, 398 insertions(+), 2606 deletions(-) delete mode 100644 go-patches/0001-cmd-link-recognize-arm-header-of-PE-objects.patch create mode 100644 go-patches/0001-runtime-allow-builtin-write-function-to-be-redirecte.patch delete mode 100644 go-patches/0002-cmd-link-deal-with-ADDR32NB-relocations-the-same-way.patch create mode 100644 go-patches/0002-cmd-link-handle-grouped-resource-sections.patch delete mode 100644 go-patches/0003-cmd-link-ignore-SEH-marking-on-PE-objects.patch delete mode 100644 go-patches/0004-cmd-link-do-not-mark-resource-section-as-writable.patch delete mode 100644 go-patches/0005-cmd-link-handle-grouped-resource-sections.patch delete mode 100644 go-patches/0006-Revert-release-branch.go1.15-runtime-detect-services.patch delete mode 100644 go-patches/0007-runtime-do-not-explicitly-exit-on-ctrl-handler.patch delete mode 100644 go-patches/0008-runtime-allow-callback-functions-with-up-to-8-argume.patch delete mode 100644 go-patches/0009-runtime-use-CreateWaitableTimerEx-to-implement-uslee.patch delete mode 100644 go-patches/0010-runtime-allow-for-usleep2HighRes-to-run-without-TLS-.patch delete mode 100644 go-patches/0011-cmd-link-windows-arm-is-all-pie-so-mark-it-as-such.patch delete mode 100644 go-patches/0012-runtime-adjust-address-calculation-in-identifying-ab.patch delete mode 100644 go-patches/0013-cmd-compile-do-not-assume-TST-and-TEQ-set-V-on-arm.patch delete mode 100644 go-patches/0014-runtime-make-write-into-function-pointer.patch (limited to 'go-patches') diff --git a/go-patches/0001-cmd-link-recognize-arm-header-of-PE-objects.patch b/go-patches/0001-cmd-link-recognize-arm-header-of-PE-objects.patch deleted file mode 100644 index 19fdd04a..00000000 --- a/go-patches/0001-cmd-link-recognize-arm-header-of-PE-objects.patch +++ /dev/null @@ -1,32 +0,0 @@ -From fde4a13eb5eba28ac546b10752b38a80f389cc5a Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Sun, 8 Nov 2020 02:48:09 +0100 -Subject: [PATCH 01/14] cmd/link: recognize arm header of PE objects - -The linker recognizes headers for 386 and amd64 PE objects, but not arm -objects. This is easily overlooked, since its the same as the 386 header -value, except the two nibbles of the first word are swapped. This commit -simply adds the check for this. Without it, .syso objects are rejected, -which means Windows binaries can't have resources built into them. - -Change-Id: I210411d978504c1a9540e23abc5a180e24f159ad ---- - src/cmd/link/internal/ld/lib.go | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go -index 0366bc7a6f..f98668a7dc 100644 ---- a/src/cmd/link/internal/ld/lib.go -+++ b/src/cmd/link/internal/ld/lib.go -@@ -1893,7 +1893,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, - return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file) - } - -- if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 { -+ if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 || c1 == 0xc4 && c2 == 0x01 { - ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { - textp, rsrc, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.Syms.IncVersion(), f, pkg, length, pn) - if err != nil { --- -2.29.2 - diff --git a/go-patches/0001-runtime-allow-builtin-write-function-to-be-redirecte.patch b/go-patches/0001-runtime-allow-builtin-write-function-to-be-redirecte.patch new file mode 100644 index 00000000..a22ec91f --- /dev/null +++ b/go-patches/0001-runtime-allow-builtin-write-function-to-be-redirecte.patch @@ -0,0 +1,59 @@ +From 293b84bef3f6656a263248ff00c9d2fb82f4168d Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Thu, 3 Dec 2020 13:29:58 +0100 +Subject: [PATCH 1/2] runtime: allow builtin write function to be redirected + with function pointer + +The x/sys/windows package currently uses go:linkname for other facilities +inside of runtime that are not suitable to be exposed as a public API +due to their dangers but are still necessary for manipulating any +low-level plumbing that the runtime controls. + +Logging, via the built-in println and panic handler, is one such +low-level plumbing feature. In this case, x/sys/windows/svc needs to be +able to redirect panics to the Windows event log. Because the event log +is a complicated interface, this requires a bit more fiddling than the +simple solution used on Android (baking it into runtime itself), and +because Windows services are very diverse, the event log might not even +always be a desirable destination. + +This commit accomplishes this by exposing a function pointer called +"overrideWrite" that low-level runtime packages like x/sys/windows/svc +can use to redirect output logs toward the event log or otherwise. + +It is not safe or acceptable to use as a generic mechanism, and for that +reason, we wouldn't want to expose this as a real stable API, similar to +the other instances of go:linkname in x/sys/windows. But for packages +that must interoperate with low-level Go runtime fundamentals, this is a +safety hatch for packages that are developed in tandem with the runtime. +x/sys/windows is one such package. + +Fixes #42888. + +Change-Id: I77a32ff7e1494324e8cc38e792e007f86d32672d +--- + src/runtime/time_nofake.go | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/runtime/time_nofake.go b/src/runtime/time_nofake.go +index 1912a94e87..0564448b2e 100644 +--- a/src/runtime/time_nofake.go ++++ b/src/runtime/time_nofake.go +@@ -23,9 +23,14 @@ func walltime() (sec int64, nsec int32) { + return walltime1() + } + ++var overrideWrite func(fd uintptr, p unsafe.Pointer, n int32) int32 ++ + // write must be nosplit on Windows (see write1) + // + //go:nosplit + func write(fd uintptr, p unsafe.Pointer, n int32) int32 { ++ if overrideWrite != nil { ++ return overrideWrite(fd, noescape(p), n) ++ } + return write1(fd, p, n) + } +-- +2.29.2 + diff --git a/go-patches/0002-cmd-link-deal-with-ADDR32NB-relocations-the-same-way.patch b/go-patches/0002-cmd-link-deal-with-ADDR32NB-relocations-the-same-way.patch deleted file mode 100644 index e260ccd8..00000000 --- a/go-patches/0002-cmd-link-deal-with-ADDR32NB-relocations-the-same-way.patch +++ /dev/null @@ -1,31 +0,0 @@ -From a0a59fc25f4d8aef3c7bce38c84f04c504745f0e Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Sun, 8 Nov 2020 03:09:42 +0100 -Subject: [PATCH 02/14] cmd/link: deal with ADDR32NB relocations the same way - as ADDR32 on arm - -As far as I can tell, the addend is the same for both of these, and in -this context we don't really care about setting or unsetting the thumb -selection bit, so just treat these the same way. - -Change-Id: I3756c027239f77778c32b317733df9ac92272580 ---- - src/cmd/link/internal/loadpe/ldpe.go | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/cmd/link/internal/loadpe/ldpe.go b/src/cmd/link/internal/loadpe/ldpe.go -index cf76741f43..5839a6a5f2 100644 ---- a/src/cmd/link/internal/loadpe/ldpe.go -+++ b/src/cmd/link/internal/loadpe/ldpe.go -@@ -308,7 +308,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - - rAdd = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rOff:]))) - -- case IMAGE_REL_ARM_ADDR32: -+ case IMAGE_REL_ARM_ADDR32, IMAGE_REL_ARM_ADDR32NB: - rType = objabi.R_ADDR - - rAdd = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rOff:]))) --- -2.29.2 - diff --git a/go-patches/0002-cmd-link-handle-grouped-resource-sections.patch b/go-patches/0002-cmd-link-handle-grouped-resource-sections.patch new file mode 100644 index 00000000..85fbc3e9 --- /dev/null +++ b/go-patches/0002-cmd-link-handle-grouped-resource-sections.patch @@ -0,0 +1,339 @@ +From f7465aae6e0e8bc4c90c3b8386f5a2a574a15de0 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Sun, 8 Nov 2020 11:57:42 +0100 +Subject: [PATCH 2/2] cmd/link: handle grouped resource sections + +The Go PE linker does not support enough generalized PE logic to +properly handle .rsrc sections gracefully. Instead a few things are +special cased for these. The linker also does not support PE's "grouped +sections" features, in which input objects have several named sections +that are sorted, merged, and renamed in the output file. In the past, +more sophisticated support for resources or for PE features like grouped +sections have not been necessary, as Go's own object formats are pretty +vanilla, and GNU binutils also produces pretty vanilla objects where all +sections are already merged. + +However, GNU binutils is lagging with arm support, and here LLVM has +picked up the slack. In particular, LLVM has its own rc/cvtres combo, +which are glued together in mingw LLVM distributions as windres, a +command line compatible tool with binutils' windres, which supports arm +and arm64. But there's a key difference between binutils' windres and +LLVM's windres: the LLVM one uses proper grouped sections. + +So, this commit adds grouped sections support for resource sections to +the linker. We don't attempt to plumb generic support for grouped +sections, just as there isn't generic support already for what resources +require. Instead we augment the resource handling logic to deal with +standard two-section resource objects. + +We also add a test for this, akin to the current test for more vanilla +binutils resource objects, and make sure that the rsrc tests are always +performed. + +Fixes #42866. +Fixes #43182. + +Change-Id: I059450021405cdf2ef1c195ddbab3960764ad711 +Reviewed-on: https://go-review.googlesource.com/c/go/+/268337 +Run-TryBot: Jason A. Donenfeld +TryBot-Result: Go Bot +Reviewed-by: Cherry Zhang +Trust: Alex Brainman +Trust: Jason A. Donenfeld +--- + src/cmd/link/internal/ld/lib.go | 2 +- + src/cmd/link/internal/ld/pe.go | 60 ++++++++++-------- + src/cmd/link/internal/loadpe/ldpe.go | 49 +++++++------- + src/cmd/link/link_test.go | 19 ++++++ + .../link/testdata/testPErsrc-complex/main.go | 43 +++++++++++++ + .../testdata/testPErsrc-complex/rsrc.syso | Bin 0 -> 352 bytes + 6 files changed, 124 insertions(+), 49 deletions(-) + create mode 100644 src/cmd/link/testdata/testPErsrc-complex/main.go + create mode 100644 src/cmd/link/testdata/testPErsrc-complex/rsrc.syso + +diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go +index f3c301cc9b..9c2231a34e 100644 +--- a/src/cmd/link/internal/ld/lib.go ++++ b/src/cmd/link/internal/ld/lib.go +@@ -1808,7 +1808,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, + Errorf(nil, "%v", err) + return + } +- if rsrc != 0 { ++ if len(rsrc) != 0 { + setpersrc(ctxt, rsrc) + } + ctxt.Textp = append(ctxt.Textp, textp...) +diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go +index adbf516d5c..5edaf54dd2 100644 +--- a/src/cmd/link/internal/ld/pe.go ++++ b/src/cmd/link/internal/ld/pe.go +@@ -253,7 +253,7 @@ type Dll struct { + } + + var ( +- rsrcsym loader.Sym ++ rsrcsyms []loader.Sym + PESECTHEADR int32 + PEFILEHEADR int32 + pe64 int +@@ -1508,46 +1508,56 @@ func (ctxt *Link) dope() { + initdynexport(ctxt) + } + +-func setpersrc(ctxt *Link, sym loader.Sym) { +- if rsrcsym != 0 { ++func setpersrc(ctxt *Link, syms []loader.Sym) { ++ if len(rsrcsyms) != 0 { + Errorf(nil, "too many .rsrc sections") + } +- +- rsrcsym = sym ++ rsrcsyms = syms + } + + func addpersrc(ctxt *Link) { +- if rsrcsym == 0 { ++ if len(rsrcsyms) == 0 { + return + } + +- data := ctxt.loader.Data(rsrcsym) +- size := len(data) +- h := pefile.addSection(".rsrc", size, size) ++ var size int64 ++ for _, rsrcsym := range rsrcsyms { ++ size += ctxt.loader.SymSize(rsrcsym) ++ } ++ h := pefile.addSection(".rsrc", int(size), int(size)) + h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA + h.checkOffset(ctxt.Out.Offset()) + +- // relocation +- relocs := ctxt.loader.Relocs(rsrcsym) +- for i := 0; i < relocs.Count(); i++ { +- r := relocs.At(i) +- p := data[r.Off():] +- val := uint32(int64(h.virtualAddress) + r.Add()) +- +- // 32-bit little-endian +- p[0] = byte(val) +- +- p[1] = byte(val >> 8) +- p[2] = byte(val >> 16) +- p[3] = byte(val >> 24) ++ for _, rsrcsym := range rsrcsyms { ++ // A split resource happens when the actual resource data and its relocations are ++ // split across multiple sections, denoted by a $01 or $02 at the end of the .rsrc ++ // section name. ++ splitResources := strings.Contains(ctxt.loader.SymName(rsrcsym), ".rsrc$") ++ relocs := ctxt.loader.Relocs(rsrcsym) ++ data := ctxt.loader.Data(rsrcsym) ++ for ri := 0; ri < relocs.Count(); ri++ { ++ r := relocs.At(ri) ++ p := data[r.Off():] ++ val := uint32(int64(h.virtualAddress) + r.Add()) ++ if splitResources { ++ // If we're a split resource section, and that section has relocation ++ // symbols, then the data that it points to doesn't actually begin at ++ // the virtual address listed in this current section, but rather ++ // begins at the section immediately after this one. So, in order to ++ // calculate the proper virtual address of the data it's pointing to, ++ // we have to add the length of this section to the virtual address. ++ // This works because .rsrc sections are divided into two (but not more) ++ // of these sections. ++ val += uint32(len(data)) ++ } ++ binary.LittleEndian.PutUint32(p, val) ++ } ++ ctxt.Out.Write(data) + } +- +- ctxt.Out.Write(data) + h.pad(ctxt.Out, uint32(size)) + + // update data directory + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress +- + pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize + } + +diff --git a/src/cmd/link/internal/loadpe/ldpe.go b/src/cmd/link/internal/loadpe/ldpe.go +index 1e6f978531..a5c025de8f 100644 +--- a/src/cmd/link/internal/loadpe/ldpe.go ++++ b/src/cmd/link/internal/loadpe/ldpe.go +@@ -157,8 +157,9 @@ func makeUpdater(l *loader.Loader, bld *loader.SymbolBuilder, s loader.Sym) *loa + + // Load loads the PE file pn from input. + // Symbols are written into syms, and a slice of the text symbols is returned. +-// If an .rsrc section is found, its symbol is returned as rsrc. +-func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, rsrc loader.Sym, err error) { ++// If an .rsrc section or set of .rsrc$xx sections is found, its symbols are ++// returned as rsrc. ++func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, rsrc []loader.Sym, err error) { + lookup := func(name string, version int) (*loader.SymbolBuilder, loader.Sym) { + s := l.LookupOrCreateSym(name, version) + sb := l.MakeSymbolUpdater(s) +@@ -176,7 +177,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + // TODO: replace pe.NewFile with pe.Load (grep for "add Load function" in debug/pe for details) + f, err := pe.NewFile(sr) + if err != nil { +- return nil, 0, err ++ return nil, nil, err + } + defer f.Close() + +@@ -211,21 +212,21 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + bld.SetType(sym.STEXT) + + default: +- return nil, 0, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name) ++ return nil, nil, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name) + } + + if bld.Type() != sym.SNOPTRBSS { + data, err := sect.Data() + if err != nil { +- return nil, 0, err ++ return nil, nil, err + } + sectdata[sect] = data + bld.SetData(data) + } + bld.SetSize(int64(sect.Size)) + sectsyms[sect] = s +- if sect.Name == ".rsrc" { +- rsrc = s ++ if sect.Name == ".rsrc" || strings.HasPrefix(sect.Name, ".rsrc$") { ++ rsrc = append(rsrc, s) + } + } + +@@ -246,22 +247,23 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + continue + } + ++ splitResources := strings.HasPrefix(rsect.Name, ".rsrc$") + sb := l.MakeSymbolUpdater(sectsyms[rsect]) + for j, r := range rsect.Relocs { + if int(r.SymbolTableIndex) >= len(f.COFFSymbols) { +- return nil, 0, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols)) ++ return nil, nil, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols)) + } + pesym := &f.COFFSymbols[r.SymbolTableIndex] + _, gosym, err := readpesym(l, arch, l.LookupOrCreateSym, f, pesym, sectsyms, localSymVersion) + if err != nil { +- return nil, 0, err ++ return nil, nil, err + } + if gosym == 0 { + name, err := pesym.FullName(f.StringTable) + if err != nil { + name = string(pesym.Name[:]) + } +- return nil, 0, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type) ++ return nil, nil, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type) + } + + rSym := gosym +@@ -271,11 +273,11 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + var rType objabi.RelocType + switch arch.Family { + default: +- return nil, 0, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family) ++ return nil, nil, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family) + case sys.I386, sys.AMD64: + switch r.Type { + default: +- return nil, 0, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type) ++ return nil, nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type) + + case IMAGE_REL_I386_REL32, IMAGE_REL_AMD64_REL32, + IMAGE_REL_AMD64_ADDR32, // R_X86_64_PC32 +@@ -302,7 +304,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + case sys.ARM: + switch r.Type { + default: +- return nil, 0, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type) ++ return nil, nil, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type) + + case IMAGE_REL_ARM_SECREL: + rType = objabi.R_PCREL +@@ -323,8 +325,9 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + + // ld -r could generate multiple section symbols for the + // same section but with different values, we have to take +- // that into account +- if issect(pesym) { ++ // that into account, or in the case of split resources, ++ // the section and its symbols are split into two sections. ++ if issect(pesym) || splitResources { + rAdd += int64(pesym.Value) + } + +@@ -346,7 +349,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + + name, err := pesym.FullName(f.StringTable) + if err != nil { +- return nil, 0, err ++ return nil, nil, err + } + if name == "" { + continue +@@ -384,7 +387,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + + bld, s, err := readpesym(l, arch, l.LookupOrCreateSym, f, pesym, sectsyms, localSymVersion) + if err != nil { +- return nil, 0, err ++ return nil, nil, err + } + + if pesym.SectionNumber == 0 { // extern +@@ -402,14 +405,14 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + } else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) { + sect = f.Sections[pesym.SectionNumber-1] + if _, found := sectsyms[sect]; !found { +- return nil, 0, fmt.Errorf("%s: %v: missing sect.sym", pn, s) ++ return nil, nil, fmt.Errorf("%s: %v: missing sect.sym", pn, s) + } + } else { +- return nil, 0, fmt.Errorf("%s: %v: sectnum < 0!", pn, s) ++ return nil, nil, fmt.Errorf("%s: %v: sectnum < 0!", pn, s) + } + + if sect == nil { +- return nil, 0, nil ++ return nil, nil, nil + } + + if l.OuterSym(s) != 0 { +@@ -418,7 +421,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + } + outerName := l.SymName(l.OuterSym(s)) + sectName := l.SymName(sectsyms[sect]) +- return nil, 0, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName) ++ return nil, nil, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName) + } + + bld = makeUpdater(l, bld, s) +@@ -429,7 +432,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + bld.SetSize(4) + if l.SymType(sectsym) == sym.STEXT { + if bld.External() && !bld.DuplicateOK() { +- return nil, 0, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s)) ++ return nil, nil, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s)) + } + bld.SetExternal(true) + } +@@ -446,7 +449,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read + if l.SymType(s) == sym.STEXT { + for ; s != 0; s = l.SubSym(s) { + if l.AttrOnList(s) { +- return nil, 0, fmt.Errorf("symbol %s listed multiple times", l.SymName(s)) ++ return nil, nil, fmt.Errorf("symbol %s listed multiple times", l.SymName(s)) + } + l.SetAttrOnList(s, true) + textp = append(textp, s) +-- +2.29.2 + diff --git a/go-patches/0003-cmd-link-ignore-SEH-marking-on-PE-objects.patch b/go-patches/0003-cmd-link-ignore-SEH-marking-on-PE-objects.patch deleted file mode 100644 index e5c86f88..00000000 --- a/go-patches/0003-cmd-link-ignore-SEH-marking-on-PE-objects.patch +++ /dev/null @@ -1,47 +0,0 @@ -From e8142ab5e3b3a513683a8e3792e6197644547981 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Sun, 8 Nov 2020 03:20:36 +0100 -Subject: [PATCH 03/14] cmd/link: ignore SEH marking on PE objects - -Microsoft's linker looks at whether all input objects have an empty -section called @feat.00. If all of them do, then it enables SEH; -otherwise it doesn't enable that feature. So, since around the Windows -XP SP2 era, most tools that make PE objects just tack on that section, -so that it won't gimp Microsoft's linker logic. Go doesn't support SEH, -so in theory, none of this really matters to us. But actually, if the -linker tries to ingest an object with @feat.00 -- which are produced by -LLVM's resource compiler, for example -- it chokes because of the -IMAGE_SYM_ABSOLUTE section that it doesn't know how to deal with. Since -@feat.00 is just a marking anyway, skip IMAGE_SYM_ABSOLUTE sections that -are called @feat.00. - -Change-Id: I1d7bfcf6001186c53e2c487c5ac251ca65efefee ---- - src/cmd/link/internal/loadpe/ldpe.go | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/cmd/link/internal/loadpe/ldpe.go b/src/cmd/link/internal/loadpe/ldpe.go -index 5839a6a5f2..b60b84ce9f 100644 ---- a/src/cmd/link/internal/loadpe/ldpe.go -+++ b/src/cmd/link/internal/loadpe/ldpe.go -@@ -6,6 +6,7 @@ - package loadpe - - import ( -+ "bytes" - "cmd/internal/bio" - "cmd/internal/objabi" - "cmd/internal/sys" -@@ -359,6 +360,9 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - if pesym.SectionNumber == IMAGE_SYM_DEBUG { - continue - } -+ if pesym.SectionNumber == IMAGE_SYM_ABSOLUTE && bytes.Equal(pesym.Name[:], []byte("@feat.00")) { -+ continue -+ } - var sect *pe.Section - if pesym.SectionNumber > 0 { - sect = f.Sections[pesym.SectionNumber-1] --- -2.29.2 - diff --git a/go-patches/0004-cmd-link-do-not-mark-resource-section-as-writable.patch b/go-patches/0004-cmd-link-do-not-mark-resource-section-as-writable.patch deleted file mode 100644 index 1d9cb434..00000000 --- a/go-patches/0004-cmd-link-do-not-mark-resource-section-as-writable.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 8255e115f325a58fd4746741f9f35c2f54d70d63 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Sun, 8 Nov 2020 11:11:27 +0100 -Subject: [PATCH 04/14] cmd/link: do not mark resource section as writable - -Resources are immutable, and all other linkers set this section to be -read-only and not read-write. Fix this oversight by rmoving the writable -flag. - -Change-Id: Ib441bde6620be2000f1685df1ea7bfaebdbe7860 ---- - src/cmd/link/internal/ld/pe.go | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go -index c9cb25dbe5..ec5b6d5f52 100644 ---- a/src/cmd/link/internal/ld/pe.go -+++ b/src/cmd/link/internal/ld/pe.go -@@ -1482,7 +1482,7 @@ func addpersrc(ctxt *Link) { - data := rsrc.P - size := len(data) - h := pefile.addSection(".rsrc", size, size) -- h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA -+ h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA - h.checkOffset(ctxt.Out.Offset()) - - // relocation --- -2.29.2 - diff --git a/go-patches/0005-cmd-link-handle-grouped-resource-sections.patch b/go-patches/0005-cmd-link-handle-grouped-resource-sections.patch deleted file mode 100644 index 02af61a2..00000000 --- a/go-patches/0005-cmd-link-handle-grouped-resource-sections.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 5d5d74f35dd3375cda8ef2ba8257547aad107ecb Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Sun, 8 Nov 2020 11:57:42 +0100 -Subject: [PATCH 05/14] cmd/link: handle grouped resource sections - -The Go PE linker does not support enough generalized PE logic to -properly handle .rsrc sections gracefully. Instead a few things are -special cased for these. The linker also does not support PE's "grouped -sections" features, in which input objects have several named sections -that are sorted, merged, and renamed in the output file. In the past, -more sophisticated support for resources or for PE features like grouped -sections have not been necessary, as Go's own object formats are pretty -vanilla, and GNU binutils also produces pretty vanilla objects where all -sections are already merged. - -However, GNU binutils is lagging with arm support, and here LLVM has -picked up the slack. In particular, LLVM has its own rc/cvtres combo, -which are glued together in mingw LLVM distributions as windres, a -command line compatible tool with binutils' windres, which supports arm -and arm64. But there's a key difference between binutils' windres and -LLVM's windres: the LLVM one uses proper grouped sections. - -So, this commit adds grouped sections support for resource sections to -the linker. We don't attempt to plumb generic support for grouped -sections, just as there isn't generic support already for what resources -require. Instead we augment the resource handling logic to deal with -standard two-section resource objects. - -Change-Id: I059450021405cdf2ef1c195ddbab3960764ad711 ---- - src/cmd/link/internal/ld/lib.go | 2 +- - src/cmd/link/internal/ld/pe.go | 50 ++++++++++++++-------------- - src/cmd/link/internal/loadpe/ldpe.go | 47 ++++++++++++++------------ - 3 files changed, 52 insertions(+), 47 deletions(-) - -diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go -index f98668a7dc..f09b5910b9 100644 ---- a/src/cmd/link/internal/ld/lib.go -+++ b/src/cmd/link/internal/ld/lib.go -@@ -1900,7 +1900,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, - Errorf(nil, "%v", err) - return - } -- if rsrc != 0 { -+ if rsrc != nil { - setpersrc(ctxt, rsrc) - } - ctxt.Textp2 = append(ctxt.Textp2, textp...) -diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go -index ec5b6d5f52..29094fe8ed 100644 ---- a/src/cmd/link/internal/ld/pe.go -+++ b/src/cmd/link/internal/ld/pe.go -@@ -253,7 +253,7 @@ type Dll struct { - } - - var ( -- rsrcsym loader.Sym -+ rsrcsyms []loader.Sym - PESECTHEADR int32 - PEFILEHEADR int32 - pe64 int -@@ -1464,47 +1464,47 @@ func (ctxt *Link) dope() { - initdynexport(ctxt) - } - --func setpersrc(ctxt *Link, sym loader.Sym) { -- if rsrcsym != 0 { -+func setpersrc(ctxt *Link, syms []loader.Sym) { -+ if rsrcsyms != nil { - Errorf(nil, "too many .rsrc sections") - } -- -- rsrcsym = sym -- ctxt.loader.SetAttrReachable(rsrcsym, true) -+ rsrcsyms = syms -+ for i := range rsrcsyms { -+ ctxt.loader.SetAttrReachable(rsrcsyms[i], true) -+ } - } - - func addpersrc(ctxt *Link) { -- if rsrcsym == 0 { -+ if rsrcsyms == nil { - return - } - -- rsrc := ctxt.loader.Syms[rsrcsym] -- data := rsrc.P -- size := len(data) -+ var size int -+ for i := range rsrcsyms { -+ size += len(ctxt.loader.Syms[rsrcsyms[i]].P) -+ } - h := pefile.addSection(".rsrc", size, size) - h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA - h.checkOffset(ctxt.Out.Offset()) - -- // relocation -- for ri := range rsrc.R { -- r := &rsrc.R[ri] -- p := data[r.Off:] -- val := uint32(int64(h.virtualAddress) + r.Add) -- -- // 32-bit little-endian -- p[0] = byte(val) -- -- p[1] = byte(val >> 8) -- p[2] = byte(val >> 16) -- p[3] = byte(val >> 24) -+ for i := range rsrcsyms { -+ rsrc := ctxt.loader.Syms[rsrcsyms[i]] -+ splitResources := strings.Contains(rsrc.Name, ".rsrc$") -+ for ri := range rsrc.R { -+ r := &rsrc.R[ri] -+ p := rsrc.P[r.Off:] -+ val := uint32(int64(h.virtualAddress) + r.Add) -+ if splitResources { -+ val += uint32(len(rsrc.P)) -+ } -+ binary.LittleEndian.PutUint32(p, val) -+ } -+ ctxt.Out.Write(rsrc.P) - } -- -- ctxt.Out.Write(data) - h.pad(ctxt.Out, uint32(size)) - - // update data directory - pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress -- - pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize - } - -diff --git a/src/cmd/link/internal/loadpe/ldpe.go b/src/cmd/link/internal/loadpe/ldpe.go -index b60b84ce9f..08832ba552 100644 ---- a/src/cmd/link/internal/loadpe/ldpe.go -+++ b/src/cmd/link/internal/loadpe/ldpe.go -@@ -158,7 +158,7 @@ func makeUpdater(l *loader.Loader, bld *loader.SymbolBuilder, s loader.Sym) *loa - // Load loads the PE file pn from input. - // Symbols are written into syms, and a slice of the text symbols is returned. - // If an .rsrc section is found, its symbol is returned as rsrc. --func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, rsrc loader.Sym, err error) { -+func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, rsrc []loader.Sym, err error) { - lookup := func(name string, version int) (*loader.SymbolBuilder, loader.Sym) { - s := l.LookupOrCreateSym(name, version) - sb := l.MakeSymbolUpdater(s) -@@ -176,7 +176,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - // TODO: replace pe.NewFile with pe.Load (grep for "add Load function" in debug/pe for details) - f, err := pe.NewFile(sr) - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - defer f.Close() - -@@ -211,21 +211,21 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - bld.SetType(sym.STEXT) - - default: -- return nil, 0, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name) -+ return nil, nil, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name) - } - - if bld.Type() != sym.SNOPTRBSS { - data, err := sect.Data() - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - sectdata[sect] = data - bld.SetData(data) - } - bld.SetSize(int64(sect.Size)) - sectsyms[sect] = s -- if sect.Name == ".rsrc" { -- rsrc = s -+ if sect.Name == ".rsrc" || strings.HasPrefix(sect.Name, ".rsrc$") { -+ rsrc = append(rsrc, s) - } - } - -@@ -246,22 +246,23 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - continue - } - -+ splitResources := strings.HasPrefix(rsect.Name, ".rsrc$") - sb := l.MakeSymbolUpdater(sectsyms[rsect]) - for j, r := range rsect.Relocs { - if int(r.SymbolTableIndex) >= len(f.COFFSymbols) { -- return nil, 0, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols)) -+ return nil, nil, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols)) - } - pesym := &f.COFFSymbols[r.SymbolTableIndex] - _, gosym, err := readpesym(l, arch, l.LookupOrCreateSym, f, pesym, sectsyms, localSymVersion) - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - if gosym == 0 { - name, err := pesym.FullName(f.StringTable) - if err != nil { - name = string(pesym.Name[:]) - } -- return nil, 0, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type) -+ return nil, nil, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type) - } - - rSym := gosym -@@ -271,11 +272,11 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - var rType objabi.RelocType - switch arch.Family { - default: -- return nil, 0, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family) -+ return nil, nil, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family) - case sys.I386, sys.AMD64: - switch r.Type { - default: -- return nil, 0, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type) -+ return nil, nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type) - - case IMAGE_REL_I386_REL32, IMAGE_REL_AMD64_REL32, - IMAGE_REL_AMD64_ADDR32, // R_X86_64_PC32 -@@ -302,7 +303,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - case sys.ARM: - switch r.Type { - default: -- return nil, 0, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type) -+ return nil, nil, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type) - - case IMAGE_REL_ARM_SECREL: - rType = objabi.R_PCREL -@@ -324,7 +325,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - // ld -r could generate multiple section symbols for the - // same section but with different values, we have to take - // that into account -- if issect(pesym) { -+ if issect(pesym) || splitResources { - rAdd += int64(pesym.Value) - } - -@@ -333,6 +334,10 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - rel.SetSiz(rSize) - rel.SetSym(rSym) - rel.SetAdd(rAdd) -+ -+ if splitResources { -+ l.SetAttrReachable(rSym, true) -+ } - } - - sb.SortRelocs() -@@ -346,7 +351,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - - name, err := pesym.FullName(f.StringTable) - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - if name == "" { - continue -@@ -373,7 +378,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - - bld, s, err := readpesym(l, arch, l.LookupOrCreateSym, f, pesym, sectsyms, localSymVersion) - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - - if pesym.SectionNumber == 0 { // extern -@@ -391,14 +396,14 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - } else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) { - sect = f.Sections[pesym.SectionNumber-1] - if _, found := sectsyms[sect]; !found { -- return nil, 0, fmt.Errorf("%s: %v: missing sect.sym", pn, s) -+ return nil, nil, fmt.Errorf("%s: %v: missing sect.sym", pn, s) - } - } else { -- return nil, 0, fmt.Errorf("%s: %v: sectnum < 0!", pn, s) -+ return nil, nil, fmt.Errorf("%s: %v: sectnum < 0!", pn, s) - } - - if sect == nil { -- return nil, 0, nil -+ return nil, nil, nil - } - - if l.OuterSym(s) != 0 { -@@ -407,7 +412,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - } - outerName := l.SymName(l.OuterSym(s)) - sectName := l.SymName(sectsyms[sect]) -- return nil, 0, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName) -+ return nil, nil, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName) - } - - bld = makeUpdater(l, bld, s) -@@ -418,7 +423,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - bld.SetSize(4) - if l.SymType(sectsym) == sym.STEXT { - if bld.External() && !bld.DuplicateOK() { -- return nil, 0, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s)) -+ return nil, nil, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s)) - } - bld.SetExternal(true) - } -@@ -435,7 +440,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - if l.SymType(s) == sym.STEXT { - for ; s != 0; s = l.SubSym(s) { - if l.AttrOnList(s) { -- return nil, 0, fmt.Errorf("symbol %s listed multiple times", l.SymName(s)) -+ return nil, nil, fmt.Errorf("symbol %s listed multiple times", l.SymName(s)) - } - l.SetAttrOnList(s, true) - textp = append(textp, s) --- -2.29.2 - diff --git a/go-patches/0006-Revert-release-branch.go1.15-runtime-detect-services.patch b/go-patches/0006-Revert-release-branch.go1.15-runtime-detect-services.patch deleted file mode 100644 index cb21af9f..00000000 --- a/go-patches/0006-Revert-release-branch.go1.15-runtime-detect-services.patch +++ /dev/null @@ -1,135 +0,0 @@ -From e6b4c1b3beb4f843ed40abead27c8132d29a0db8 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Fri, 11 Sep 2020 13:04:11 +0200 -Subject: [PATCH 06/14] Revert "[release-branch.go1.15] runtime: detect - services in signal handler" - -This reverts commit b1253d24e159129c778377c3a2a0bde15904a417. ---- - src/runtime/os_windows.go | 73 +++------------------------------------ - 1 file changed, 4 insertions(+), 69 deletions(-) - -diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go -index 769197db46..a584ada702 100644 ---- a/src/runtime/os_windows.go -+++ b/src/runtime/os_windows.go -@@ -36,10 +36,7 @@ const ( - //go:cgo_import_dynamic runtime._SetThreadContext SetThreadContext%2 "kernel32.dll" - //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll" - //go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll" --//go:cgo_import_dynamic runtime._OpenProcess OpenProcess%3 "kernel32.dll" - //go:cgo_import_dynamic runtime._PostQueuedCompletionStatus PostQueuedCompletionStatus%4 "kernel32.dll" --//go:cgo_import_dynamic runtime._ProcessIdToSessionId ProcessIdToSessionId%2 "kernel32.dll" --//go:cgo_import_dynamic runtime._QueryFullProcessImageNameA QueryFullProcessImageNameA%4 "kernel32.dll" - //go:cgo_import_dynamic runtime._ResumeThread ResumeThread%1 "kernel32.dll" - //go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler%2 "kernel32.dll" - //go:cgo_import_dynamic runtime._SetErrorMode SetErrorMode%1 "kernel32.dll" -@@ -87,10 +84,7 @@ var ( - _SetThreadContext, - _LoadLibraryW, - _LoadLibraryA, -- _OpenProcess, - _PostQueuedCompletionStatus, -- _ProcessIdToSessionId, -- _QueryFullProcessImageNameA, - _QueryPerformanceCounter, - _QueryPerformanceFrequency, - _ResumeThread, -@@ -134,8 +128,7 @@ var ( - // Load ntdll.dll manually during startup, otherwise Mingw - // links wrong printf function to cgo executable (see issue - // 12030 for details). -- _NtWaitForSingleObject stdFunction -- _NtQueryInformationProcess stdFunction -+ _NtWaitForSingleObject stdFunction - - // These are from non-kernel32.dll, so we prefer to LoadLibraryEx them. - _timeBeginPeriod, -@@ -262,7 +255,6 @@ func loadOptionalSyscalls() { - throw("ntdll.dll not found") - } - _NtWaitForSingleObject = windowsFindfunc(n32, []byte("NtWaitForSingleObject\000")) -- _NtQueryInformationProcess = windowsFindfunc(n32, []byte("NtQueryInformationProcess\000")) - - if GOARCH == "arm" { - _QueryPerformanceCounter = windowsFindfunc(k32, []byte("QueryPerformanceCounter\000")) -@@ -1003,63 +995,6 @@ func usleep(us uint32) { - onosstack(usleep2Addr, 10*us) - } - --// isWindowsService returns whether the process is currently executing as a --// Windows service. The below technique looks a bit hairy, but it's actually --// exactly what the .NET framework does for the similarly named function: --// https://github.com/dotnet/extensions/blob/f4066026ca06984b07e90e61a6390ac38152ba93/src/Hosting/WindowsServices/src/WindowsServiceHelpers.cs#L26-L31 --// Specifically, it looks up whether the parent process has session ID zero --// and is called "services". --func isWindowsService() bool { -- const ( -- _CURRENT_PROCESS = ^uintptr(0) -- _PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 -- ) -- // pbi is a PROCESS_BASIC_INFORMATION struct, where we just care about -- // the 6th pointer inside of it, which contains the pid of the process -- // parent: -- // https://github.com/wine-mirror/wine/blob/42cb7d2ad1caba08de235e6319b9967296b5d554/include/winternl.h#L1294 -- var pbi [6]uintptr -- var pbiLen uint32 -- err := stdcall5(_NtQueryInformationProcess, _CURRENT_PROCESS, 0, uintptr(unsafe.Pointer(&pbi[0])), uintptr(unsafe.Sizeof(pbi)), uintptr(unsafe.Pointer(&pbiLen))) -- if err != 0 { -- return false -- } -- var psid uint32 -- err = stdcall2(_ProcessIdToSessionId, pbi[5], uintptr(unsafe.Pointer(&psid))) -- if err == 0 || psid != 0 { -- return false -- } -- pproc := stdcall3(_OpenProcess, _PROCESS_QUERY_LIMITED_INFORMATION, 0, pbi[5]) -- if pproc == 0 { -- return false -- } -- defer stdcall1(_CloseHandle, pproc) -- // exeName gets the path to the executable image of the parent process -- var exeName [261]byte -- exeNameLen := uint32(len(exeName) - 1) -- err = stdcall4(_QueryFullProcessImageNameA, pproc, 0, uintptr(unsafe.Pointer(&exeName[0])), uintptr(unsafe.Pointer(&exeNameLen))) -- if err == 0 || exeNameLen == 0 { -- return false -- } -- servicesLower := "services.exe" -- servicesUpper := "SERVICES.EXE" -- i := int(exeNameLen) - 1 -- j := len(servicesLower) - 1 -- if i < j { -- return false -- } -- for { -- if j == -1 { -- return i == -1 || exeName[i] == '\\' -- } -- if exeName[i] != servicesLower[j] && exeName[i] != servicesUpper[j] { -- return false -- } -- i-- -- j-- -- } --} -- - func ctrlhandler1(_type uint32) uint32 { - var s uint32 - -@@ -1075,9 +1010,9 @@ func ctrlhandler1(_type uint32) uint32 { - if sigsend(s) { - return 1 - } -- if !islibrary && !isarchive && !isWindowsService() { -- // Only exit the program if we don't have a DLL or service. -- // See https://golang.org/issues/35965 and https://golang.org/issues/40167 -+ if !islibrary && !isarchive { -+ // Only exit the program if we don't have a DLL. -+ // See https://golang.org/issues/35965. - exit(2) // SIGINT, SIGTERM, etc - } - return 0 --- -2.29.2 - diff --git a/go-patches/0007-runtime-do-not-explicitly-exit-on-ctrl-handler.patch b/go-patches/0007-runtime-do-not-explicitly-exit-on-ctrl-handler.patch deleted file mode 100644 index 4db19853..00000000 --- a/go-patches/0007-runtime-do-not-explicitly-exit-on-ctrl-handler.patch +++ /dev/null @@ -1,49 +0,0 @@ -From af4eb34d920c0c727041ebf587e0de608068ed59 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Tue, 14 Jul 2020 01:41:03 -0600 -Subject: [PATCH 07/14] runtime: do not explicitly exit on ctrl handler - -The default ctrl+c handler should process exits in situations where it -makes sense, like console apps, but not in situations where it doesn't, -like libraries or services. Therefore, we should remove the exit(2) so -that the default handler is used for this. This also uses the more -proper windows exit code of STATUS_CONTROL_C_EXIT, with the base case -handler installed by KernelBase.dll. In particular, this helps in the -case of services, which previously would terminate when receiving -shutdown signals, instead of passing them onward to the service program. -In this CL, contrary to CL 244959, we do not need to special case -services with expensive detection algorithms, or rely on hard-coded -library/archive flags. - -Fixes #40167. -Fixes #40074. - -Change-Id: I9bf6ed6f65cefeff754d270aa33fa4df8d0b451f -Reviewed-on: https://go-review.googlesource.com/c/go/+/243597 -Run-TryBot: Jason A. Donenfeld -TryBot-Result: Gobot Gobot -Reviewed-by: Alex Brainman -Reviewed-by: Jason A. Donenfeld ---- - src/runtime/os_windows.go | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go -index a584ada702..a62e941229 100644 ---- a/src/runtime/os_windows.go -+++ b/src/runtime/os_windows.go -@@ -1010,11 +1010,6 @@ func ctrlhandler1(_type uint32) uint32 { - if sigsend(s) { - return 1 - } -- if !islibrary && !isarchive { -- // Only exit the program if we don't have a DLL. -- // See https://golang.org/issues/35965. -- exit(2) // SIGINT, SIGTERM, etc -- } - return 0 - } - --- -2.29.2 - diff --git a/go-patches/0008-runtime-allow-callback-functions-with-up-to-8-argume.patch b/go-patches/0008-runtime-allow-callback-functions-with-up-to-8-argume.patch deleted file mode 100644 index 0af97ce2..00000000 --- a/go-patches/0008-runtime-allow-callback-functions-with-up-to-8-argume.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 5a7c808cbacb8c0477395c5656c1eba3ef38cd6e Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Tue, 10 Nov 2020 21:42:36 +0100 -Subject: [PATCH 08/14] runtime: allow callback functions with up to 8 - arguments on windows/arm - -Previously, windows/arm programs would abort when trying to use -functions that took callbacks with more than 4 arguments. This caused -issues when using SetWinEventHook, which receives 7 arguments. Add 4 -more by pulling them off the stack. - -Change-Id: I15a6a3168237fd8bb1128cc2c11ff2d900d665d2 ---- - src/runtime/sys_windows_arm.s | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/src/runtime/sys_windows_arm.s b/src/runtime/sys_windows_arm.s -index 256b5ff7f0..049c69ec88 100644 ---- a/src/runtime/sys_windows_arm.s -+++ b/src/runtime/sys_windows_arm.s -@@ -315,10 +315,14 @@ GLOBL runtime·cbctxts(SB), NOPTR, $4 - - TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0 - MOVM.DB.W [R4-R11, R14], (R13) // push {r4-r11, lr} -- SUB $36, R13 // space for locals -+ SUB $52, R13 // space for locals - -- // save callback arguments to stack. We currently support up to 4 arguments -+ // save callback arguments to stack. We currently support up to 8 arguments - ADD $16, R13, R4 -+ MOVM.IA.W [R0-R3], (R4) -+ // the remaining 4 arguments are on the stack -+ ADD $88, R13, R5 -+ MOVM.IA (R5), [R0-R3] - MOVM.IA [R0-R3], (R4) - - // load cbctxts[i]. The trampoline in zcallback_windows.s puts the callback -@@ -330,8 +334,8 @@ TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0 - MOVW wincallbackcontext_argsize(R4), R5 - MOVW wincallbackcontext_gobody(R4), R4 - -- // we currently support up to 4 arguments -- CMP $(4 * 4), R5 -+ // we currently support up to 8 arguments -+ CMP $(4 * 8), R5 - BL.GT runtime·abort(SB) - - // extend argsize by size of return value -@@ -351,7 +355,7 @@ TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0 - SUB $4, R1 // offset to return value - MOVW R1<<0(R0), R0 // load return value - -- ADD $36, R13 // free locals -+ ADD $52, R13 // free locals - MOVM.IA.W (R13), [R4-R11, R15] // pop {r4-r11, pc} - - // uint32 tstart_stdcall(M *newm); --- -2.29.2 - diff --git a/go-patches/0009-runtime-use-CreateWaitableTimerEx-to-implement-uslee.patch b/go-patches/0009-runtime-use-CreateWaitableTimerEx-to-implement-uslee.patch deleted file mode 100644 index 83647c59..00000000 --- a/go-patches/0009-runtime-use-CreateWaitableTimerEx-to-implement-uslee.patch +++ /dev/null @@ -1,419 +0,0 @@ -From 1a163f2e676e4664f2db3f614eb4168bda9d4fd8 Mon Sep 17 00:00:00 2001 -From: Alex Brainman -Date: Sun, 19 Jul 2020 16:06:48 +1000 -Subject: [PATCH 09/14] runtime: use CreateWaitableTimerEx to implement usleep -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -@jstarks suggested that recent versions of Windows provide access to high resolution timers. See - -https://github.com/golang/go/issues/8687#issuecomment-656259353 - -for details. - -I tried to run this C program on my Windows 10 computer - -``` - #include - #include - - #pragma comment(lib, "Winmm.lib") - -// Apparently this is already defined when I use msvc cl. -//#define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION = 0x00000002; - -int usleep(HANDLE timer, LONGLONG d) { - LARGE_INTEGER liDueTime; - DWORD ret; - LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds; - LARGE_INTEGER Frequency; - - QueryPerformanceFrequency(&Frequency); - QueryPerformanceCounter(&StartingTime); - - liDueTime.QuadPart = d; - liDueTime.QuadPart = liDueTime.QuadPart * 10; // us into 100 of ns units - liDueTime.QuadPart = -liDueTime.QuadPart; // negative for relative dure time - - if (!SetWaitableTimer(timer, &liDueTime, 0, NULL, NULL, 0)) { - printf("SetWaitableTimer failed: errno=%d\n", GetLastError()); - return 1; - } - - ret = WaitForSingleObject(timer, INFINITE); - if (ret != WAIT_OBJECT_0) { - printf("WaitForSingleObject failed: ret=%d errno=%d\n", ret, GetLastError()); - return 1; - } - - QueryPerformanceCounter(&EndingTime); - ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart; - ElapsedMicroseconds.QuadPart *= 1000000; - ElapsedMicroseconds.QuadPart /= Frequency.QuadPart; - - printf("delay is %lld us - slept for %lld us\n", d, ElapsedMicroseconds.QuadPart); - - return 0; -} - -int testTimer(DWORD createFlag) -{ - HANDLE timer; - - timer = CreateWaitableTimerEx(NULL, NULL, createFlag, TIMER_ALL_ACCESS); - if (timer == NULL) { - printf("CreateWaitableTimerEx failed: errno=%d\n", GetLastError()); - return 1; - } - - usleep(timer, 1000LL); - usleep(timer, 100LL); - usleep(timer, 10LL); - usleep(timer, 1LL); - - CloseHandle(timer); - - return 0; -} - -int main() -{ - printf("\n1. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is off - timeBeginPeriod is off\n"); - testTimer(0); - - printf("\n2. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is on - timeBeginPeriod is off\n"); - testTimer(CREATE_WAITABLE_TIMER_HIGH_RESOLUTION); - - timeBeginPeriod(1); - - printf("\n3. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is off - timeBeginPeriod is on\n"); - testTimer(0); - - printf("\n4. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is on - timeBeginPeriod is on\n"); - testTimer(CREATE_WAITABLE_TIMER_HIGH_RESOLUTION); -} -``` - -and I see this output - -``` -1. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is off - timeBeginPeriod is off -delay is 1000 us - slept for 4045 us -delay is 100 us - slept for 3915 us -delay is 10 us - slept for 3291 us -delay is 1 us - slept for 2234 us - -2. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is on - timeBeginPeriod is off -delay is 1000 us - slept for 1076 us -delay is 100 us - slept for 569 us -delay is 10 us - slept for 585 us -delay is 1 us - slept for 17 us - -3. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is off - timeBeginPeriod is on -delay is 1000 us - slept for 742 us -delay is 100 us - slept for 893 us -delay is 10 us - slept for 414 us -delay is 1 us - slept for 920 us - -4. CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is on - timeBeginPeriod is on -delay is 1000 us - slept for 1466 us -delay is 100 us - slept for 559 us -delay is 10 us - slept for 535 us -delay is 1 us - slept for 5 us -``` - -That shows, that indeed using CREATE_WAITABLE_TIMER_HIGH_RESOLUTION -will provide sleeps as low as about 500 microseconds, while our -current approach provides about 1 millisecond sleep. - -New approach also does not require for timeBeginPeriod to be on, -so this change solves long standing problem with go programs draining -laptop battery, because it calls timeBeginPeriod. - -This change will only run on systems where -CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag is available. If not -available, the runtime will fallback to original code that uses -timeBeginPeriod. - -This is how this change affects benchmark reported in issue #14790 - -name               old time/op  new time/op  delta -ChanToSyscallPing  1.05ms ± 2%  0.68ms ±11%  -35.43%  (p=0.000 n=10+10) - -The benchmark was run with GOMAXPROCS set to 1. - -Fixes #8687 -Updates #14790 - -Change-Id: I5b97ba58289c088c17c05292e12e45285c467eae -Reviewed-on: https://go-review.googlesource.com/c/go/+/248699 -Run-TryBot: Alex Brainman -TryBot-Result: Go Bot -Trust: Alex Brainman -Reviewed-by: Austin Clements ---- - src/runtime/os_windows.go | 73 ++++++++++++++++++++++++++++++++- - src/runtime/sys_windows_386.s | 36 ++++++++++++++++ - src/runtime/sys_windows_amd64.s | 32 +++++++++++++++ - src/runtime/sys_windows_arm.s | 5 +++ - 4 files changed, 144 insertions(+), 2 deletions(-) - -diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go -index a62e941229..9dd140c952 100644 ---- a/src/runtime/os_windows.go -+++ b/src/runtime/os_windows.go -@@ -21,6 +21,7 @@ const ( - //go:cgo_import_dynamic runtime._CreateIoCompletionPort CreateIoCompletionPort%4 "kernel32.dll" - //go:cgo_import_dynamic runtime._CreateThread CreateThread%6 "kernel32.dll" - //go:cgo_import_dynamic runtime._CreateWaitableTimerA CreateWaitableTimerA%3 "kernel32.dll" -+//go:cgo_import_dynamic runtime._CreateWaitableTimerExW CreateWaitableTimerExW%4 "kernel32.dll" - //go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle%7 "kernel32.dll" - //go:cgo_import_dynamic runtime._ExitProcess ExitProcess%1 "kernel32.dll" - //go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW%1 "kernel32.dll" -@@ -68,6 +69,7 @@ var ( - _CreateIoCompletionPort, - _CreateThread, - _CreateWaitableTimerA, -+ _CreateWaitableTimerExW, - _DuplicateHandle, - _ExitProcess, - _FreeEnvironmentStringsW, -@@ -151,6 +153,8 @@ type mOS struct { - waitsema uintptr // semaphore for parking on locks - resumesema uintptr // semaphore to indicate suspend/resume - -+ highResTimer uintptr // high resolution timer handle used in usleep -+ - // preemptExtLock synchronizes preemptM with entry/exit from - // external C code. - // -@@ -402,11 +406,21 @@ const osRelaxMinNS = 60 * 1e6 - // osRelax is called by the scheduler when transitioning to and from - // all Ps being idle. - // --// On Windows, it adjusts the system-wide timer resolution. Go needs a -+// Some versions of Windows have high resolution timer. For those -+// versions osRelax is noop. -+// For Windows versions without high resolution timer, osRelax -+// adjusts the system-wide timer resolution. Go needs a - // high resolution timer while running and there's little extra cost - // if we're already using the CPU, but if all Ps are idle there's no - // need to consume extra power to drive the high-res timer. - func osRelax(relax bool) uint32 { -+ if haveHighResTimer { -+ // If the high resolution timer is available, the runtime uses the timer -+ // to sleep for short durations. This means there's no need to adjust -+ // the global clock frequency. -+ return 0 -+ } -+ - if relax { - return uint32(stdcall1(_timeEndPeriod, 1)) - } else { -@@ -414,6 +428,42 @@ func osRelax(relax bool) uint32 { - } - } - -+// haveHighResTimer indicates that the CreateWaitableTimerEx -+// CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag is available. -+var haveHighResTimer = false -+ -+// createHighResTimer calls CreateWaitableTimerEx with -+// CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag to create high -+// resolution timer. createHighResTimer returns new timer -+// handle or 0, if CreateWaitableTimerEx failed. -+func createHighResTimer() uintptr { -+ const ( -+ // As per @jstarks, see -+ // https://github.com/golang/go/issues/8687#issuecomment-656259353 -+ _CREATE_WAITABLE_TIMER_HIGH_RESOLUTION = 0x00000002 -+ -+ _SYNCHRONIZE = 0x00100000 -+ _TIMER_QUERY_STATE = 0x0001 -+ _TIMER_MODIFY_STATE = 0x0002 -+ ) -+ return stdcall4(_CreateWaitableTimerExW, 0, 0, -+ _CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, -+ _SYNCHRONIZE|_TIMER_QUERY_STATE|_TIMER_MODIFY_STATE) -+} -+ -+func initHighResTimer() { -+ if GOARCH == "arm" { -+ // TODO: Not yet implemented. -+ return -+ } -+ h := createHighResTimer() -+ if h != 0 { -+ haveHighResTimer = true -+ usleep2Addr = unsafe.Pointer(funcPC(usleep2HighRes)) -+ stdcall1(_CloseHandle, h) -+ } -+} -+ - func osinit() { - asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall)) - usleep2Addr = unsafe.Pointer(funcPC(usleep2)) -@@ -429,6 +479,7 @@ func osinit() { - - stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1) - -+ initHighResTimer() - timeBeginPeriodRetValue = osRelax(false) - - ncpu = getproccount() -@@ -844,9 +895,20 @@ func minit() { - var thandle uintptr - stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS) - -+ // Configure usleep timer, if possible. -+ var timer uintptr -+ if haveHighResTimer { -+ timer = createHighResTimer() -+ if timer == 0 { -+ print("runtime: CreateWaitableTimerEx failed; errno=", getlasterror(), "\n") -+ throw("CreateWaitableTimerEx when creating timer failed") -+ } -+ } -+ - mp := getg().m - lock(&mp.threadLock) - mp.thread = thandle -+ mp.highResTimer = timer - unlock(&mp.threadLock) - - // Query the true stack base from the OS. Currently we're -@@ -884,6 +946,10 @@ func unminit() { - lock(&mp.threadLock) - stdcall1(_CloseHandle, mp.thread) - mp.thread = 0 -+ if mp.highResTimer != 0 { -+ stdcall1(_CloseHandle, mp.highResTimer) -+ mp.highResTimer = 0 -+ } - unlock(&mp.threadLock) - } - -@@ -976,9 +1042,12 @@ func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr { - return stdcall(fn) - } - --// in sys_windows_386.s and sys_windows_amd64.s -+// In sys_windows_386.s and sys_windows_amd64.s. - func onosstack(fn unsafe.Pointer, arg uint32) -+ -+// These are not callable functions. They should only be called via onosstack. - func usleep2(usec uint32) -+func usleep2HighRes(usec uint32) - func switchtothread() - - var usleep2Addr unsafe.Pointer -diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s -index 9e1f40925d..4ac1527ab1 100644 ---- a/src/runtime/sys_windows_386.s -+++ b/src/runtime/sys_windows_386.s -@@ -428,6 +428,42 @@ TEXT runtime·usleep2(SB),NOSPLIT,$20 - MOVL BP, SP - RET - -+// Runs on OS stack. duration (in 100ns units) is in BX. -+TEXT runtime·usleep2HighRes(SB),NOSPLIT,$36 -+ // Want negative 100ns units. -+ NEGL BX -+ MOVL $-1, hi-4(SP) -+ MOVL BX, lo-8(SP) -+ -+ get_tls(CX) -+ MOVL g(CX), CX -+ MOVL g_m(CX), CX -+ MOVL (m_mOS+mOS_highResTimer)(CX), CX -+ MOVL CX, saved_timer-12(SP) -+ -+ MOVL $0, fResume-16(SP) -+ MOVL $0, lpArgToCompletionRoutine-20(SP) -+ MOVL $0, pfnCompletionRoutine-24(SP) -+ MOVL $0, lPeriod-28(SP) -+ LEAL lo-8(SP), BX -+ MOVL BX, lpDueTime-32(SP) -+ MOVL CX, hTimer-36(SP) -+ MOVL SP, BP -+ MOVL runtime·_SetWaitableTimer(SB), AX -+ CALL AX -+ MOVL BP, SP -+ -+ MOVL $0, ptime-28(SP) -+ MOVL $0, alertable-32(SP) -+ MOVL saved_timer-12(SP), CX -+ MOVL CX, handle-36(SP) -+ MOVL SP, BP -+ MOVL runtime·_NtWaitForSingleObject(SB), AX -+ CALL AX -+ MOVL BP, SP -+ -+ RET -+ - // Runs on OS stack. - TEXT runtime·switchtothread(SB),NOSPLIT,$0 - MOVL SP, BP -diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s -index 6c8eecd4e7..847542592b 100644 ---- a/src/runtime/sys_windows_amd64.s -+++ b/src/runtime/sys_windows_amd64.s -@@ -457,6 +457,38 @@ TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$48 - MOVQ 40(SP), SP - RET - -+// Runs on OS stack. duration (in 100ns units) is in BX. -+TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$72 -+ MOVQ SP, AX -+ ANDQ $~15, SP // alignment as per Windows requirement -+ MOVQ AX, 64(SP) -+ -+ get_tls(CX) -+ MOVQ g(CX), CX -+ MOVQ g_m(CX), CX -+ MOVQ (m_mOS+mOS_highResTimer)(CX), CX // hTimer -+ MOVQ CX, 48(SP) // save hTimer for later -+ // Want negative 100ns units. -+ NEGQ BX -+ LEAQ 56(SP), DX // lpDueTime -+ MOVQ BX, (DX) -+ MOVQ $0, R8 // lPeriod -+ MOVQ $0, R9 // pfnCompletionRoutine -+ MOVQ $0, AX -+ MOVQ AX, 32(SP) // lpArgToCompletionRoutine -+ MOVQ AX, 40(SP) // fResume -+ MOVQ runtime·_SetWaitableTimer(SB), AX -+ CALL AX -+ -+ MOVQ 48(SP), CX // handle -+ MOVQ $0, DX // alertable -+ MOVQ $0, R8 // ptime -+ MOVQ runtime·_NtWaitForSingleObject(SB), AX -+ CALL AX -+ -+ MOVQ 64(SP), SP -+ RET -+ - // Runs on OS stack. - TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0 - MOVQ SP, AX -diff --git a/src/runtime/sys_windows_arm.s b/src/runtime/sys_windows_arm.s -index 049c69ec88..eaceca4bc3 100644 ---- a/src/runtime/sys_windows_arm.s -+++ b/src/runtime/sys_windows_arm.s -@@ -472,6 +472,11 @@ TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$0 - MOVW R4, R13 // Restore SP - MOVM.IA.W (R13), [R4, R15] // pop {R4, pc} - -+// Runs on OS stack. Duration (in 100ns units) is in R0. -+// TODO: neeeds to be implemented properly. -+TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$0 -+ B runtime·abort(SB) -+ - // Runs on OS stack. - TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0 - MOVM.DB.W [R4, R14], (R13) // push {R4, lr} --- -2.29.2 - diff --git a/go-patches/0010-runtime-allow-for-usleep2HighRes-to-run-without-TLS-.patch b/go-patches/0010-runtime-allow-for-usleep2HighRes-to-run-without-TLS-.patch deleted file mode 100644 index 1c25f5b6..00000000 --- a/go-patches/0010-runtime-allow-for-usleep2HighRes-to-run-without-TLS-.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 1edac4879e2d4a36d339353c151cb7b9871e135f Mon Sep 17 00:00:00 2001 -From: Alex Brainman -Date: Sat, 21 Nov 2020 14:56:26 +1100 -Subject: [PATCH 10/14] runtime: allow for usleep2HighRes to run without TLS - setup -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This change adjusts usleep2HighRes so it does not crash when TLS is -not configured. When g is not available, usleep2HighRes just calls -usleep2 instead. - -Updates #8687 - -Change-Id: Idbb80f7b71d1da350a6a7df7c49154eb1ffe29a8 ---- - src/runtime/sys_windows_386.s | 11 ++++++++++- - src/runtime/sys_windows_amd64.s | 11 ++++++++++- - 2 files changed, 20 insertions(+), 2 deletions(-) - -diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s -index 4ac1527ab1..310c4008e5 100644 ---- a/src/runtime/sys_windows_386.s -+++ b/src/runtime/sys_windows_386.s -@@ -430,12 +430,15 @@ TEXT runtime·usleep2(SB),NOSPLIT,$20 - - // Runs on OS stack. duration (in 100ns units) is in BX. - TEXT runtime·usleep2HighRes(SB),NOSPLIT,$36 -+ get_tls(CX) -+ CMPL CX, $0 -+ JE gisnotset -+ - // Want negative 100ns units. - NEGL BX - MOVL $-1, hi-4(SP) - MOVL BX, lo-8(SP) - -- get_tls(CX) - MOVL g(CX), CX - MOVL g_m(CX), CX - MOVL (m_mOS+mOS_highResTimer)(CX), CX -@@ -464,6 +467,12 @@ TEXT runtime·usleep2HighRes(SB),NOSPLIT,$36 - - RET - -+gisnotset: -+ // TLS is not configured. Call usleep2 instead. -+ MOVL $runtime·usleep2(SB), AX -+ CALL AX -+ RET -+ - // Runs on OS stack. - TEXT runtime·switchtothread(SB),NOSPLIT,$0 - MOVL SP, BP -diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s -index 847542592b..699a6e6ff2 100644 ---- a/src/runtime/sys_windows_amd64.s -+++ b/src/runtime/sys_windows_amd64.s -@@ -459,11 +459,14 @@ TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$48 - - // Runs on OS stack. duration (in 100ns units) is in BX. - TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$72 -+ get_tls(CX) -+ CMPQ CX, $0 -+ JE gisnotset -+ - MOVQ SP, AX - ANDQ $~15, SP // alignment as per Windows requirement - MOVQ AX, 64(SP) - -- get_tls(CX) - MOVQ g(CX), CX - MOVQ g_m(CX), CX - MOVQ (m_mOS+mOS_highResTimer)(CX), CX // hTimer -@@ -489,6 +492,12 @@ TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$72 - MOVQ 64(SP), SP - RET - -+gisnotset: -+ // TLS is not configured. Call usleep2 instead. -+ MOVQ $runtime·usleep2(SB), AX -+ CALL AX -+ RET -+ - // Runs on OS stack. - TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0 - MOVQ SP, AX --- -2.29.2 - diff --git a/go-patches/0011-cmd-link-windows-arm-is-all-pie-so-mark-it-as-such.patch b/go-patches/0011-cmd-link-windows-arm-is-all-pie-so-mark-it-as-such.patch deleted file mode 100644 index a2984678..00000000 --- a/go-patches/0011-cmd-link-windows-arm-is-all-pie-so-mark-it-as-such.patch +++ /dev/null @@ -1,44 +0,0 @@ -From fee7906e1a7e62b655bea0f25c921572ee29fc44 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Thu, 26 Nov 2020 22:38:45 +0100 -Subject: [PATCH 11/14] cmd/link: windows/arm is all pie, so mark it as such - -If the linker thinks that it's making an exe instead of a pie object, it -won't apply relocations to the pclntab and we wind up with crashes like: - - Building Go toolchain2 using go_bootstrap and Go toolchain1. - fatal error: minpc or maxpc invalid - runtime: panic before malloc heap initialized - -This problem was already solved by darwin/arm64, so solve it the same -way here for windows/arm. - -Fixes CL 228478. -Updates #42786. - -Change-Id: I6d1db6907c131183649fc263ccca06783188f344 ---- - src/cmd/link/internal/ld/config.go | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go -index 2373b500e3..83a8698289 100644 ---- a/src/cmd/link/internal/ld/config.go -+++ b/src/cmd/link/internal/ld/config.go -@@ -35,7 +35,12 @@ func (mode *BuildMode) Set(s string) error { - default: - return fmt.Errorf("invalid buildmode: %q", s) - case "exe": -- *mode = BuildModeExe -+ switch objabi.GOOS + "/" + objabi.GOARCH { -+ case "windows/arm": // On these platforms, everything is PIE -+ *mode = BuildModePIE -+ default: -+ *mode = BuildModeExe -+ } - case "pie": - switch objabi.GOOS { - case "aix", "android", "linux", "windows": --- -2.29.2 - diff --git a/go-patches/0012-runtime-adjust-address-calculation-in-identifying-ab.patch b/go-patches/0012-runtime-adjust-address-calculation-in-identifying-ab.patch deleted file mode 100644 index 38fcbb9b..00000000 --- a/go-patches/0012-runtime-adjust-address-calculation-in-identifying-ab.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 8ec41fee1e6ef074ef74e56fe079c70c8a1d0548 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Fri, 27 Nov 2020 22:07:23 +0100 -Subject: [PATCH 12/14] runtime: adjust address calculation in identifying - abort on windows/arm - -Apparently we're being called on arm 1 byte off, just like on 386 and -amd64, so unify the handler for isAbortPC. - -Fixes #42859. -Updates #29050. - -Change-Id: I97fffeb4a33d93ca3397ce1c9ba2b05137f391ca ---- - src/runtime/signal_windows.go | 13 +++---------- - 1 file changed, 3 insertions(+), 10 deletions(-) - -diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go -index d123276d3e..8db24fb805 100644 ---- a/src/runtime/signal_windows.go -+++ b/src/runtime/signal_windows.go -@@ -43,16 +43,9 @@ func initExceptionHandler() { - // - //go:nosplit - func isAbort(r *context) bool { -- switch GOARCH { -- case "386", "amd64": -- // In the case of an abort, the exception IP is one byte after -- // the INT3 (this differs from UNIX OSes). -- return isAbortPC(r.ip() - 1) -- case "arm": -- return isAbortPC(r.ip()) -- default: -- return false -- } -+ // In the case of an abort, the exception IP is one byte after -+ // the INT3 (this differs from UNIX OSes). -+ return isAbortPC(r.ip() - 1) - } - - // isgoexception reports whether this exception should be translated --- -2.29.2 - diff --git a/go-patches/0013-cmd-compile-do-not-assume-TST-and-TEQ-set-V-on-arm.patch b/go-patches/0013-cmd-compile-do-not-assume-TST-and-TEQ-set-V-on-arm.patch deleted file mode 100644 index a8eb403d..00000000 --- a/go-patches/0013-cmd-compile-do-not-assume-TST-and-TEQ-set-V-on-arm.patch +++ /dev/null @@ -1,1275 +0,0 @@ -From 58e426bb8175959d7bf32ea7c87e51f4706b309b Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Mon, 30 Nov 2020 10:41:46 +0100 -Subject: [PATCH 13/14] cmd/compile: do not assume TST and TEQ set V on arm - -These replacement rules assume that TST and TEQ set V. But TST and -TEQ do not set V. This is a problem because instructions like LT are -actually checking for N!=V. But with TST and TEQ not setting V, LT -doesn't do anything meaningful. It's possible to construct trivial -miscompilations from this, such as: - - package main - - var x = [4]int32{-0x7fffffff, 0x7fffffff, 2, 4} - - func main() { - if x[0] > x[1] { - panic("fail 1") - } - if x[2]&x[3] < 0 { - panic("fail 2") // Fails here - } - } - -That first comparison sets V, via the CMP that subtracts the values -causing the overflow. Then the second comparison operation thinks that -it uses the result of TST, when it actually uses the V from CMP. - -Before this fix: - - TST R0, R1 - BLT loc_6C164 - -After this fix: - - TST R0, R1 - BMI loc_6C164 - -The BMI instruction checks the N flag, which TST sets. This commit -fixes the issue by using [LG][TE]noov instead of vanilla [LG][TE], and -also adds a test case for the direct issue. - -Fixes #42876. - -Change-Id: I13c62c88d18574247ad002b671b38d2d0b0fc6fa -Reviewed-on: https://go-review.googlesource.com/c/go/+/274026 -Run-TryBot: Jason A. Donenfeld -TryBot-Result: Go Bot -Reviewed-by: Cherry Zhang -Trust: Jason A. Donenfeld ---- - src/cmd/compile/internal/ssa/gen/ARM.rules | 128 ++++----- - src/cmd/compile/internal/ssa/rewriteARM.go | 306 ++++++++++----------- - test/fixedbugs/issue42876.go | 18 ++ - 3 files changed, 235 insertions(+), 217 deletions(-) - create mode 100644 test/fixedbugs/issue42876.go - -diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules -index ab8bd0e81e..c69084a701 100644 ---- a/src/cmd/compile/internal/ssa/gen/ARM.rules -+++ b/src/cmd/compile/internal/ssa/gen/ARM.rules -@@ -1369,38 +1369,38 @@ - (LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLLreg x y z) yes no) - (LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRLreg x y z) yes no) - (LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRAreg x y z) yes no) --(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LT (TST x y) yes no) --(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LT (TSTconst [c] x) yes no) --(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftLL x y [c]) yes no) --(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftRL x y [c]) yes no) --(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftRA x y [c]) yes no) --(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (TSTshiftLLreg x y z) yes no) --(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (TSTshiftRLreg x y z) yes no) --(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (TSTshiftRAreg x y z) yes no) --(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LE (TST x y) yes no) --(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LE (TSTconst [c] x) yes no) --(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (TSTshiftLL x y [c]) yes no) --(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (TSTshiftRL x y [c]) yes no) --(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (TSTshiftRA x y [c]) yes no) --(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TSTshiftLLreg x y z) yes no) --(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TSTshiftRLreg x y z) yes no) --(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TSTshiftRAreg x y z) yes no) --(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LT (TEQ x y) yes no) --(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (LT (TEQconst [c] x) yes no) --(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TEQshiftLL x y [c]) yes no) --(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (TEQshiftRL x y [c]) yes no) --(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (TEQshiftRA x y [c]) yes no) --(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (TEQshiftLLreg x y z) yes no) --(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (TEQshiftRLreg x y z) yes no) --(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (TEQshiftRAreg x y z) yes no) --(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LE (TEQ x y) yes no) --(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (LE (TEQconst [c] x) yes no) --(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (TEQshiftLL x y [c]) yes no) --(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (TEQshiftRL x y [c]) yes no) --(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (TEQshiftRA x y [c]) yes no) --(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftLLreg x y z) yes no) --(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRLreg x y z) yes no) --(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRAreg x y z) yes no) -+(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LTnoov (TST x y) yes no) -+(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (TSTconst [c] x) yes no) -+(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (TSTshiftLL x y [c]) yes no) -+(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (TSTshiftRL x y [c]) yes no) -+(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (TSTshiftRA x y [c]) yes no) -+(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TSTshiftLLreg x y z) yes no) -+(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TSTshiftRLreg x y z) yes no) -+(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TSTshiftRAreg x y z) yes no) -+(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LEnoov (TST x y) yes no) -+(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (TSTconst [c] x) yes no) -+(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (TSTshiftLL x y [c]) yes no) -+(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (TSTshiftRL x y [c]) yes no) -+(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (TSTshiftRA x y [c]) yes no) -+(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TSTshiftLLreg x y z) yes no) -+(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TSTshiftRLreg x y z) yes no) -+(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TSTshiftRAreg x y z) yes no) -+(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LTnoov (TEQ x y) yes no) -+(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (TEQconst [c] x) yes no) -+(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (TEQshiftLL x y [c]) yes no) -+(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (TEQshiftRL x y [c]) yes no) -+(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (TEQshiftRA x y [c]) yes no) -+(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TEQshiftLLreg x y z) yes no) -+(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TEQshiftRLreg x y z) yes no) -+(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (TEQshiftRAreg x y z) yes no) -+(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LEnoov (TEQ x y) yes no) -+(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (TEQconst [c] x) yes no) -+(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (TEQshiftLL x y [c]) yes no) -+(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (TEQshiftRL x y [c]) yes no) -+(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (TEQshiftRA x y [c]) yes no) -+(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TEQshiftLLreg x y z) yes no) -+(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TEQshiftRLreg x y z) yes no) -+(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (TEQshiftRAreg x y z) yes no) - (GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GTnoov (CMP x y) yes no) - (GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GTnoov (CMP a (MUL x y)) yes no) - (GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMPconst [c] x) yes no) -@@ -1436,39 +1436,39 @@ - (GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLLreg x y z) yes no) - (GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRLreg x y z) yes no) - (GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRAreg x y z) yes no) --(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GT (TST x y) yes no) - (GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GTnoov (CMN a (MUL x y)) yes no) --(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GT (TSTconst [c] x) yes no) --(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftLL x y [c]) yes no) --(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRL x y [c]) yes no) --(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRA x y [c]) yes no) --(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (TSTshiftLLreg x y z) yes no) --(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (TSTshiftRLreg x y z) yes no) --(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (TSTshiftRAreg x y z) yes no) --(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GE (TST x y) yes no) --(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GE (TSTconst [c] x) yes no) --(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (TSTshiftLL x y [c]) yes no) --(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (TSTshiftRL x y [c]) yes no) --(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (TSTshiftRA x y [c]) yes no) --(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (TSTshiftLLreg x y z) yes no) --(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (TSTshiftRLreg x y z) yes no) --(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (TSTshiftRAreg x y z) yes no) --(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GT (TEQ x y) yes no) --(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GT (TEQconst [c] x) yes no) --(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TEQshiftLL x y [c]) yes no) --(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TEQshiftRL x y [c]) yes no) --(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (TEQshiftRA x y [c]) yes no) --(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (TEQshiftLLreg x y z) yes no) --(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (TEQshiftRLreg x y z) yes no) --(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (TEQshiftRAreg x y z) yes no) --(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GE (TEQ x y) yes no) --(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GE (TEQconst [c] x) yes no) --(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (TEQshiftLL x y [c]) yes no) --(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (TEQshiftRL x y [c]) yes no) --(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (TEQshiftRA x y [c]) yes no) --(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftLLreg x y z) yes no) --(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftRLreg x y z) yes no) --(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftRAreg x y z) yes no) -+(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GTnoov (TST x y) yes no) -+(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (TSTconst [c] x) yes no) -+(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (TSTshiftLL x y [c]) yes no) -+(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (TSTshiftRL x y [c]) yes no) -+(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (TSTshiftRA x y [c]) yes no) -+(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TSTshiftLLreg x y z) yes no) -+(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TSTshiftRLreg x y z) yes no) -+(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TSTshiftRAreg x y z) yes no) -+(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GEnoov (TST x y) yes no) -+(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (TSTconst [c] x) yes no) -+(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (TSTshiftLL x y [c]) yes no) -+(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (TSTshiftRL x y [c]) yes no) -+(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (TSTshiftRA x y [c]) yes no) -+(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TSTshiftLLreg x y z) yes no) -+(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TSTshiftRLreg x y z) yes no) -+(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TSTshiftRAreg x y z) yes no) -+(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GTnoov (TEQ x y) yes no) -+(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (TEQconst [c] x) yes no) -+(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (TEQshiftLL x y [c]) yes no) -+(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (TEQshiftRL x y [c]) yes no) -+(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (TEQshiftRA x y [c]) yes no) -+(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TEQshiftLLreg x y z) yes no) -+(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TEQshiftRLreg x y z) yes no) -+(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (TEQshiftRAreg x y z) yes no) -+(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GEnoov (TEQ x y) yes no) -+(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (TEQconst [c] x) yes no) -+(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (TEQshiftLL x y [c]) yes no) -+(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (TEQshiftRL x y [c]) yes no) -+(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (TEQshiftRA x y [c]) yes no) -+(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TEQshiftLLreg x y z) yes no) -+(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TEQshiftRLreg x y z) yes no) -+(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (TEQshiftRAreg x y z) yes no) - - (MOVBUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(read8(sym, off))]) - (MOVHUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(read16(sym, off, config.ctxt.Arch.ByteOrder))]) -diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go -index f55e542505..07653b78f8 100644 ---- a/src/cmd/compile/internal/ssa/rewriteARM.go -+++ b/src/cmd/compile/internal/ssa/rewriteARM.go -@@ -17278,7 +17278,7 @@ func rewriteBlockARM(b *Block) bool { - } - // match: (GE (CMPconst [0] l:(AND x y)) yes no) - // cond: l.Uses==1 -- // result: (GE (TST x y) yes no) -+ // result: (GEnoov (TST x y) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17299,14 +17299,14 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - break - } - // match: (GE (CMPconst [0] l:(ANDconst [c] x)) yes no) - // cond: l.Uses==1 -- // result: (GE (TSTconst [c] x) yes no) -+ // result: (GEnoov (TSTconst [c] x) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17324,12 +17324,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) - v0.AuxInt = c - v0.AddArg(x) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GE (TSTshiftLL x y [c]) yes no) -+ // result: (GEnoov (TSTshiftLL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17348,12 +17348,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GE (TSTshiftRL x y [c]) yes no) -+ // result: (GEnoov (TSTshiftRL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17372,12 +17372,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GE (TSTshiftRA x y [c]) yes no) -+ // result: (GEnoov (TSTshiftRA x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17396,12 +17396,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GE (TSTshiftLLreg x y z) yes no) -+ // result: (GEnoov (TSTshiftLLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17419,12 +17419,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GE (TSTshiftRLreg x y z) yes no) -+ // result: (GEnoov (TSTshiftRLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17442,12 +17442,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GE (TSTshiftRAreg x y z) yes no) -+ // result: (GEnoov (TSTshiftRAreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17465,12 +17465,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(XOR x y)) yes no) - // cond: l.Uses==1 -- // result: (GE (TEQ x y) yes no) -+ // result: (GEnoov (TEQ x y) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17491,14 +17491,14 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - break - } - // match: (GE (CMPconst [0] l:(XORconst [c] x)) yes no) - // cond: l.Uses==1 -- // result: (GE (TEQconst [c] x) yes no) -+ // result: (GEnoov (TEQconst [c] x) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17516,12 +17516,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) - v0.AuxInt = c - v0.AddArg(x) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GE (TEQshiftLL x y [c]) yes no) -+ // result: (GEnoov (TEQshiftLL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17540,12 +17540,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GE (TEQshiftRL x y [c]) yes no) -+ // result: (GEnoov (TEQshiftRL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17564,12 +17564,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GE (TEQshiftRA x y [c]) yes no) -+ // result: (GEnoov (TEQshiftRA x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17588,12 +17588,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GE (TEQshiftLLreg x y z) yes no) -+ // result: (GEnoov (TEQshiftLLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17611,12 +17611,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GE (TEQshiftRLreg x y z) yes no) -+ // result: (GEnoov (TEQshiftRLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17634,12 +17634,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - // match: (GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GE (TEQshiftRAreg x y z) yes no) -+ // result: (GEnoov (TEQshiftRAreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -17657,7 +17657,7 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGE, v0) -+ b.resetWithControl(BlockARMGEnoov, v0) - return true - } - case BlockARMGEnoov: -@@ -18131,9 +18131,34 @@ func rewriteBlockARM(b *Block) bool { - b.resetWithControl(BlockARMGTnoov, v0) - return true - } -+ // match: (GT (CMPconst [0] l:(MULA x y a)) yes no) -+ // cond: l.Uses==1 -+ // result: (GTnoov (CMN a (MUL x y)) yes no) -+ for b.Controls[0].Op == OpARMCMPconst { -+ v_0 := b.Controls[0] -+ if v_0.AuxInt != 0 { -+ break -+ } -+ l := v_0.Args[0] -+ if l.Op != OpARMMULA { -+ break -+ } -+ a := l.Args[2] -+ x := l.Args[0] -+ y := l.Args[1] -+ if !(l.Uses == 1) { -+ break -+ } -+ v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) -+ v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) -+ v1.AddArg2(x, y) -+ v0.AddArg2(a, v1) -+ b.resetWithControl(BlockARMGTnoov, v0) -+ return true -+ } - // match: (GT (CMPconst [0] l:(AND x y)) yes no) - // cond: l.Uses==1 -- // result: (GT (TST x y) yes no) -+ // result: (GTnoov (TST x y) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18154,39 +18179,14 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - break - } -- // match: (GT (CMPconst [0] l:(MULA x y a)) yes no) -- // cond: l.Uses==1 -- // result: (GTnoov (CMN a (MUL x y)) yes no) -- for b.Controls[0].Op == OpARMCMPconst { -- v_0 := b.Controls[0] -- if v_0.AuxInt != 0 { -- break -- } -- l := v_0.Args[0] -- if l.Op != OpARMMULA { -- break -- } -- a := l.Args[2] -- x := l.Args[0] -- y := l.Args[1] -- if !(l.Uses == 1) { -- break -- } -- v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags) -- v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type) -- v1.AddArg2(x, y) -- v0.AddArg2(a, v1) -- b.resetWithControl(BlockARMGTnoov, v0) -- return true -- } - // match: (GT (CMPconst [0] l:(ANDconst [c] x)) yes no) - // cond: l.Uses==1 -- // result: (GT (TSTconst [c] x) yes no) -+ // result: (GTnoov (TSTconst [c] x) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18204,12 +18204,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) - v0.AuxInt = c - v0.AddArg(x) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GT (TSTshiftLL x y [c]) yes no) -+ // result: (GTnoov (TSTshiftLL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18228,12 +18228,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GT (TSTshiftRL x y [c]) yes no) -+ // result: (GTnoov (TSTshiftRL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18252,12 +18252,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GT (TSTshiftRA x y [c]) yes no) -+ // result: (GTnoov (TSTshiftRA x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18276,12 +18276,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GT (TSTshiftLLreg x y z) yes no) -+ // result: (GTnoov (TSTshiftLLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18299,12 +18299,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GT (TSTshiftRLreg x y z) yes no) -+ // result: (GTnoov (TSTshiftRLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18322,12 +18322,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GT (TSTshiftRAreg x y z) yes no) -+ // result: (GTnoov (TSTshiftRAreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18345,12 +18345,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(XOR x y)) yes no) - // cond: l.Uses==1 -- // result: (GT (TEQ x y) yes no) -+ // result: (GTnoov (TEQ x y) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18371,14 +18371,14 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - break - } - // match: (GT (CMPconst [0] l:(XORconst [c] x)) yes no) - // cond: l.Uses==1 -- // result: (GT (TEQconst [c] x) yes no) -+ // result: (GTnoov (TEQconst [c] x) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18396,12 +18396,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) - v0.AuxInt = c - v0.AddArg(x) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GT (TEQshiftLL x y [c]) yes no) -+ // result: (GTnoov (TEQshiftLL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18420,12 +18420,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GT (TEQshiftRL x y [c]) yes no) -+ // result: (GTnoov (TEQshiftRL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18444,12 +18444,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) - // cond: l.Uses==1 -- // result: (GT (TEQshiftRA x y [c]) yes no) -+ // result: (GTnoov (TEQshiftRA x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18468,12 +18468,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GT (TEQshiftLLreg x y z) yes no) -+ // result: (GTnoov (TEQshiftLLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18491,12 +18491,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GT (TEQshiftRLreg x y z) yes no) -+ // result: (GTnoov (TEQshiftRLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18514,12 +18514,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - // match: (GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (GT (TEQshiftRAreg x y z) yes no) -+ // result: (GTnoov (TEQshiftRAreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -18537,7 +18537,7 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMGT, v0) -+ b.resetWithControl(BlockARMGTnoov, v0) - return true - } - case BlockARMGTnoov: -@@ -19129,7 +19129,7 @@ func rewriteBlockARM(b *Block) bool { - } - // match: (LE (CMPconst [0] l:(AND x y)) yes no) - // cond: l.Uses==1 -- // result: (LE (TST x y) yes no) -+ // result: (LEnoov (TST x y) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19150,14 +19150,14 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - break - } - // match: (LE (CMPconst [0] l:(ANDconst [c] x)) yes no) - // cond: l.Uses==1 -- // result: (LE (TSTconst [c] x) yes no) -+ // result: (LEnoov (TSTconst [c] x) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19175,12 +19175,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) - v0.AuxInt = c - v0.AddArg(x) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LE (TSTshiftLL x y [c]) yes no) -+ // result: (LEnoov (TSTshiftLL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19199,12 +19199,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LE (TSTshiftRL x y [c]) yes no) -+ // result: (LEnoov (TSTshiftRL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19223,12 +19223,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LE (TSTshiftRA x y [c]) yes no) -+ // result: (LEnoov (TSTshiftRA x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19247,12 +19247,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LE (TSTshiftLLreg x y z) yes no) -+ // result: (LEnoov (TSTshiftLLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19270,12 +19270,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LE (TSTshiftRLreg x y z) yes no) -+ // result: (LEnoov (TSTshiftRLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19293,12 +19293,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LE (TSTshiftRAreg x y z) yes no) -+ // result: (LEnoov (TSTshiftRAreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19316,12 +19316,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(XOR x y)) yes no) - // cond: l.Uses==1 -- // result: (LE (TEQ x y) yes no) -+ // result: (LEnoov (TEQ x y) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19342,14 +19342,14 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - break - } - // match: (LE (CMPconst [0] l:(XORconst [c] x)) yes no) - // cond: l.Uses==1 -- // result: (LE (TEQconst [c] x) yes no) -+ // result: (LEnoov (TEQconst [c] x) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19367,12 +19367,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) - v0.AuxInt = c - v0.AddArg(x) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LE (TEQshiftLL x y [c]) yes no) -+ // result: (LEnoov (TEQshiftLL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19391,12 +19391,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LE (TEQshiftRL x y [c]) yes no) -+ // result: (LEnoov (TEQshiftRL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19415,12 +19415,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LE (TEQshiftRA x y [c]) yes no) -+ // result: (LEnoov (TEQshiftRA x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19439,12 +19439,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LE (TEQshiftLLreg x y z) yes no) -+ // result: (LEnoov (TEQshiftLLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19462,12 +19462,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LE (TEQshiftRLreg x y z) yes no) -+ // result: (LEnoov (TEQshiftRLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19485,12 +19485,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - // match: (LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LE (TEQshiftRAreg x y z) yes no) -+ // result: (LEnoov (TEQshiftRAreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -19508,7 +19508,7 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLE, v0) -+ b.resetWithControl(BlockARMLEnoov, v0) - return true - } - case BlockARMLEnoov: -@@ -20009,7 +20009,7 @@ func rewriteBlockARM(b *Block) bool { - } - // match: (LT (CMPconst [0] l:(AND x y)) yes no) - // cond: l.Uses==1 -- // result: (LT (TST x y) yes no) -+ // result: (LTnoov (TST x y) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20030,14 +20030,14 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - break - } - // match: (LT (CMPconst [0] l:(ANDconst [c] x)) yes no) - // cond: l.Uses==1 -- // result: (LT (TSTconst [c] x) yes no) -+ // result: (LTnoov (TSTconst [c] x) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20055,12 +20055,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) - v0.AuxInt = c - v0.AddArg(x) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LT (TSTshiftLL x y [c]) yes no) -+ // result: (LTnoov (TSTshiftLL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20079,12 +20079,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LT (TSTshiftRL x y [c]) yes no) -+ // result: (LTnoov (TSTshiftRL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20103,12 +20103,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LT (TSTshiftRA x y [c]) yes no) -+ // result: (LTnoov (TSTshiftRA x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20127,12 +20127,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LT (TSTshiftLLreg x y z) yes no) -+ // result: (LTnoov (TSTshiftLLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20150,12 +20150,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LT (TSTshiftRLreg x y z) yes no) -+ // result: (LTnoov (TSTshiftRLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20173,12 +20173,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LT (TSTshiftRAreg x y z) yes no) -+ // result: (LTnoov (TSTshiftRAreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20196,12 +20196,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(XOR x y)) yes no) - // cond: l.Uses==1 -- // result: (LT (TEQ x y) yes no) -+ // result: (LTnoov (TEQ x y) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20222,14 +20222,14 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - break - } - // match: (LT (CMPconst [0] l:(XORconst [c] x)) yes no) - // cond: l.Uses==1 -- // result: (LT (TEQconst [c] x) yes no) -+ // result: (LTnoov (TEQconst [c] x) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20247,12 +20247,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) - v0.AuxInt = c - v0.AddArg(x) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LT (TEQshiftLL x y [c]) yes no) -+ // result: (LTnoov (TEQshiftLL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20271,12 +20271,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LT (TEQshiftRL x y [c]) yes no) -+ // result: (LTnoov (TEQshiftRL x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20295,12 +20295,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) - // cond: l.Uses==1 -- // result: (LT (TEQshiftRA x y [c]) yes no) -+ // result: (LTnoov (TEQshiftRA x y [c]) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20319,12 +20319,12 @@ func rewriteBlockARM(b *Block) bool { - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) - v0.AuxInt = c - v0.AddArg2(x, y) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LT (TEQshiftLLreg x y z) yes no) -+ // result: (LTnoov (TEQshiftLLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20342,12 +20342,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LT (TEQshiftRLreg x y z) yes no) -+ // result: (LTnoov (TEQshiftRLreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20365,12 +20365,12 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - // match: (LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) - // cond: l.Uses==1 -- // result: (LT (TEQshiftRAreg x y z) yes no) -+ // result: (LTnoov (TEQshiftRAreg x y z) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if v_0.AuxInt != 0 { -@@ -20388,7 +20388,7 @@ func rewriteBlockARM(b *Block) bool { - } - v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) - v0.AddArg3(x, y, z) -- b.resetWithControl(BlockARMLT, v0) -+ b.resetWithControl(BlockARMLTnoov, v0) - return true - } - case BlockARMLTnoov: -diff --git a/test/fixedbugs/issue42876.go b/test/fixedbugs/issue42876.go -new file mode 100644 -index 0000000000..67cf4919ac ---- /dev/null -+++ b/test/fixedbugs/issue42876.go -@@ -0,0 +1,18 @@ -+// run -+ -+// Copyright 2020 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package main -+ -+var x = [4]int32{-0x7fffffff, 0x7fffffff, 2, 4} -+ -+func main() { -+ if x[0] > x[1] { -+ panic("fail 1") -+ } -+ if x[2]&x[3] < 0 { -+ panic("fail 2") // Fails here -+ } -+} --- -2.29.2 - diff --git a/go-patches/0014-runtime-make-write-into-function-pointer.patch b/go-patches/0014-runtime-make-write-into-function-pointer.patch deleted file mode 100644 index 1618f02e..00000000 --- a/go-patches/0014-runtime-make-write-into-function-pointer.patch +++ /dev/null @@ -1,32 +0,0 @@ -From d7b6f2bfcee5787d9055f5d7ec92c74e258e8fab Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" -Date: Thu, 3 Dec 2020 13:29:58 +0100 -Subject: [PATCH 14/14] runtime: make write into function pointer - -Change-Id: I77a32ff7e1494324e8cc38e792e007f86d32672d ---- - src/runtime/time_nofake.go | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/runtime/time_nofake.go b/src/runtime/time_nofake.go -index 1912a94e87..0564448b2e 100644 ---- a/src/runtime/time_nofake.go -+++ b/src/runtime/time_nofake.go -@@ -23,9 +23,14 @@ func walltime() (sec int64, nsec int32) { - return walltime1() - } - -+var overrideWrite func(fd uintptr, p unsafe.Pointer, n int32) int32 -+ - // write must be nosplit on Windows (see write1) - // - //go:nosplit - func write(fd uintptr, p unsafe.Pointer, n int32) int32 { -+ if overrideWrite != nil { -+ return overrideWrite(fd, noescape(p), n) -+ } - return write1(fd, p, n) - } --- -2.29.2 - -- cgit v1.2.3-59-g8ed1b